diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sat Sep 21 21:25:45 2002
+++ b/Makefile	Sat Sep 21 21:25:45 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 37
+SUBLEVEL = 38
 EXTRAVERSION =
 
 # *DOCUMENTATION*
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Sat Sep 21 21:25:45 2002
+++ b/arch/i386/kernel/vm86.c	Sat Sep 21 21:25:45 2002
@@ -261,7 +261,7 @@
 		"movl %0,%%esp\n\t"
 		"jmp resume_userspace"
 		: /* no outputs */
-		:"r" (&info->regs), "b" (tsk) : "ax");
+		:"r" (&info->regs), "b" (tsk->thread_info) : "ax");
 	/* we never return here */
 }
 
@@ -273,7 +273,7 @@
 	regs32->eax = retval;
 	__asm__ __volatile__("movl %0,%%esp\n\t"
 		"jmp resume_userspace"
-		: : "r" (regs32), "b" (current));
+		: : "r" (regs32), "b" (current_thread_info()));
 }
 
 static inline void set_IF(struct kernel_vm86_regs * regs)
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	Sat Sep 21 21:25:43 2002
+++ b/arch/ia64/Makefile	Sat Sep 21 21:25:45 2002
@@ -86,11 +86,10 @@
 
 HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o
 
-SUBDIRS := arch/$(ARCH)/tools arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib $(SUBDIRS)
-CORE_FILES := arch/$(ARCH)/kernel/kernel.o arch/$(ARCH)/mm/mm.o $(CORE_FILES)
-
-LIBS := $(TOPDIR)/arch/$(ARCH)/lib/lib.a $(LIBS) \
-	$(TOPDIR)/arch/$(ARCH)/lib/lib.a
+libs-y				+= arch/$(ARCH)/lib/
+core-y				+= arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
+drivers-$(CONFIG_PCI)		+= arch/$(ARCH)/pci/
+drivers-$(CONFIG_IA64_HP_ZX1)	+= arch/$(ARCH)/hp/common/ arch/$(ARCH)/hp/zx1/
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
@@ -102,30 +101,14 @@
 rawboot:
 	@$(MAKEBOOT) rawboot
 
-#
-# My boot writes directly to a specific disk partition, I doubt most
-# people will want to do that without changes..
-#
-msb my-special-boot:
-	@$(MAKEBOOT) msb
-
-bootimage:
-	@$(MAKEBOOT) bootimage
-
-srmboot:
-	@$(MAKEBOOT) srmboot
-
 archclean:
 	@$(MAKEBOOT) clean
 
 archmrproper:
 	@$(MAKE) -C arch/$(ARCH)/tools mrproper
 
-bootpfile:
-	@$(MAKEBOOT) bootpfile
-
 prepare: $(TOPDIR)/include/asm-ia64/offsets.h
 
 $(TOPDIR)/include/asm-ia64/offsets.h: include/asm include/linux/version.h \
 				      include/config/MARKER
-	@$(MAKE) -C arch/$(ARCH)/tools $@
\ No newline at end of file
+	@$(MAKE) -C arch/$(ARCH)/tools $@
diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in
--- a/arch/ia64/config.in	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/config.in	Sat Sep 21 21:25:48 2002
@@ -68,6 +68,7 @@
 then
 	bool '  Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
 	define_bool CONFIG_PM y
+	define_bool CONFIG_IOSAPIC y
 fi
 
 if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then
@@ -85,6 +86,31 @@
 fi
 
 define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /proc/kcore.
+
+define_int CONFIG_FORCE_MAX_ZONEORDER 18
+
+bool 'IA-64 Huge TLB Page Support' CONFIG_HUGETLB_PAGE
+
+if [ "$CONFIG_HUGETLB_PAGE" = "y" ]; then
+	if [ "$CONFIG_MCKINLEY" = "y" ]; then
+		choice '    IA-64 Huge TLB Page Size'				\
+		 	"4GB           CONFIG_HUGETLB_PAGE_SIZE_4GB		\
+		 	256MB          CONFIG_HUGETLB_PAGE_SIZE_256MB		\
+			64MB           CONFIG_HUGETLB_PAGE_SIZE_64MB		\
+			16MB           CONFIG_HUGETLB_PAGE_SIZE_16MB		\
+			4MB            CONFIG_HUGETLB_PAGE_SIZE_4MB		\
+			1MB            CONFIG_HUGETLB_PAGE_SIZE_1MB		\
+			256KB          CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB
+	else
+		choice '    IA-64 Huge TLB Page Size'				\
+		 	"256MB         CONFIG_HUGETLB_PAGE_SIZE_256MB		\
+			64MB           CONFIG_HUGETLB_PAGE_SIZE_64MB		\
+			16MB           CONFIG_HUGETLB_PAGE_SIZE_16MB		\
+			4MB            CONFIG_HUGETLB_PAGE_SIZE_4MB		\
+			1MB            CONFIG_HUGETLB_PAGE_SIZE_1MB		\
+			256KB          CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB
+	fi
+fi
 
 bool 'SMP support' CONFIG_SMP
 bool 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT
diff -Nru a/arch/ia64/hp/Makefile b/arch/ia64/hp/Makefile
--- a/arch/ia64/hp/Makefile	Sat Sep 21 21:25:46 2002
+++ b/arch/ia64/hp/Makefile	Sat Sep 21 21:25:46 2002
@@ -7,7 +7,6 @@
 
 subdir-$(CONFIG_IA64_GENERIC) += $(ALL_SUB_DIRS)
 subdir-$(CONFIG_IA64_HP_SIM) += sim
-subdir-$(CONFIG_IA64_HP_ZX1) += zx1 common
 
 SUB_DIRS := $(subdir-y)
 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
diff -Nru a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile
--- a/arch/ia64/hp/common/Makefile	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/hp/common/Makefile	Sat Sep 21 21:25:48 2002
@@ -5,8 +5,6 @@
 # Copyright (C) Alex Williamson (alex_williamson@hp.com)
 #
 
-O_TARGET := common.o
-
 export-objs := sba_iommu.o
 
 obj-y := sba_iommu.o
diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/hp/common/sba_iommu.c	Sat Sep 21 21:25:45 2002
@@ -39,9 +39,7 @@
 
 #define DRIVER_NAME "SBA"
 
-#ifndef CONFIG_IA64_HP_PROTO
 #define ALLOW_IOV_BYPASS
-#endif
 #define ENABLE_MARK_CLEAN
 /*
 ** The number of debug flags is a clue - this code is fragile.
@@ -740,6 +738,9 @@
 	unsigned long phys_addr = virt_to_phys(addr);
 #endif
 
+	if (!sba_list)
+		panic("sba_map_single: no SBA found!\n");
+
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -828,6 +829,9 @@
 	unsigned long flags; 
 	dma_addr_t offset;
 
+	if (!sba_list)
+		panic("sba_map_single: no SBA found!\n");
+
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -1094,6 +1098,9 @@
 	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents,
 		sba_sg_address(sglist), sba_sg_len(sglist));
 
+	if (!sba_list)
+		panic("sba_map_single: no SBA found!\n");
+
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -1183,6 +1190,9 @@
 	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n",
 		__FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist));
 
+	if (!sba_list)
+		panic("sba_map_single: no SBA found!\n");
+
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
@@ -1252,10 +1262,6 @@
 	** Firmware programs the maximum IOV space size into the imask reg
 	*/
 	iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1;
-#ifdef CONFIG_IA64_HP_PROTO
-	if (!iova_space_size)
-		iova_space_size = GB(1);
-#endif
 
 	/*
 	** iov_order is always based on a 1GB IOVA space since we want to
@@ -1484,66 +1490,65 @@
 #ifdef CONFIG_PROC_FS
 static int sba_proc_info(char *buf, char **start, off_t offset, int len)
 {
-	struct sba_device *sba_dev = sba_list;
-	struct ioc *ioc = &sba_dev->ioc[0];	/* FIXME: Multi-IOC support! */
-	int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
+	struct sba_device *sba_dev;
+	struct ioc *ioc;
+	int total_pages;
 	unsigned long i = 0, avg = 0, min, max;
 
-	sprintf(buf, "%s rev %d.%d\n",
-		"Hewlett Packard zx1 SBA",
-		((sba_dev->hw_rev >> 4) & 0xF),
-		(sba_dev->hw_rev & 0xF)
-		);
-	sprintf(buf, "%sIO PDIR size    : %d bytes (%d entries)\n",
-		buf,
-		(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
-		total_pages);
-
-	sprintf(buf, "%sIO PDIR entries : %ld free  %ld used (%d%%)\n", buf,
-		total_pages - ioc->used_pages, ioc->used_pages,
-		(int) (ioc->used_pages * 100 / total_pages));
-	
-	sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
-		buf, ioc->res_size, ioc->res_size << 3);   /* 8 bits per byte */
-
-	min = max = ioc->avg_search[0];
-	for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
-		avg += ioc->avg_search[i];
-		if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
-		if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
-	}
-	avg /= SBA_SEARCH_SAMPLE;
-	sprintf(buf, "%s  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
-		buf, min, avg, max);
-
-	sprintf(buf, "%spci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
-		buf, ioc->msingle_calls, ioc->msingle_pages,
-		(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+	for (sba_dev = sba_list; sba_dev; sba_dev = sba_dev->next) {
+		ioc = &sba_dev->ioc[0];	/* FIXME: Multi-IOC support! */
+		total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
+
+		sprintf(buf, "%s rev %d.%d\n", "Hewlett Packard zx1 SBA",
+			((sba_dev->hw_rev >> 4) & 0xF), (sba_dev->hw_rev & 0xF));
+		sprintf(buf, "%sIO PDIR size    : %d bytes (%d entries)\n", buf,
+			(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages);
+
+		sprintf(buf, "%sIO PDIR entries : %ld free  %ld used (%d%%)\n", buf,
+			total_pages - ioc->used_pages, ioc->used_pages,
+			(int) (ioc->used_pages * 100 / total_pages));
+
+		sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
+			buf, ioc->res_size, ioc->res_size << 3);   /* 8 bits per byte */
+
+		min = max = ioc->avg_search[0];
+		for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
+			avg += ioc->avg_search[i];
+			if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
+			if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
+		}
+		avg /= SBA_SEARCH_SAMPLE;
+		sprintf(buf, "%s  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+			buf, min, avg, max);
+
+		sprintf(buf, "%spci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
+			buf, ioc->msingle_calls, ioc->msingle_pages,
+			(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
 #ifdef ALLOW_IOV_BYPASS
-	sprintf(buf, "%spci_map_single(): %12ld bypasses\n",
-	        buf, ioc->msingle_bypass);
+		sprintf(buf, "%spci_map_single(): %12ld bypasses\n",
+			buf, ioc->msingle_bypass);
 #endif
 
-	sprintf(buf, "%spci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
-		buf, ioc->usingle_calls, ioc->usingle_pages,
-		(int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
+		sprintf(buf, "%spci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
+			buf, ioc->usingle_calls, ioc->usingle_pages,
+			(int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls));
 #ifdef ALLOW_IOV_BYPASS
-	sprintf(buf, "%spci_unmap_single: %12ld bypasses\n",
-	        buf, ioc->usingle_bypass);
+		sprintf(buf, "%spci_unmap_single: %12ld bypasses\n",
+			buf, ioc->usingle_bypass);
 #endif
 
-	sprintf(buf, "%spci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
-		buf, ioc->msg_calls, ioc->msg_pages,
-		(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
+		sprintf(buf, "%spci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
+			buf, ioc->msg_calls, ioc->msg_pages,
+			(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
 #ifdef ALLOW_IOV_BYPASS
-	sprintf(buf, "%spci_map_sg()    : %12ld bypasses\n",
-	        buf, ioc->msg_bypass);
+		sprintf(buf, "%spci_map_sg()    : %12ld bypasses\n",
+			buf, ioc->msg_bypass);
 #endif
 
-	sprintf(buf, "%spci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
-		buf, ioc->usg_calls, ioc->usg_pages,
-		(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
-
+		sprintf(buf, "%spci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
+			buf, ioc->usg_calls, ioc->usg_pages,
+			(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
+	}
 	return strlen(buf);
 }
 
@@ -1551,9 +1556,13 @@
 sba_resource_map(char *buf, char **start, off_t offset, int len)
 {
 	struct ioc *ioc = sba_list->ioc;	/* FIXME: Multi-IOC support! */
-	unsigned int *res_ptr = (unsigned int *)ioc->res_map;
+	unsigned int *res_ptr;
 	int i;
 
+	if (!ioc)
+		return 0;
+
+	res_ptr = (unsigned int *)ioc->res_map;
 	buf[0] = '\0';
 	for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) {
 		if ((i & 7) == 0)
@@ -1593,13 +1602,11 @@
 	}
 
 	func_id = READ_REG(hpa + SBA_FUNC_ID);
-
-	if (func_id == ZX1_FUNC_ID_VALUE) {
-		strcpy(sba_rev, "zx1");
-		func_offset = zx1_func_offsets;
-	} else {
+	if (func_id != ZX1_FUNC_ID_VALUE)
 		return;
-	}
+
+	strcpy(sba_rev, "zx1");
+	func_offset = zx1_func_offsets;
 
 	/* Read HW Rev First */
 	hw_rev = READ_REG(hpa + SBA_FCLASS) & 0xFFUL;
@@ -1625,10 +1632,8 @@
 	       device->slot_name, hpa);
 
 	if ((hw_rev & 0xFF) < 0x20) {
-		printk(KERN_INFO "%s WARNING rev 2.0 or greater will be required for IO MMU support in the future\n", DRIVER_NAME);
-#ifndef CONFIG_IA64_HP_PROTO
-		panic("%s: CONFIG_IA64_HP_PROTO MUST be enabled to support SBA rev less than 2.0", DRIVER_NAME);
-#endif
+		printk("%s: SBA rev less than 2.0 not supported", DRIVER_NAME);
+		return;
 	}
 
 	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
diff -Nru a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile
--- a/arch/ia64/hp/zx1/Makefile	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/hp/zx1/Makefile	Sat Sep 21 21:25:48 2002
@@ -1,11 +1,9 @@
 #
-# ia64/platform/hp/zx1/Makefile
+# ia64/hp/zx1/Makefile
 #
 # Copyright (C) 2002 Hewlett Packard
 # Copyright (C) Alex Williamson (alex_williamson@hp.com)
 #
-
-O_TARGET := zx1.o
 
 obj-y := hpzx1_misc.o
 obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o
diff -Nru a/arch/ia64/hp/zx1/hpzx1_misc.c b/arch/ia64/hp/zx1/hpzx1_misc.c
--- a/arch/ia64/hp/zx1/hpzx1_misc.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/hp/zx1/hpzx1_misc.c	Sat Sep 21 21:25:45 2002
@@ -25,68 +25,84 @@
 static int hpzx1_devices;
 
 struct fake_pci_dev {
+	struct fake_pci_dev *next;
+	struct pci_dev *pci_dev;
 	unsigned long csr_base;
 	unsigned long csr_size;
 	unsigned long mapped_csrs;	// ioremapped
 	int sizing;			// in middle of BAR sizing operation?
-};
+} *fake_pci_dev_list;
 
 static struct pci_ops *orig_pci_ops;
 
-#define HP_CFG_RD(sz, bits, name)						\
-static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value)	\
-{										\
-	struct fake_pci_dev *fake_dev;						\
-	if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata))			\
-		return orig_pci_ops->name(dev, where, value);			\
-										\
-	if (where == PCI_BASE_ADDRESS_0) {					\
-		if (fake_dev->sizing)						\
-			*value = ~(fake_dev->csr_size - 1);			\
-		else								\
-			*value = (fake_dev->csr_base &				\
-				    PCI_BASE_ADDRESS_MEM_MASK) |		\
-				PCI_BASE_ADDRESS_SPACE_MEMORY;			\
-		fake_dev->sizing = 0;						\
-		return PCIBIOS_SUCCESSFUL;					\
-	}									\
-	*value = read##sz(fake_dev->mapped_csrs + where);			\
-	if (where == PCI_COMMAND)						\
-		*value |= PCI_COMMAND_MEMORY; /* SBA omits this */		\
-	return PCIBIOS_SUCCESSFUL;						\
+struct fake_pci_dev *
+lookup_fake_dev (struct pci_bus *bus, unsigned int devfn)
+{
+	struct fake_pci_dev *fake_dev;
+
+	for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next)
+		if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn)
+			return fake_dev;
+	return NULL;
 }
 
-#define HP_CFG_WR(sz, bits, name)						\
-static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value)	\
-{										\
-	struct fake_pci_dev *fake_dev;						\
-										\
-	if (!(fake_dev = (struct fake_pci_dev *) dev->sysdata))			\
-		return orig_pci_ops->name(dev, where, value);			\
-										\
-	if (where == PCI_BASE_ADDRESS_0) {					\
-		if (value == (u##bits) ~0)					\
-			fake_dev->sizing = 1;					\
-		return PCIBIOS_SUCCESSFUL;					\
-	} else									\
-		write##sz(value, fake_dev->mapped_csrs + where);		\
-	return PCIBIOS_SUCCESSFUL;						\
+static int
+hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
+
+	if (!fake_dev)
+		return (*orig_pci_ops->read)(bus, devfn, where, size, value);
+
+	if (where == PCI_BASE_ADDRESS_0) {
+		if (fake_dev->sizing)
+			*value = ~(fake_dev->csr_size - 1);
+		else
+			*value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK)
+				  | PCI_BASE_ADDRESS_SPACE_MEMORY);
+		fake_dev->sizing = 0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+	switch (size) {
+	      case 1: *value = readb(fake_dev->mapped_csrs + where); break;
+	      case 2: *value = readw(fake_dev->mapped_csrs + where); break;
+	      case 4: *value = readl(fake_dev->mapped_csrs + where); break;
+	      default:
+		printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size);
+		break;
+	}
+	if (where == PCI_COMMAND)
+		*value |= PCI_COMMAND_MEMORY; /* SBA omits this */
+	return PCIBIOS_SUCCESSFUL;
 }
 
-HP_CFG_RD(b,  8, read_byte)
-HP_CFG_RD(w, 16, read_word)
-HP_CFG_RD(l, 32, read_dword)
-HP_CFG_WR(b,  8, write_byte)
-HP_CFG_WR(w, 16, write_word)
-HP_CFG_WR(l, 32, write_dword)
+static int
+hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn);
+
+	if (!fake_dev)
+		return (*orig_pci_ops->write)(bus, devfn, where, size, value);
+
+	if (where == PCI_BASE_ADDRESS_0) {
+		if (value == ((1UL << 8*size) - 1))
+			fake_dev->sizing = 1;
+		return PCIBIOS_SUCCESSFUL;
+	}
+	switch (size) {
+	      case 1: writeb(value, fake_dev->mapped_csrs + where); break;
+	      case 2: writew(value, fake_dev->mapped_csrs + where); break;
+	      case 4: writel(value, fake_dev->mapped_csrs + where); break;
+	      default:
+		printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
 
 static struct pci_ops hp_pci_conf = {
-	hp_cfg_readb,
-	hp_cfg_readw,
-	hp_cfg_readl,
-	hp_cfg_writeb,
-	hp_cfg_writew,
-	hp_cfg_writel,
+	.read =		hp_cfg_read,
+	.write =	hp_cfg_write
 };
 
 static void
@@ -143,6 +159,10 @@
 
 	bus->ops = &hp_pci_conf;	// replace pci ops for this bus
 
+	fake->pci_dev = dev;
+	fake->next = fake_pci_dev_list;
+	fake_pci_dev_list = fake;
+
 	memset(dev, 0, sizeof(*dev));
 	dev->bus = bus;
 	dev->sysdata = fake;
@@ -309,57 +329,20 @@
 	 * HWP0003: AGP LBA device
 	 */
 	acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);
-#ifdef CONFIG_IA64_HP_PROTO
-	if (hpzx1_devices) {
-#endif
 	acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL);
 	acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL);
-
-#ifdef CONFIG_IA64_HP_PROTO
-	}
-
-#define ZX1_FUNC_ID_VALUE    (PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP
-	/*
-	 * Early protos don't have bridges in the ACPI namespace, so
-	 * if we didn't find anything, add the things we know are
-	 * there.
-	 */
-	if (hpzx1_devices == 0) {
-		u64 hpa, csr_base;
-
-		csr_base = 0xfed00000UL;
-		hpa = (u64) ioremap(csr_base, 0x2000);
-		if (__raw_readl(hpa) == ZX1_FUNC_ID_VALUE) {
-			hpzx1_fake_pci_dev("HWP0001 SBA", 0, csr_base, 0x1000);
-			hpzx1_fake_pci_dev("HWP0001 IOC", 0, csr_base + 0x1000,
-					    0x1000);
-
-			csr_base = 0xfed24000UL;
-			iounmap(hpa);
-			hpa = (u64) ioremap(csr_base, 0x1000);
-			hpzx1_fake_pci_dev("HWP0003 AGP LBA", 0x40, csr_base,
-					    0x1000);
-		}
-		iounmap(hpa);
-	}
-#endif
 }
 
 extern void sba_init(void);
 
-void
-hpzx1_pci_fixup (int phase)
+static void
+hpzx1_init (void)
 {
-	iosapic_pci_fixup(phase);
-	switch (phase) {
-	      case 0:
-		/* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
-		MAX_DMA_ADDRESS = ~0UL;
-		break;
+	/* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */
+	MAX_DMA_ADDRESS = ~0UL;
 
-	      case 1:
-		hpzx1_acpi_dev_init();
-		sba_init();
-		break;
-	}
+	hpzx1_acpi_dev_init();
+	sba_init();
 }
+
+subsys_initcall(hpzx1_init);
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Sat Sep 21 21:25:46 2002
+++ b/arch/ia64/ia32/sys_ia32.c	Sat Sep 21 21:25:46 2002
@@ -2111,8 +2111,8 @@
 };
 
 struct ipc_kludge {
-	struct msgbuf *msgp;
-	long msgtyp;
+	u32 msgp;
+	s32 msgtyp;
 };
 
 #define SEMOP		 1
diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
--- a/arch/ia64/kernel/Makefile	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/Makefile	Sat Sep 21 21:25:45 2002
@@ -2,7 +2,6 @@
 # Makefile for the linux kernel.
 #
 
-O_TARGET	:= kernel.o
 EXTRA_TARGETS	:= head.o init_task.o
 
 export-objs := ia64_ksyms.o
@@ -10,12 +9,9 @@
 obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \
 	 machvec.o pal.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o	\
 	 signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o
-obj-$(CONFIG_IA64_GENERIC) += iosapic.o
-obj-$(CONFIG_IA64_HP_ZX1) += iosapic.o
-obj-$(CONFIG_IA64_DIG) += iosapic.o
+obj-$(CONFIG_IOSAPIC) += iosapic.o
 obj-$(CONFIG_IA64_PALINFO) += palinfo.o
 obj-$(CONFIG_EFI_VARS) += efivars.o
-obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SMP) += smp.o smpboot.o
 obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o
 obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/acpi.c	Sat Sep 21 21:25:45 2002
@@ -58,6 +58,8 @@
 
 unsigned char acpi_kbd_controller_present = 1;
 
+int acpi_disabled __initdata;	/* XXX this shouldn't be needed---we can't boot without ACPI! */
+
 const char *
 acpi_get_sysname (void)
 {
@@ -608,7 +610,7 @@
 	 * gets interrupts such as power and sleep buttons.  If it's not
 	 * on a Legacy interrupt, it needs to be setup.
 	 */
-	if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
+	if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1)
 		printk(KERN_ERR PREFIX "Can't find FADT\n");
 
 #ifdef CONFIG_SERIAL_8250_ACPI
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/efi.c	Sat Sep 21 21:25:45 2002
@@ -33,6 +33,15 @@
 
 #define EFI_DEBUG	0
 
+#ifdef CONFIG_HUGETLB_PAGE
+
+/* By default at total of 512MB is reserved huge pages. */
+#define HTLBZONE_SIZE_DEFAULT  0x20000000
+
+unsigned long htlbzone_pages = (HTLBZONE_SIZE_DEFAULT >> HPAGE_SHIFT);
+
+#endif
+
 extern efi_status_t efi_call_phys (void *, ...);
 
 struct efi efi;
@@ -399,6 +408,25 @@
 				++cp;
 		}
 	}
+#ifdef CONFIG_HUGETLB_PAGE
+	/* Just duplicating the above algo for lpzone start */
+	for (cp = saved_command_line; *cp; ) {
+		if (memcmp(cp, "lpmem=", 6) == 0) {
+			cp += 6;
+			htlbzone_pages = memparse(cp, &end);
+			htlbzone_pages = (htlbzone_pages >> HPAGE_SHIFT);
+			if (end != cp)
+				break;
+			cp = end;
+		} else {
+			while (*cp != ' ' && *cp)
+				++cp;
+			while (*cp == ' ')
+				++cp;
+		}
+	}
+	printk("Total HugeTLB_Page memory pages requested  0x%lx \n", htlbzone_pages);
+#endif
 	if (mem_limit != ~0UL)
 		printk("Ignoring memory above %luMB\n", mem_limit >> 20);
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/entry.S	Sat Sep 21 21:25:45 2002
@@ -90,15 +90,23 @@
 	br.ret.sptk.many rp
 END(ia64_execve)
 
+/*
+ * sys_clone2(u64 flags, u64 ustack_base, u64 ustack_size, u64 user_tid, u64 tls)
+ */
 GLOBAL_ENTRY(sys_clone2)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
-	alloc r16=ar.pfs,3,2,4,0
+	alloc r16=ar.pfs,5,2,5,0
 	DO_SAVE_SWITCH_STACK
+	adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
 	mov loc0=rp
 	mov loc1=r16				// save ar.pfs across do_fork
 	.body
 	mov out1=in1
 	mov out3=in2
+	tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
+	mov out4=in3				// valid only w/CLONE_SETTID and/or CLONE_CLEARTID
+	;;
+(p6)	st8 [r2]=in4				// store TLS in r13 (tp)
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
 	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
 	br.call.sptk.many rp=do_fork
@@ -115,15 +123,24 @@
 	br.ret.sptk.many rp
 END(sys_clone2)
 
+/*
+ * sys_clone(u64 flags, u64 ustack_base, u64 user_tid, u64 tls)
+ *	Deprecated.  Use sys_clone2() instead.
+ */
 GLOBAL_ENTRY(sys_clone)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
-	alloc r16=ar.pfs,2,2,4,0
+	alloc r16=ar.pfs,4,2,5,0
 	DO_SAVE_SWITCH_STACK
+	adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
 	mov loc0=rp
 	mov loc1=r16				// save ar.pfs across do_fork
 	.body
 	mov out1=in1
 	mov out3=16				// stacksize (compensates for 16-byte scratch area)
+	tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
+	mov out4=in2				// out4 = user_tid (optional)
+	;;
+(p6)	st8 [r2]=in3				// store TLS in r13 (tp)
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
 	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
 	br.call.sptk.many rp=do_fork
@@ -521,7 +538,7 @@
 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	/*
 	 * We need to call schedule_tail() to complete the scheduling process.
-	 * Called by ia64_switch_to after do_fork()->copy_thread().  r8 contains the
+	 * Called by ia64_switch_to() after do_fork()->copy_thread().  r8 contains the
 	 * address of the previously executing task.
 	 */
 	br.call.sptk.many rp=ia64_invoke_schedule_tail
@@ -872,7 +889,7 @@
 #endif /* __GNUC__ < 3 */
 
 	/*
-	 * Setup stack and call ia64_do_signal.  Note that pSys and pNonSys need to
+	 * Setup stack and call do_notify_resume_user().  Note that pSys and pNonSys need to
 	 * be set up by the caller.  We declare 8 input registers so the system call
 	 * args get preserved, in case we need to restart a system call.
 	 */
@@ -900,7 +917,7 @@
 	mov ar.unat=r9
 	mov ar.pfs=loc1
 	br.ret.sptk.many rp
-END(do_notify_resume_user)
+END(notify_resume_user)
 
 GLOBAL_ENTRY(sys_rt_sigsuspend)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
@@ -1224,10 +1241,10 @@
 	data8 sys_futex				// 1230
 	data8 sys_sched_setaffinity
 	data8 sys_sched_getaffinity
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall
-	data8 ia64_ni_syscall			// 1235
-	data8 ia64_ni_syscall
+	data8 sys_security
+	data8 sys_alloc_hugepages
+	data8 sys_free_hugepages		// 1235
+	data8 sys_exit_group
 	data8 ia64_ni_syscall
 	data8 sys_io_setup
 	data8 sys_io_destroy
diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
--- a/arch/ia64/kernel/gate.S	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/kernel/gate.S	Sat Sep 21 21:25:48 2002
@@ -2,7 +2,7 @@
  * This file contains the code that gets mapped at the upper end of each task's text
  * region.  For now, it contains the signal trampoline code only.
  *
- * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * Copyright (C) 1999-2002 Hewlett-Packard Co
  * 	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -135,7 +135,7 @@
 	;;
 	ld8 r8=[base0]				// restore (perhaps modified) CFM0, EC0, and CPL0
 	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
-(p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14 and r16)
+(p8)	br.cond.spnt restore_rbs		// yup -> (clobbers r14-r18, f6 & f7)
 	;;
 back_from_restore_rbs:
 	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
@@ -189,20 +189,69 @@
 	.spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
 	.body
 restore_rbs:
+	// On input:
+	//	r14 = bsp1 (bsp at the time of return from signal handler)
+	//	r15 = bsp0 (bsp at the time the signal occurred)
+	//
+	// Here, we need to calculate bspstore0, the value that ar.bspstore needs
+	// to be set to, based on bsp0 and the size of the dirty partition on
+	// the alternate stack (sc_loadrs >> 16).  This can be done with the
+	// following algorithm:
+	//
+	//  bspstore0 = rse_skip_regs(bsp0, -rse_num_regs(bsp1 - (loadrs >> 19), bsp1));
+	//
+	// This is what the code below does.
+	//
 	alloc r2=ar.pfs,0,0,0,0			// alloc null frame
 	adds r16=(LOADRS_OFF+SIGCONTEXT_OFF),sp
+	adds r18=(RNAT_OFF+SIGCONTEXT_OFF),sp
 	;;
-	ld8 r14=[r16]
-	adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
+	ld8 r17=[r16]
+	ld8 r16=[r18]			// get new rnat
+	extr.u r18=r15,3,6	// r18 <- rse_slot_num(bsp0)
 	;;
-	mov ar.rsc=r14				// put RSE into enforced lazy mode
-	ld8 r14=[r16]				// get new rnat
+	mov ar.rsc=r17			// put RSE into enforced lazy mode
+	shr.u r17=r17,16
 	;;
-	loadrs					// restore dirty partition
+	sub r14=r14,r17		// r14 (bspstore1) <- bsp1 - (sc_loadrs >> 16)
+	shr.u r17=r17,3		// r17 <- (sc_loadrs >> 19)
+	;;
+	loadrs			// restore dirty partition
+	extr.u r14=r14,3,6	// r14 <- rse_slot_num(bspstore1)
+	;;
+	add r14=r14,r17		// r14 <- rse_slot_num(bspstore1) + (sc_loadrs >> 19)
+	;;
+	shr.u r14=r14,6		// r14 <- (rse_slot_num(bspstore1) + (sc_loadrs >> 19))/0x40
+	;;
+	sub r14=r14,r17		// r14 <- -rse_num_regs(bspstore1, bsp1)
+	movl r17=0x8208208208208209
+	;;
+	add r18=r18,r14		// r18 (delta) <- rse_slot_num(bsp0) - rse_num_regs(bspstore1,bsp1)
+	setf.sig f7=r17
+	cmp.lt p7,p0=r14,r0	// p7 <- (r14 < 0)?
+	;;
+(p7)	adds r18=-62,r18	// delta -= 62
+	;;
+	setf.sig f6=r18
+	;;
+	xmpy.h f6=f6,f7
+	;;
+	getf.sig r17=f6
+	;;
+	add r17=r17,r18
+	shr r18=r18,63
+	;;
+	shr r17=r17,5
+	;;
+	sub r17=r17,r18		// r17 = delta/63
+	;;
+	add r17=r14,r17		// r17 <- delta/63 - rse_num_regs(bspstore1, bsp1)
+	;;
+	shladd r15=r17,3,r15	// r15 <- bsp0 + 8*(delta/63 - rse_num_regs(bspstore1, bsp1))
 	;;
 	mov ar.bspstore=r15			// switch back to old register backing store area
 	;;
-	mov ar.rnat=r14				// restore RNaT
+	mov ar.rnat=r16				// restore RNaT
 	mov ar.rsc=0xf				// (will be restored later on from sc_ar_rsc)
 	// invala not necessary as that will happen when returning to user-mode
 	br.cond.sptk back_from_restore_rbs
diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
--- a/arch/ia64/kernel/head.S	Sat Sep 21 21:25:46 2002
+++ b/arch/ia64/kernel/head.S	Sat Sep 21 21:25:46 2002
@@ -13,6 +13,8 @@
  * Copyright (C) 1999 Intel Corp.
  * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@intel.com>
  * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
+ * Copyright (C) 2002 Fenghua Yu <fenghua.yu@intel.com>
+ *   -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
  */
 
 #include <linux/config.h>
@@ -260,302 +262,297 @@
 END(ia64_load_debug_regs)
 
 GLOBAL_ENTRY(__ia64_save_fpu)
-	alloc r2=ar.pfs,1,0,0,0
-	adds r3=16,in0
+	alloc r2=ar.pfs,1,4,0,0
+	adds loc0=96*16-16,in0
+	adds loc1=96*16-16-128,in0
 	;;
-	stf.spill.nta [in0]=f32,32
-	stf.spill.nta [ r3]=f33,32
+	stf.spill.nta [loc0]=f127,-256
+	stf.spill.nta [loc1]=f119,-256
 	;;
-	stf.spill.nta [in0]=f34,32
-	stf.spill.nta [ r3]=f35,32
+	stf.spill.nta [loc0]=f111,-256
+	stf.spill.nta [loc1]=f103,-256
 	;;
-	stf.spill.nta [in0]=f36,32
-	stf.spill.nta [ r3]=f37,32
+	stf.spill.nta [loc0]=f95,-256
+	stf.spill.nta [loc1]=f87,-256
 	;;
-	stf.spill.nta [in0]=f38,32
-	stf.spill.nta [ r3]=f39,32
+	stf.spill.nta [loc0]=f79,-256
+	stf.spill.nta [loc1]=f71,-256
 	;;
-	stf.spill.nta [in0]=f40,32
-	stf.spill.nta [ r3]=f41,32
+	stf.spill.nta [loc0]=f63,-256
+	stf.spill.nta [loc1]=f55,-256
+	adds loc2=96*16-32,in0
 	;;
-	stf.spill.nta [in0]=f42,32
-	stf.spill.nta [ r3]=f43,32
+	stf.spill.nta [loc0]=f47,-256
+	stf.spill.nta [loc1]=f39,-256
+	adds loc3=96*16-32-128,in0
 	;;
-	stf.spill.nta [in0]=f44,32
-	stf.spill.nta [ r3]=f45,32
+	stf.spill.nta [loc2]=f126,-256
+	stf.spill.nta [loc3]=f118,-256
 	;;
-	stf.spill.nta [in0]=f46,32
-	stf.spill.nta [ r3]=f47,32
+	stf.spill.nta [loc2]=f110,-256
+	stf.spill.nta [loc3]=f102,-256
 	;;
-	stf.spill.nta [in0]=f48,32
-	stf.spill.nta [ r3]=f49,32
+	stf.spill.nta [loc2]=f94,-256
+	stf.spill.nta [loc3]=f86,-256
 	;;
-	stf.spill.nta [in0]=f50,32
-	stf.spill.nta [ r3]=f51,32
+	stf.spill.nta [loc2]=f78,-256
+	stf.spill.nta [loc3]=f70,-256
 	;;
-	stf.spill.nta [in0]=f52,32
-	stf.spill.nta [ r3]=f53,32
+	stf.spill.nta [loc2]=f62,-256
+	stf.spill.nta [loc3]=f54,-256
+	adds loc0=96*16-48,in0
 	;;
-	stf.spill.nta [in0]=f54,32
-	stf.spill.nta [ r3]=f55,32
+	stf.spill.nta [loc2]=f46,-256
+	stf.spill.nta [loc3]=f38,-256
+	adds loc1=96*16-48-128,in0
 	;;
-	stf.spill.nta [in0]=f56,32
-	stf.spill.nta [ r3]=f57,32
+	stf.spill.nta [loc0]=f125,-256
+	stf.spill.nta [loc1]=f117,-256
 	;;
-	stf.spill.nta [in0]=f58,32
-	stf.spill.nta [ r3]=f59,32
+	stf.spill.nta [loc0]=f109,-256
+	stf.spill.nta [loc1]=f101,-256
 	;;
-	stf.spill.nta [in0]=f60,32
-	stf.spill.nta [ r3]=f61,32
+	stf.spill.nta [loc0]=f93,-256
+	stf.spill.nta [loc1]=f85,-256
 	;;
-	stf.spill.nta [in0]=f62,32
-	stf.spill.nta [ r3]=f63,32
+	stf.spill.nta [loc0]=f77,-256
+	stf.spill.nta [loc1]=f69,-256
 	;;
-	stf.spill.nta [in0]=f64,32
-	stf.spill.nta [ r3]=f65,32
+	stf.spill.nta [loc0]=f61,-256
+	stf.spill.nta [loc1]=f53,-256
+	adds loc2=96*16-64,in0
 	;;
-	stf.spill.nta [in0]=f66,32
-	stf.spill.nta [ r3]=f67,32
+	stf.spill.nta [loc0]=f45,-256
+	stf.spill.nta [loc1]=f37,-256
+	adds loc3=96*16-64-128,in0
 	;;
-	stf.spill.nta [in0]=f68,32
-	stf.spill.nta [ r3]=f69,32
+	stf.spill.nta [loc2]=f124,-256
+	stf.spill.nta [loc3]=f116,-256
 	;;
-	stf.spill.nta [in0]=f70,32
-	stf.spill.nta [ r3]=f71,32
+	stf.spill.nta [loc2]=f108,-256
+	stf.spill.nta [loc3]=f100,-256
 	;;
-	stf.spill.nta [in0]=f72,32
-	stf.spill.nta [ r3]=f73,32
+	stf.spill.nta [loc2]=f92,-256
+	stf.spill.nta [loc3]=f84,-256
 	;;
-	stf.spill.nta [in0]=f74,32
-	stf.spill.nta [ r3]=f75,32
+	stf.spill.nta [loc2]=f76,-256
+	stf.spill.nta [loc3]=f68,-256
 	;;
-	stf.spill.nta [in0]=f76,32
-	stf.spill.nta [ r3]=f77,32
+	stf.spill.nta [loc2]=f60,-256
+	stf.spill.nta [loc3]=f52,-256
+	adds loc0=96*16-80,in0
 	;;
-	stf.spill.nta [in0]=f78,32
-	stf.spill.nta [ r3]=f79,32
+	stf.spill.nta [loc2]=f44,-256
+	stf.spill.nta [loc3]=f36,-256
+	adds loc1=96*16-80-128,in0
 	;;
-	stf.spill.nta [in0]=f80,32
-	stf.spill.nta [ r3]=f81,32
+	stf.spill.nta [loc0]=f123,-256
+	stf.spill.nta [loc1]=f115,-256
 	;;
-	stf.spill.nta [in0]=f82,32
-	stf.spill.nta [ r3]=f83,32
+	stf.spill.nta [loc0]=f107,-256
+	stf.spill.nta [loc1]=f99,-256
 	;;
-	stf.spill.nta [in0]=f84,32
-	stf.spill.nta [ r3]=f85,32
+	stf.spill.nta [loc0]=f91,-256
+	stf.spill.nta [loc1]=f83,-256
 	;;
-	stf.spill.nta [in0]=f86,32
-	stf.spill.nta [ r3]=f87,32
+	stf.spill.nta [loc0]=f75,-256
+	stf.spill.nta [loc1]=f67,-256
 	;;
-	stf.spill.nta [in0]=f88,32
-	stf.spill.nta [ r3]=f89,32
+	stf.spill.nta [loc0]=f59,-256
+	stf.spill.nta [loc1]=f51,-256
+	adds loc2=96*16-96,in0
 	;;
-	stf.spill.nta [in0]=f90,32
-	stf.spill.nta [ r3]=f91,32
+	stf.spill.nta [loc0]=f43,-256
+	stf.spill.nta [loc1]=f35,-256
+	adds loc3=96*16-96-128,in0
 	;;
-	stf.spill.nta [in0]=f92,32
-	stf.spill.nta [ r3]=f93,32
+	stf.spill.nta [loc2]=f122,-256
+	stf.spill.nta [loc3]=f114,-256
 	;;
-	stf.spill.nta [in0]=f94,32
-	stf.spill.nta [ r3]=f95,32
+	stf.spill.nta [loc2]=f106,-256
+	stf.spill.nta [loc3]=f98,-256
 	;;
-	stf.spill.nta [in0]=f96,32
-	stf.spill.nta [ r3]=f97,32
+	stf.spill.nta [loc2]=f90,-256
+	stf.spill.nta [loc3]=f82,-256
 	;;
-	stf.spill.nta [in0]=f98,32
-	stf.spill.nta [ r3]=f99,32
+	stf.spill.nta [loc2]=f74,-256
+	stf.spill.nta [loc3]=f66,-256
 	;;
-	stf.spill.nta [in0]=f100,32
-	stf.spill.nta [ r3]=f101,32
+	stf.spill.nta [loc2]=f58,-256
+	stf.spill.nta [loc3]=f50,-256
+	adds loc0=96*16-112,in0
 	;;
-	stf.spill.nta [in0]=f102,32
-	stf.spill.nta [ r3]=f103,32
+	stf.spill.nta [loc2]=f42,-256
+	stf.spill.nta [loc3]=f34,-256
+	adds loc1=96*16-112-128,in0
 	;;
-	stf.spill.nta [in0]=f104,32
-	stf.spill.nta [ r3]=f105,32
+	stf.spill.nta [loc0]=f121,-256
+	stf.spill.nta [loc1]=f113,-256
 	;;
-	stf.spill.nta [in0]=f106,32
-	stf.spill.nta [ r3]=f107,32
+	stf.spill.nta [loc0]=f105,-256
+	stf.spill.nta [loc1]=f97,-256
 	;;
-	stf.spill.nta [in0]=f108,32
-	stf.spill.nta [ r3]=f109,32
+	stf.spill.nta [loc0]=f89,-256
+	stf.spill.nta [loc1]=f81,-256
 	;;
-	stf.spill.nta [in0]=f110,32
-	stf.spill.nta [ r3]=f111,32
+	stf.spill.nta [loc0]=f73,-256
+	stf.spill.nta [loc1]=f65,-256
 	;;
-	stf.spill.nta [in0]=f112,32
-	stf.spill.nta [ r3]=f113,32
+	stf.spill.nta [loc0]=f57,-256
+	stf.spill.nta [loc1]=f49,-256
+	adds loc2=96*16-128,in0
 	;;
-	stf.spill.nta [in0]=f114,32
-	stf.spill.nta [ r3]=f115,32
+	stf.spill.nta [loc0]=f41,-256
+	stf.spill.nta [loc1]=f33,-256
+	adds loc3=96*16-128-128,in0
 	;;
-	stf.spill.nta [in0]=f116,32
-	stf.spill.nta [ r3]=f117,32
+	stf.spill.nta [loc2]=f120,-256
+	stf.spill.nta [loc3]=f112,-256
 	;;
-	stf.spill.nta [in0]=f118,32
-	stf.spill.nta [ r3]=f119,32
+	stf.spill.nta [loc2]=f104,-256
+	stf.spill.nta [loc3]=f96,-256
 	;;
-	stf.spill.nta [in0]=f120,32
-	stf.spill.nta [ r3]=f121,32
+	stf.spill.nta [loc2]=f88,-256
+	stf.spill.nta [loc3]=f80,-256
 	;;
-	stf.spill.nta [in0]=f122,32
-	stf.spill.nta [ r3]=f123,32
+	stf.spill.nta [loc2]=f72,-256
+	stf.spill.nta [loc3]=f64,-256
 	;;
-	stf.spill.nta [in0]=f124,32
-	stf.spill.nta [ r3]=f125,32
+	stf.spill.nta [loc2]=f56,-256
+	stf.spill.nta [loc3]=f48,-256
 	;;
-	stf.spill.nta [in0]=f126,32
-	stf.spill.nta [ r3]=f127,32
+	stf.spill.nta [loc2]=f40
+	stf.spill.nta [loc3]=f32
 	br.ret.sptk.many rp
 END(__ia64_save_fpu)
 
 GLOBAL_ENTRY(__ia64_load_fpu)
-	alloc r2=ar.pfs,1,0,0,0
-	adds r3=16,in0
-	;;
-	ldf.fill.nta f32=[in0],32
-	ldf.fill.nta f33=[ r3],32
-	;;
-	ldf.fill.nta f34=[in0],32
-	ldf.fill.nta f35=[ r3],32
-	;;
-	ldf.fill.nta f36=[in0],32
-	ldf.fill.nta f37=[ r3],32
-	;;
-	ldf.fill.nta f38=[in0],32
-	ldf.fill.nta f39=[ r3],32
-	;;
-	ldf.fill.nta f40=[in0],32
-	ldf.fill.nta f41=[ r3],32
-	;;
-	ldf.fill.nta f42=[in0],32
-	ldf.fill.nta f43=[ r3],32
-	;;
-	ldf.fill.nta f44=[in0],32
-	ldf.fill.nta f45=[ r3],32
-	;;
-	ldf.fill.nta f46=[in0],32
-	ldf.fill.nta f47=[ r3],32
-	;;
-	ldf.fill.nta f48=[in0],32
-	ldf.fill.nta f49=[ r3],32
-	;;
-	ldf.fill.nta f50=[in0],32
-	ldf.fill.nta f51=[ r3],32
-	;;
-	ldf.fill.nta f52=[in0],32
-	ldf.fill.nta f53=[ r3],32
-	;;
-	ldf.fill.nta f54=[in0],32
-	ldf.fill.nta f55=[ r3],32
-	;;
-	ldf.fill.nta f56=[in0],32
-	ldf.fill.nta f57=[ r3],32
-	;;
-	ldf.fill.nta f58=[in0],32
-	ldf.fill.nta f59=[ r3],32
-	;;
-	ldf.fill.nta f60=[in0],32
-	ldf.fill.nta f61=[ r3],32
-	;;
-	ldf.fill.nta f62=[in0],32
-	ldf.fill.nta f63=[ r3],32
-	;;
-	ldf.fill.nta f64=[in0],32
-	ldf.fill.nta f65=[ r3],32
-	;;
-	ldf.fill.nta f66=[in0],32
-	ldf.fill.nta f67=[ r3],32
-	;;
-	ldf.fill.nta f68=[in0],32
-	ldf.fill.nta f69=[ r3],32
-	;;
-	ldf.fill.nta f70=[in0],32
-	ldf.fill.nta f71=[ r3],32
-	;;
-	ldf.fill.nta f72=[in0],32
-	ldf.fill.nta f73=[ r3],32
-	;;
-	ldf.fill.nta f74=[in0],32
-	ldf.fill.nta f75=[ r3],32
-	;;
-	ldf.fill.nta f76=[in0],32
-	ldf.fill.nta f77=[ r3],32
-	;;
-	ldf.fill.nta f78=[in0],32
-	ldf.fill.nta f79=[ r3],32
-	;;
-	ldf.fill.nta f80=[in0],32
-	ldf.fill.nta f81=[ r3],32
-	;;
-	ldf.fill.nta f82=[in0],32
-	ldf.fill.nta f83=[ r3],32
-	;;
-	ldf.fill.nta f84=[in0],32
-	ldf.fill.nta f85=[ r3],32
-	;;
-	ldf.fill.nta f86=[in0],32
-	ldf.fill.nta f87=[ r3],32
-	;;
-	ldf.fill.nta f88=[in0],32
-	ldf.fill.nta f89=[ r3],32
-	;;
-	ldf.fill.nta f90=[in0],32
-	ldf.fill.nta f91=[ r3],32
-	;;
-	ldf.fill.nta f92=[in0],32
-	ldf.fill.nta f93=[ r3],32
-	;;
-	ldf.fill.nta f94=[in0],32
-	ldf.fill.nta f95=[ r3],32
-	;;
-	ldf.fill.nta f96=[in0],32
-	ldf.fill.nta f97=[ r3],32
-	;;
-	ldf.fill.nta f98=[in0],32
-	ldf.fill.nta f99=[ r3],32
-	;;
-	ldf.fill.nta f100=[in0],32
-	ldf.fill.nta f101=[ r3],32
-	;;
-	ldf.fill.nta f102=[in0],32
-	ldf.fill.nta f103=[ r3],32
-	;;
-	ldf.fill.nta f104=[in0],32
-	ldf.fill.nta f105=[ r3],32
-	;;
-	ldf.fill.nta f106=[in0],32
-	ldf.fill.nta f107=[ r3],32
-	;;
-	ldf.fill.nta f108=[in0],32
-	ldf.fill.nta f109=[ r3],32
-	;;
-	ldf.fill.nta f110=[in0],32
-	ldf.fill.nta f111=[ r3],32
-	;;
-	ldf.fill.nta f112=[in0],32
-	ldf.fill.nta f113=[ r3],32
-	;;
-	ldf.fill.nta f114=[in0],32
-	ldf.fill.nta f115=[ r3],32
-	;;
-	ldf.fill.nta f116=[in0],32
-	ldf.fill.nta f117=[ r3],32
-	;;
-	ldf.fill.nta f118=[in0],32
-	ldf.fill.nta f119=[ r3],32
-	;;
-	ldf.fill.nta f120=[in0],32
-	ldf.fill.nta f121=[ r3],32
-	;;
-	ldf.fill.nta f122=[in0],32
-	ldf.fill.nta f123=[ r3],32
-	;;
-	ldf.fill.nta f124=[in0],32
-	ldf.fill.nta f125=[ r3],32
-	;;
-	ldf.fill.nta f126=[in0],32
-	ldf.fill.nta f127=[ r3],32
+	alloc r2=ar.pfs,1,2,0,0
+	adds r3=128,in0
+	adds r14=256,in0
+	adds r15=384,in0
+	mov loc0=512
+	mov loc1=-1024+16
+	;;
+	ldf.fill.nta f32=[in0],loc0
+	ldf.fill.nta f40=[ r3],loc0
+	ldf.fill.nta f48=[r14],loc0
+	ldf.fill.nta f56=[r15],loc0
+	;;
+	ldf.fill.nta f64=[in0],loc0
+	ldf.fill.nta f72=[ r3],loc0
+	ldf.fill.nta f80=[r14],loc0
+	ldf.fill.nta f88=[r15],loc0
+	;;
+	ldf.fill.nta f96=[in0],loc1
+	ldf.fill.nta f104=[ r3],loc1
+	ldf.fill.nta f112=[r14],loc1
+	ldf.fill.nta f120=[r15],loc1
+	;;
+	ldf.fill.nta f33=[in0],loc0
+	ldf.fill.nta f41=[ r3],loc0
+	ldf.fill.nta f49=[r14],loc0
+	ldf.fill.nta f57=[r15],loc0
+	;;
+	ldf.fill.nta f65=[in0],loc0
+	ldf.fill.nta f73=[ r3],loc0
+	ldf.fill.nta f81=[r14],loc0
+	ldf.fill.nta f89=[r15],loc0
+	;;
+	ldf.fill.nta f97=[in0],loc1
+	ldf.fill.nta f105=[ r3],loc1
+	ldf.fill.nta f113=[r14],loc1
+	ldf.fill.nta f121=[r15],loc1
+	;;
+	ldf.fill.nta f34=[in0],loc0
+	ldf.fill.nta f42=[ r3],loc0
+	ldf.fill.nta f50=[r14],loc0
+	ldf.fill.nta f58=[r15],loc0
+	;;
+	ldf.fill.nta f66=[in0],loc0
+	ldf.fill.nta f74=[ r3],loc0
+	ldf.fill.nta f82=[r14],loc0
+	ldf.fill.nta f90=[r15],loc0
+	;;
+	ldf.fill.nta f98=[in0],loc1
+	ldf.fill.nta f106=[ r3],loc1
+	ldf.fill.nta f114=[r14],loc1
+	ldf.fill.nta f122=[r15],loc1
+	;;
+	ldf.fill.nta f35=[in0],loc0
+	ldf.fill.nta f43=[ r3],loc0
+	ldf.fill.nta f51=[r14],loc0
+	ldf.fill.nta f59=[r15],loc0
+	;;
+	ldf.fill.nta f67=[in0],loc0
+	ldf.fill.nta f75=[ r3],loc0
+	ldf.fill.nta f83=[r14],loc0
+	ldf.fill.nta f91=[r15],loc0
+	;;
+	ldf.fill.nta f99=[in0],loc1
+	ldf.fill.nta f107=[ r3],loc1
+	ldf.fill.nta f115=[r14],loc1
+	ldf.fill.nta f123=[r15],loc1
+	;;
+	ldf.fill.nta f36=[in0],loc0
+	ldf.fill.nta f44=[ r3],loc0
+	ldf.fill.nta f52=[r14],loc0
+	ldf.fill.nta f60=[r15],loc0
+	;;
+	ldf.fill.nta f68=[in0],loc0
+	ldf.fill.nta f76=[ r3],loc0
+	ldf.fill.nta f84=[r14],loc0
+	ldf.fill.nta f92=[r15],loc0
+	;;
+	ldf.fill.nta f100=[in0],loc1
+	ldf.fill.nta f108=[ r3],loc1
+	ldf.fill.nta f116=[r14],loc1
+	ldf.fill.nta f124=[r15],loc1
+	;;
+	ldf.fill.nta f37=[in0],loc0
+	ldf.fill.nta f45=[ r3],loc0
+	ldf.fill.nta f53=[r14],loc0
+	ldf.fill.nta f61=[r15],loc0
+	;;
+	ldf.fill.nta f69=[in0],loc0
+	ldf.fill.nta f77=[ r3],loc0
+	ldf.fill.nta f85=[r14],loc0
+	ldf.fill.nta f93=[r15],loc0
+	;;
+	ldf.fill.nta f101=[in0],loc1
+	ldf.fill.nta f109=[ r3],loc1
+	ldf.fill.nta f117=[r14],loc1
+	ldf.fill.nta f125=[r15],loc1
+	;;
+	ldf.fill.nta f38 =[in0],loc0
+	ldf.fill.nta f46 =[ r3],loc0
+	ldf.fill.nta f54 =[r14],loc0
+	ldf.fill.nta f62 =[r15],loc0
+	;;
+	ldf.fill.nta f70 =[in0],loc0
+	ldf.fill.nta f78 =[ r3],loc0
+	ldf.fill.nta f86 =[r14],loc0
+	ldf.fill.nta f94 =[r15],loc0
+	;;
+	ldf.fill.nta f102=[in0],loc1
+	ldf.fill.nta f110=[ r3],loc1
+	ldf.fill.nta f118=[r14],loc1
+	ldf.fill.nta f126=[r15],loc1
+	;;
+	ldf.fill.nta f39 =[in0],loc0
+	ldf.fill.nta f47 =[ r3],loc0
+	ldf.fill.nta f55 =[r14],loc0
+	ldf.fill.nta f63 =[r15],loc0
+	;;
+	ldf.fill.nta f71 =[in0],loc0
+	ldf.fill.nta f79 =[ r3],loc0
+	ldf.fill.nta f87 =[r14],loc0
+	ldf.fill.nta f95 =[r15],loc0
+	;;
+	ldf.fill.nta f103=[in0]
+	ldf.fill.nta f111=[ r3]
+	ldf.fill.nta f119=[r14]
+	ldf.fill.nta f127=[r15]
 	br.ret.sptk.many rp
 END(__ia64_load_fpu)
 
diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
--- a/arch/ia64/kernel/ia64_ksyms.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/ia64_ksyms.c	Sat Sep 21 21:25:45 2002
@@ -127,6 +127,8 @@
 EXPORT_SYMBOL(ia64_pal_call_phys_static);
 EXPORT_SYMBOL(ia64_pal_call_stacked);
 EXPORT_SYMBOL(ia64_pal_call_static);
+EXPORT_SYMBOL(ia64_load_scratch_fpregs);
+EXPORT_SYMBOL(ia64_save_scratch_fpregs);
 
 extern struct efi efi;
 EXPORT_SYMBOL(efi);
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/kernel/init_task.c	Sat Sep 21 21:25:48 2002
@@ -16,7 +16,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/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/iosapic.c	Sat Sep 21 21:25:45 2002
@@ -27,8 +27,8 @@
  * 02/04/30	J.I. Lee	bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping
  *				error
  * 02/07/29	T. Kochi	Allocate interrupt vectors dynamically
- * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system interrupt, vector,
- *				etc.)
+ * 02/08/04	T. Kochi	Cleaned up terminology (irq, global system interrupt, vector, etc.)
+ * 02/09/20	D. Mosberger	Simplified by taking advantage of ACPI's pci_irq code.
  */
 /*
  * Here is what the interrupt logic between a PCI device and the kernel looks like:
@@ -51,7 +51,7 @@
  *     architecture-independent interrupt handling mechanism in Linux.  As an
  *     IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number
  *     mapping.  On smaller systems, we use one-to-one mapping between IA-64 vector and
- *     IRQ.  A platform can implemnent platform_irq_to_vector(irq) and
+ *     IRQ.  A platform can implement platform_irq_to_vector(irq) and
  *     platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
  *     Please see also include/asm-ia64/hw_irq.h for those APIs.
  *
@@ -65,14 +65,15 @@
  */
 #include <linux/config.h>
 
-#include <linux/kernel.h>
+#include <linux/acpi.h>
 #include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
-#include <linux/irq.h>
-#include <linux/acpi.h>
 
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
@@ -95,13 +96,6 @@
 
 static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
 
-/* PCI pin to GSI routing information.  This info typically comes from ACPI. */
-
-static struct {
-	int num_routes;
-	struct pci_vector_struct *route;
-} pci_irq;
-
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
 
 static struct iosapic_intr_info {
@@ -146,11 +140,11 @@
 int
 gsi_to_vector (unsigned int gsi)
 {
-	int vector;
+	struct iosapic_intr_info *info;
 
-	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-		if (iosapic_intr_info[vector].gsi_base + iosapic_intr_info[vector].rte_index == gsi)
-			return vector;
+	for (info = iosapic_intr_info; info < iosapic_intr_info + IA64_NUM_VECTORS; ++info)
+		if (info->gsi_base + info->rte_index == gsi)
+			return info - iosapic_intr_info;
 	return -1;
 }
 
@@ -163,7 +157,7 @@
 	int rte_index;
 	char redir;
 
-	DBG(KERN_DEBUG "%s: routing vector %d to %x\n", __FUNCTION__, vector, dest);
+	DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest);
 
 	rte_index = iosapic_intr_info[vector].rte_index;
 	if (rte_index < 0)
@@ -584,7 +578,8 @@
 	index = find_iosapic(gsi);
 
 	if (index < 0) {
-		printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi);
+		printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n",
+		       isa_irq, gsi);
 		return;
 	}
 
@@ -604,75 +599,6 @@
 	set_rte(vector, dest);
 }
 
-/*
- * Map PCI pin to the corresponding GSI.
- * If no such mapping exists, return -1.
- */
-static int
-pci_pin_to_gsi (int bus, int slot, int pci_pin, unsigned int *gsi)
-{
-	struct pci_vector_struct *r;
-
-	for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r)
-		if (r->bus == bus &&
-		    (r->pci_id >> 16) == slot && r->pin == pci_pin) {
-			*gsi = r->irq;
-			return 0;
-		}
-
-	return -1;
-}
-
-/*
- * Map PCI pin to the corresponding IA-64 interrupt vector.  If no such mapping exists,
- * try to allocate a new vector.  If it fails, return -1.
- */
-static int
-pci_pin_to_vector (int bus, int slot, int pci_pin)
-{
-	int index, vector;
-	int gsi_base, pcat_compat;
-	char *addr;
-	unsigned int gsi;
-
-	if (pci_pin_to_gsi(bus, slot, pci_pin, &gsi) < 0) {
-		printk("PCI: no interrupt route for %02x:%02x pin %c\n", bus, slot, 'A' + pci_pin);
-		return -1;
-	}
-
-	vector = gsi_to_vector(gsi);
-
-	if (vector < 0) {
-		/* we should allocate a vector for this interrupt line */
-
-		index = find_iosapic(gsi);
-
-		if (index < 0) {
-			printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi);
-			return -1;
-		}
-
-		addr = iosapic_lists[index].addr;
-		gsi_base = iosapic_lists[index].gsi_base;
-		pcat_compat = iosapic_lists[index].pcat_compat;
-
-		if (pcat_compat && (gsi < 16))
-			vector = isa_irq_to_vector(gsi);
-		else {
-			/* new GSI; allocate a vector for it */
-			vector = ia64_alloc_vector();
-		}
-
-		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-			      0, 0, gsi_base, addr);
-
-		DBG("PCI: (%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n",
-		    bus, slot, 'A' + pci_pin, gsi, vector);
-	}
-
-	return vector;
-}
-
 void __devinit
 iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
 {
@@ -713,7 +639,7 @@
 	iosapic_lists[num_iosapic].num_rte = num_rte;
 	num_iosapic++;
 
-	printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
+	printk(KERN_INFO"  IOSAPIC v%x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
 	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
 
 	if ((gsi_base == 0) && pcat_compat) {
@@ -740,122 +666,93 @@
 	}
 }
 
-
-/*
- * Set allocated interrupt vector to dev->irq and
- * program IOSAPIC to deliver interrupts
- */
-void
-iosapic_fixup_pci_interrupt (struct pci_dev *dev)
+static void
+fixup_vector (int vector, unsigned int gsi, const char *pci_id)
 {
-	unsigned char pci_pin;
-	int vector;
-	unsigned int dest;
-	struct hw_interrupt_type *irq_type;
+	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
 	irq_desc_t *idesc;
+	unsigned int dest;
 
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pci_pin);
-	if (pci_pin) {
-		pci_pin--; /* interrupt pins are numberd starting from 1 */
-
-		vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pci_pin);
-
-		if (vector < 0 && dev->bus->parent) {
-			/* go back to the bridge */
-			struct pci_dev *bridge = dev->bus->self;
-
-			if (bridge) {
-				/* allow for multiple bridges on an adapter */
-				do {
-					/* do the bridge swizzle... */
-					pci_pin = (pci_pin + PCI_SLOT(dev->devfn)) % 4;
-					vector = pci_pin_to_vector(bridge->bus->number,
-								   PCI_SLOT(bridge->devfn),
-								   pci_pin);
-				} while (vector < 0 && (bridge = bridge->bus->self));
-			}
-			if (vector >= 0)
-				printk(KERN_WARNING
-				       "PCI: using PPB (%s INT%c) to get vector %d\n",
-				       dev->slot_name, 'A' + pci_pin,
-				       vector);
-			else
-				printk(KERN_WARNING
-				       "PCI: Couldn't map irq for (%s INT%c)\n",
-				       dev->slot_name, 'A' + pci_pin);
-		}
+	idesc = irq_desc(vector);
+	if (idesc->handler != irq_type) {
+		if (idesc->handler != &no_irq_type)
+			printk("IOSAPIC: changing vector %d from %s to %s\n",
+			       vector, idesc->handler->typename, irq_type->typename);
+		idesc->handler = irq_type;
+	}
+#ifdef CONFIG_SMP
+	/*
+	 * For platforms that do not support interrupt redirect via the XTP interface, we
+	 * can round-robin the PCI device interrupts to the processors
+	 */
+	if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
+		static int cpu_index = -1;
 
-		if (vector >= 0) {
-			dev->irq = vector;
+		do
+			if (++cpu_index >= NR_CPUS)
+				cpu_index = 0;
+		while (!cpu_online(cpu_index));
 
-			irq_type = &irq_type_iosapic_level;
-			idesc = irq_desc(vector);
-			if (idesc->handler != irq_type) {
-				if (idesc->handler != &no_irq_type)
-					printk("%s: changing vector %d from %s to %s\n",
-					       __FUNCTION__, vector,
-					       idesc->handler->typename,
-					       irq_type->typename);
-				idesc->handler = irq_type;
-			}
-#ifdef CONFIG_SMP
-			/*
-			 * For platforms that do not support interrupt redirect
-			 * via the XTP interface, we can round-robin the PCI
-			 * device interrupts to the processors
-			 */
-			if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
-				static int cpu_index = 0;
-
-				while (!cpu_online(cpu_index))
-					if (++cpu_index >= NR_CPUS)
-						cpu_index = 0;
-
-				dest = cpu_physical_id(cpu_index) & 0xffff;
-			} else {
-				/*
-				 * Direct the interrupt vector to the current cpu,
-				 * platform redirection will distribute them.
-				 */
-				dest = (ia64_get_lid() >> 16) & 0xffff;
-			}
+		dest = cpu_physical_id(cpu_index) & 0xffff;
+	} else {
+		/*
+		 * Direct the interrupt vector to the current cpu, platform redirection
+		 * will distribute them.
+		 */
+		dest = (ia64_get_lid() >> 16) & 0xffff;
+	}
 #else
-			/* direct the interrupt vector to the running cpu id */
-			dest = (ia64_get_lid() >> 16) & 0xffff;
+	/* direct the interrupt vector to the running cpu id */
+	dest = (ia64_get_lid() >> 16) & 0xffff;
 #endif
+	set_rte(vector, dest);
 
-			printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n",
-			       dev->slot_name, 'A' + pci_pin, dest, vector);
-			set_rte(vector, dest);
-		}
-	}
+	printk("IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n", pci_id, gsi, dest, vector);
 }
 
-
-void
-iosapic_pci_fixup (int phase)
+void __init
+iosapic_parse_prt (void)
 {
-	struct	pci_dev	*dev;
+	struct acpi_prt_entry *entry;
+	struct list_head *node;
+	unsigned int gsi, gsi_base;
+	int index, vector, pcat_compat;
+	char pci_id[16];
+	char *addr;
 
-	if (phase == 0) {
-		if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) {
-			printk("%s: acpi_get_prt failed\n", __FILE__);
-		}
-		return;
-	}
+	list_for_each(node, &acpi_prt.entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
 
-	if (phase != 1)
-		return;
+		/* We're only interested in static (non-link) entries.  */
+		if (entry->link.handle)
+			continue;
+
+		gsi = entry->link.index;
+
+		vector = gsi_to_vector(gsi);
+		if (vector < 0) {
+			/* allocate a vector for this interrupt line */
+			index = find_iosapic(gsi);
+
+			if (index < 0) {
+				printk(KERN_WARNING"IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi);
+				return;
+			}
+			addr = iosapic_lists[index].addr;
+			gsi_base = iosapic_lists[index].gsi_base;
+			pcat_compat = iosapic_lists[index].pcat_compat;
 
-	pci_for_each_dev(dev) {
-		/* fixup dev->irq and program IOSAPIC */
-		iosapic_fixup_pci_interrupt(dev);
+			if (pcat_compat && (gsi < 16))
+				vector = isa_irq_to_vector(gsi);
+			else
+				/* new GSI; allocate a vector for it */
+				vector = ia64_alloc_vector();
 
-		/*
-		 * Nothing to fixup
-		 * Fix out-of-range IRQ numbers
-		 */
-		if (dev->irq >= IA64_NUM_VECTORS)
-			dev->irq = 15;	/* Spurious interrupts */
+			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr);
+		}
+		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
+			 entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
+
+		fixup_vector(vector, gsi, pci_id);
 	}
 }
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/irq.c	Sat Sep 21 21:25:45 2002
@@ -403,8 +403,8 @@
 				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.
@@ -788,7 +788,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/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
--- a/arch/ia64/kernel/ivt.S	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/ivt.S	Sat Sep 21 21:25:45 2002
@@ -70,24 +70,6 @@
 	mov r19=n;;			/* prepare to save predicates */		\
 	br.sptk.many dispatch_to_fault_handler
 
-/*
- * As we don't (hopefully) use the space available, we need to fill it with
- * nops. the parameter may be used for debugging and is representing the entry
- * number
- */
-#define BREAK_BUNDLE(a)	break.m (a); \
-				break.i (a); \
-				break.i (a)
-/*
- * 4 breaks bundles all together
- */
-#define BREAK_BUNDLE4(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a)
-
-/*
- * 8 bundles all together (too lazy to use only 4 at a time !)
- */
-#define BREAK_BUNDLE8(a); BREAK_BUNDLE4(a); BREAK_BUNDLE4(a)
-
 	.section .text.ivt,"ax"
 
 	.align 32768	// align on 32KB boundary
@@ -115,6 +97,10 @@
 	 *	- the faulting virtual address has no L1, L2, or L3 mapping
 	 */
 	mov r16=cr.ifa				// get address that caused the TLB miss
+#ifdef CONFIG_HUGETLB_PAGE
+	movl r18=PAGE_SHIFT
+	mov r25=cr.itir
+#endif
 	;;
 	rsm psr.dt				// use physical addressing for data
 	mov r31=pr				// save the predicate registers
@@ -122,8 +108,18 @@
 	shl r21=r16,3				// shift bit 60 into sign bit
 	shr.u r17=r16,61			// get the region number into r17
 	;;
+	shr r22=r21,3
+#ifdef CONFIG_HUGETLB_PAGE
+	extr.u r26=r25,2,6
+	;;
+	cmp.eq p8,p0=HPAGE_SHIFT,r26
+	;;
+(p8)	dep r25=r18,r25,2,6
+(p8)	shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT
+	;;
+#endif
 	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
-	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of the faulting address
+	shr.u r18=r22,PGDIR_SHIFT		// get bits 33-63 of the faulting address
 	;;
 (p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
 	srlz.d					// ensure "rsm psr.dt" has taken effect
@@ -134,7 +130,7 @@
 (p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
 (p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
 	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
-	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	shr.u r18=r22,PMD_SHIFT			// shift L2 index into position
 	;;
 	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
 	;;
@@ -142,7 +138,7 @@
 	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
 	;;
 (p7)	ld8 r20=[r17]				// fetch the L2 entry (may be 0)
-	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	shr.u r19=r22,PAGE_SHIFT		// shift L3 index into position
 	;;
 (p7)	cmp.eq.or.andcm p6,p7=r20,r0		// was L2 entry NULL?
 	dep r21=r19,r20,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
@@ -160,6 +156,10 @@
 (p11)	itc.d r18				// insert the data TLB entry
 (p6)	br.cond.spnt.many page_fault		// handle bad address/page not present (page fault)
 	mov cr.ifa=r22
+
+#ifdef CONFIG_HUGETLB_PAGE
+(p8)	mov cr.itir=r25				// change to default page-size for VHPT
+#endif
 
 	/*
 	 * Now compute and insert the TLB entry for the virtual page table.  We never
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/mca.c	Sat Sep 21 21:25:45 2002
@@ -208,6 +208,8 @@
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
 }
 
+device_initcall(ia64_mca_check_errors);
+
 /*
  * ia64_mca_register_cpev
  *
diff -Nru a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
--- a/arch/ia64/kernel/pal.S	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/kernel/pal.S	Sat Sep 21 21:25:48 2002
@@ -245,3 +245,48 @@
 	br.ret.sptk.many b0
 END(ia64_pal_call_phys_stacked)
 
+/*
+ * Save scratch fp scratch regs which aren't saved in pt_regs already (fp10-fp15).
+ *
+ * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch
+ * regs fp-low partition.
+ *
+ * Inputs:
+ *      in0	Address of stack storage for fp regs
+ */
+GLOBAL_ENTRY(ia64_save_scratch_fpregs)
+	alloc r3=ar.pfs,1,0,0,0
+	add r2=16,in0
+	;;
+	stf.spill [in0] = f10,32
+	stf.spill [r2]  = f11,32
+	;;
+	stf.spill [in0] = f12,32
+	stf.spill [r2]  = f13,32
+	;;
+	stf.spill [in0] = f14,32
+	stf.spill [r2]  = f15,32
+	br.ret.sptk.many rp
+END(ia64_save_scratch_fpregs)
+
+/*
+ * Load scratch fp scratch regs (fp10-fp15)
+ *
+ * Inputs:
+ *      in0	Address of stack storage for fp regs
+ */
+
+GLOBAL_ENTRY(ia64_load_scratch_fpregs)
+	alloc r3=ar.pfs,1,0,0,0
+	add r2=16,in0
+	;;
+	ldf.fill  f10 = [in0],32
+	ldf.fill  f11 = [r2],32
+	;;
+	ldf.fill  f12 = [in0],32
+	ldf.fill  f13 = [r2],32
+	;;
+	ldf.fill  f14 = [in0],32
+	ldf.fill  f15 = [r2],32
+	br.ret.sptk.many rp
+END(ia64_load_scratch_fpregs)
diff -Nru a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c
--- a/arch/ia64/kernel/pci.c	Sat Sep 21 21:25:45 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,290 +0,0 @@
-/*
- * pci.c - Low-Level PCI Access in IA-64
- *
- * Derived from bios32.c of i386 tree.
- */
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-
-#include <asm/machvec.h>
-#include <asm/page.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/sal.h>
-
-
-#ifdef CONFIG_SMP
-# include <asm/smp.h>
-#endif
-#include <asm/irq.h>
-
-
-#undef DEBUG
-#define DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#ifdef CONFIG_IA64_MCA
-extern void ia64_mca_check_errors( void );
-#endif
-
-struct pci_fixup pcibios_fixups[1];
-
-struct pci_ops *pci_root_ops;
-
-
-/*
- * Low-level SAL-based PCI configuration access functions. Note that SAL
- * calls are already serialized (via sal_lock), so we don't need another
- * synchronization mechanism here.  Not using segment number (yet).
- */
-
-#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \
-	((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))
-
-static int
-__pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
-{
-	int result = 0;
-	u64 data = 0;
-
-	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
-		return -EINVAL;
-
-	result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data);
-
-	*value = (u32) data;
-
-	return result;
-}
-
-static int
-__pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
-{
-	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
-		return -EINVAL;
-
-	return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value);
-}
-
-
-static int
-pci_sal_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
-	return __pci_sal_read(0, bus->number, PCI_SLOT(devfn),
-			    PCI_FUNC(devfn), where, size, value);
-}
-
-static int
-pci_sal_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
-	return __pci_sal_write(0, bus->number, PCI_SLOT(devfn),
-			     PCI_FUNC(devfn), where, size, value);
-}
-
-struct pci_ops pci_sal_ops = {
-	.read = 	pci_sal_read,
-	.write =	pci_sal_write,
-};
-
-
-/*
- * Initialization. Uses the SAL interface
- */
-
-struct pci_bus *
-pcibios_scan_root(int bus)
-{
-	struct list_head *list = NULL;
-	struct pci_bus *pci_bus = NULL;
-
-	list_for_each(list, &pci_root_buses) {
-		pci_bus = pci_bus_b(list);
-		if (pci_bus->number == bus) {
-			/* Already scanned */
-			printk("PCI: Bus (%02x) already probed\n", bus);
-			return pci_bus;
-		}
-	}
-
-	printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
-
-	return pci_scan_bus(bus, pci_root_ops, NULL);
-}
-
-void __init
-pcibios_config_init (void)
-{
-	if (pci_root_ops)
-		return;
-
-	printk("PCI: Using SAL to access configuration space\n");
-
-	pci_root_ops = &pci_sal_ops;
-
-	return;
-}
-
-static int __init
-pcibios_init (void)
-{
-#	define PCI_BUSES_TO_SCAN 255
-	int i = 0;
-
-#ifdef CONFIG_IA64_MCA
-	ia64_mca_check_errors();    /* For post-failure MCA error logging */
-#endif
-
-	pcibios_config_init();
-
-	platform_pci_fixup(0);	/* phase 0 fixups (before buses scanned) */
-
-	printk("PCI: Probing PCI hardware\n");
-	for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
-		pci_scan_bus(i, pci_root_ops, NULL);
-
-	platform_pci_fixup(1);	/* phase 1 fixups (after buses scanned) */
-	return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-void __init
-pcibios_fixup_bus (struct pci_bus *b)
-{
-	return;
-}
-
-void __init
-pcibios_update_resource (struct pci_dev *dev, struct resource *root,
-			 struct resource *res, int resource)
-{
-	unsigned long where, size;
-	u32 reg;
-
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
-	size = res->end - res->start;
-	pci_read_config_dword(dev, where, &reg);
-	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-	pci_write_config_dword(dev, where, reg);
-
-	/* ??? FIXME -- record old value for shutdown.  */
-}
-
-void __init
-pcibios_update_irq (struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-
-	/* ??? FIXME -- record old value for shutdown.  */
-}
-
-void __init
-pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
-}
-
-int
-pcibios_enable_device (struct pci_dev *dev)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	if (!dev)
-		return -EINVAL;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx=0; idx<6; idx++) {
-		r = &dev->resource[idx];
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because of resource collisions\n",
-			       dev->slot_name);
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (dev->resource[PCI_ROM_RESOURCE].start)
-		cmd |= PCI_COMMAND_MEMORY;
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-
-	printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name);
-
-	return 0;
-}
-
-void
-pcibios_align_resource (void *data, struct resource *res,
-		        unsigned long size, unsigned long align)
-{
-}
-
-/*
- * PCI BIOS setup, always defaults to SAL interface
- */
-char * __init
-pcibios_setup (char *str)
-{
-	return NULL;
-}
-
-int
-pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
-		     enum pci_mmap_state mmap_state, int write_combine)
-{
-	/*
-	 * I/O space cannot be accessed via normal processor loads and stores on this
-	 * platform.
-	 */
-	if (mmap_state == pci_mmap_io)
-		/*
-		 * XXX we could relax this for I/O spaces for which ACPI indicates that
-		 * the space is 1-to-1 mapped.  But at the moment, we don't support
-		 * multiple PCI address spaces and the legacy I/O space is not 1-to-1
-		 * mapped, so this is moot.
-		 */
-		return -EINVAL;
-
-	/*
-	 * Leave vm_pgoff as-is, the PCI space address is the physical address on this
-	 * platform.
-	 */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
-	if (write_combine)
-		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	else
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
-			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
-
-	return 0;
-}
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/kernel/perfmon.c	Sat Sep 21 21:25:48 2002
@@ -76,7 +76,7 @@
 /* XXX: these three assume that register i is implemented */
 #define PMD_IS_COUNTING(i) (pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING)
 #define PMC_IS_COUNTING(i) (pmu_conf.pmc_desc[i].type == PFM_REG_COUNTING)
-#define PMC_IS_MONITOR(c)  (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR)
+#define PMC_IS_MONITOR(i)  (pmu_conf.pmc_desc[i].type == PFM_REG_MONITOR)
 
 /* k assume unsigned */
 #define IBR_IS_IMPL(k)	  (k<pmu_conf.num_ibrs)
@@ -193,10 +193,12 @@
  */
 typedef struct {
 	u64 val;	/* virtual 64bit counter value */
-	u64 ival;	/* initial value from user */
+	u64 lval;	/* last value */
 	u64 long_reset;	/* reset value on sampling overflow */
 	u64 short_reset;/* reset value on overflow */
 	u64 reset_pmds[4]; /* which other pmds to reset when this counter overflows */
+	u64 seed;	/* seed for random-number generator */
+	u64 mask;	/* mask for random-number generator */
 	int flags;	/* notify/do not notify */
 } pfm_counter_t;
 
@@ -336,7 +338,7 @@
 
 #define PFM_CMD_PID		0x1	/* command requires pid argument */
 #define PFM_CMD_ARG_READ	0x2	/* command must read argument(s) */
-#define PFM_CMD_ARG_WRITE	0x4	/* command must write argument(s) */
+#define PFM_CMD_ARG_RW		0x4	/* command must read/write argument(s) */
 #define PFM_CMD_CTX		0x8	/* command needs a perfmon context */
 #define PFM_CMD_NOCHK		0x10	/* command does not need to check task's state */
 
@@ -347,7 +349,7 @@
 
 #define PFM_CMD_USE_PID(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_PID) != 0)
 #define PFM_CMD_READ_ARG(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) != 0)
-#define PFM_CMD_WRITE_ARG(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_WRITE) != 0)
+#define PFM_CMD_RW_ARG(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_RW) != 0)
 #define PFM_CMD_USE_CTX(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_CTX) != 0)
 #define PFM_CMD_CHK(cmd)	((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_NOCHK) == 0)
 
@@ -366,6 +368,7 @@
 	unsigned long pfm_ovfl_intr_count; /* keep track of ovfl interrupts */
 	unsigned long pfm_recorded_samples_count;
 	unsigned long pfm_full_smpl_buffer_count; /* how many times the sampling buffer was full */
+	char pad[SMP_CACHE_BYTES] ____cacheline_aligned;
 } pfm_stats_t;
 
 /*
@@ -374,7 +377,8 @@
 static pmu_config_t	pmu_conf; 	/* PMU configuration */
 static pfm_session_t	pfm_sessions;	/* global sessions information */
 static struct proc_dir_entry *perfmon_dir; /* for debug only */
-static pfm_stats_t	pfm_stats;
+static pfm_stats_t	pfm_stats[NR_CPUS];
+
 DEFINE_PER_CPU(int, pfm_syst_wide);
 static DEFINE_PER_CPU(int, pfm_dcr_pp);
 
@@ -410,7 +414,8 @@
  */
 static struct {
 	struct task_struct *owner;
-} ____cacheline_aligned pmu_owners[NR_CPUS];
+	char pad[SMP_CACHE_BYTES] ____cacheline_aligned;
+} pmu_owners[NR_CPUS];
 
 
 
@@ -743,15 +748,14 @@
 	psb = kmalloc(sizeof(*psb), GFP_KERNEL);
 	if (psb == NULL) {
 		DBprintk(("Can't allocate sampling buffer descriptor\n"));
-		pfm_rvfree(smpl_buf, size);
-		return -ENOMEM;
+		goto error_kmalloc;
 	}
 
 	/* allocate vma */
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!vma) {
 		DBprintk(("Cannot allocate vma\n"));
-		goto error;
+		goto error_kmem;
 	}
 	/*
 	 * partially initialize the vma for the sampling buffer
@@ -851,8 +855,11 @@
 	return 0;
 
 error:
-	pfm_rvfree(smpl_buf, size);
+	kmem_cache_free(vm_area_cachep, vma);
+error_kmem:
 	kfree(psb);
+error_kmalloc:
+	pfm_rvfree(smpl_buf, size);
 	return -ENOMEM;
 }
 
@@ -961,7 +968,7 @@
 	 */
 	if (task != current) return -EINVAL;
 
-	if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+	if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
 
 	ret = pfx_is_sane(task, &tmp);
 	if (ret < 0) return ret;
@@ -1017,8 +1024,8 @@
 
 	if (notify_pid == current->pid) {
 
-		ctx->ctx_notify_task = task = current;
-		current->thread.pfm_context = ctx;
+		ctx->ctx_notify_task = current;
+		task->thread.pfm_context = ctx;
 
 	} else if (notify_pid!=0) {
 		struct task_struct *notify_task;
@@ -1034,7 +1041,10 @@
 			/*
 			 * check if we can send this task a signal
 			 */
-			if (pfm_bad_permissions(notify_task)) goto buffer_error;
+			if (pfm_bad_permissions(notify_task)) {
+				read_unlock(&tasklist_lock);
+				goto buffer_error;
+			}
 
 			/* 
 		 	 * make visible
@@ -1044,7 +1054,7 @@
 		 	 * okay because child will do the scan for nothing which
 		 	 * won't hurt.
 		 	 */
-			current->thread.pfm_context = ctx;
+			task->thread.pfm_context = ctx;
 
 			/*
 			 * will cause task to check on exit for monitored
@@ -1101,7 +1111,7 @@
 
 	sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */
 
-	if (copy_to_user(req, &tmp, sizeof(tmp))) {
+	if (__copy_to_user(req, &tmp, sizeof(tmp))) {
 		ret = -EFAULT;
 		goto buffer_error;
 	}
@@ -1147,16 +1157,38 @@
 abort:
 	UNLOCK_PFS();
 
+	/* make sure we don't leave anything behind */
+	task->thread.pfm_context = NULL;
+
 	return ret;
 }
 
+static inline unsigned long
+pfm_new_counter_value (pfm_counter_t *reg, int is_long_reset)
+{
+	unsigned long val = is_long_reset ? reg->long_reset : reg->short_reset;
+	unsigned long new_seed, old_seed = reg->seed, mask = reg->mask;
+	extern unsigned long carta_random32 (unsigned long seed);
+
+	if (reg->flags & PFM_REGFL_RANDOM) {
+		new_seed = carta_random32(old_seed);
+		val -= (old_seed & mask);	/* counter values are negative numbers! */
+		if ((mask >> 32) != 0)
+			/* construct a full 64-bit random value: */
+			new_seed |= carta_random32(old_seed >> 32) << 32;
+		reg->seed = new_seed;
+	}
+	reg->lval = val;
+	return val;
+}
+
 static void
 pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int flag)
 {
 	unsigned long mask = ovfl_regs[0];
 	unsigned long reset_others = 0UL;
 	unsigned long val;
-	int i;
+	int i, is_long_reset = (flag & PFM_RELOAD_LONG_RESET);
 
 	DBprintk(("masks=0x%lx\n", mask));
 
@@ -1166,15 +1198,11 @@
 	mask >>= PMU_FIRST_COUNTER;
 	for(i = PMU_FIRST_COUNTER; mask; i++, mask >>= 1) {
 		if (mask & 0x1) {
-			val  = flag == PFM_RELOAD_LONG_RESET ? 
-					ctx->ctx_soft_pmds[i].long_reset:
-					ctx->ctx_soft_pmds[i].short_reset;
-
+			val = pfm_new_counter_value(ctx->ctx_soft_pmds + i, is_long_reset);
 			reset_others |= ctx->ctx_soft_pmds[i].reset_pmds[0];
 
-			DBprintk(("[%d] %s reset soft_pmd[%d]=%lx\n", 
-			  	current->pid, 
-				flag == PFM_RELOAD_LONG_RESET ? "long" : "short", i, val));
+			DBprintk(("[%d] %s reset soft_pmd[%d]=%lx\n", current->pid,
+				  is_long_reset ? "long" : "short", i, val));
 
 			/* upper part is ignored on rval */
 			pfm_write_soft_counter(ctx, i, val);
@@ -1188,23 +1216,17 @@
 
 		if ((reset_others & 0x1) == 0) continue;
 
-		val  = flag == PFM_RELOAD_LONG_RESET ? 
-					ctx->ctx_soft_pmds[i].long_reset:
-					ctx->ctx_soft_pmds[i].short_reset;
+		val = pfm_new_counter_value(ctx->ctx_soft_pmds + i, is_long_reset);
 
 		if (PMD_IS_COUNTING(i)) {
 			pfm_write_soft_counter(ctx, i, val);
 		} else {
 			ia64_set_pmd(i, val);
 		}
-
-		DBprintk(("[%d] %s reset_others pmd[%d]=%lx\n", 
-			  	current->pid, 
-				flag == PFM_RELOAD_LONG_RESET ? "long" : "short", i, val));
+		DBprintk(("[%d] %s reset_others pmd[%d]=%lx\n", current->pid,
+			  is_long_reset ? "long" : "short", i, val));
 	}
 	ia64_srlz_d();
-	/* just in case ! */
-	ctx->ctx_ovfl_regs[0] = 0UL;
 }
 
 static int
@@ -1212,9 +1234,10 @@
 {
 	struct thread_struct *th = &task->thread;
 	pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg;
-	unsigned int cnum;
+	unsigned long value;
+	unsigned int cnum, reg_flags, flags;
 	int i;
-	int ret = 0, reg_retval = 0;
+	int ret = -EINVAL;
 
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
@@ -1225,10 +1248,12 @@
 
 	for (i = 0; i < count; i++, req++) {
 
+		if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
 
-		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
-
-		cnum = tmp.reg_num;
+		cnum      = tmp.reg_num;
+		reg_flags = tmp.reg_flags;
+		value     = tmp.reg_value;
+		flags     = 0;
 
 		/* 
 		 * we reject all non implemented PMC as well
@@ -1237,8 +1262,7 @@
 		 */
 		if (!PMC_IS_IMPL(cnum) || cnum < 4) {
 			DBprintk(("pmc[%u] is unimplemented or invalid\n", cnum));
-			ret = -EINVAL;
-			goto abort_mission;
+			goto error;
 		}
 		/*
 		 * A PMC used to configure monitors must be:
@@ -1247,73 +1271,79 @@
 		 * any other configuration is rejected.
 		 */
 		if (PMC_IS_MONITOR(cnum) || PMC_IS_COUNTING(cnum)) {
-			DBprintk(("pmc[%u].pm=%ld\n", cnum, PMC_PM(cnum, tmp.reg_value))); 
-
-			if (ctx->ctx_fl_system ^ PMC_PM(cnum, tmp.reg_value)) {
-				DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, tmp.reg_value), ctx->ctx_fl_system));
-				ret = -EINVAL;
-				goto abort_mission;
+			if (ctx->ctx_fl_system ^ PMC_PM(cnum, value)) {
+				DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, value), ctx->ctx_fl_system));
+				goto error;
 			}
 		}
 
 		if (PMC_IS_COUNTING(cnum)) {
-			pfm_monitor_t *p = (pfm_monitor_t *)&tmp.reg_value;
+			pfm_monitor_t *p = (pfm_monitor_t *)&value;
 			/*
 		 	 * enforce generation of overflow interrupt. Necessary on all
 		 	 * CPUs.
 		 	 */
 			p->pmc_oi = 1;
 
-			if (tmp.reg_flags & PFM_REGFL_OVFL_NOTIFY) {
+			if (reg_flags & PFM_REGFL_OVFL_NOTIFY) {
 				/*
-				 * must have a target for the signal
-				 */
+			 	 * must have a target for the signal
+			 	 */
 				if (ctx->ctx_notify_task == NULL) {
-					DBprintk(("no notify_task && PFM_REGFL_OVFL_NOTIFY\n"));
-					ret = -EINVAL;
-					goto abort_mission;
+					DBprintk(("cannot set ovfl_notify: no notify_task\n"));
+					goto error;
 				}
-
-				ctx->ctx_soft_pmds[cnum].flags |= PFM_REGFL_OVFL_NOTIFY;
+				flags |= PFM_REGFL_OVFL_NOTIFY;
 			}
-			/*
-			 * copy reset vector
-			 */
-			ctx->ctx_soft_pmds[cnum].reset_pmds[0] = tmp.reg_reset_pmds[0];
-			ctx->ctx_soft_pmds[cnum].reset_pmds[1] = tmp.reg_reset_pmds[1];
-			ctx->ctx_soft_pmds[cnum].reset_pmds[2] = tmp.reg_reset_pmds[2];
-			ctx->ctx_soft_pmds[cnum].reset_pmds[3] = tmp.reg_reset_pmds[3];
+
+			if (reg_flags & PFM_REGFL_RANDOM) flags |= PFM_REGFL_RANDOM;
+
+		} else if (reg_flags & (PFM_REGFL_OVFL_NOTIFY|PFM_REGFL_RANDOM)) {
+				DBprintk(("cannot set ovfl_notify or random on pmc%u\n", cnum));
+				goto error;
 		}
+
 		/*
 		 * execute write checker, if any
 		 */
-		if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
-abort_mission:
-		if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
+		if (PMC_WR_FUNC(cnum)) {
+			ret = PMC_WR_FUNC(cnum)(task, cnum, &value, regs);
+			if (ret) goto error;
+			ret = -EINVAL;
+		}
 
-		PFM_REG_RETFLAG_SET(tmp.reg_flags, reg_retval);
+		/*
+		 * no error on this register
+		 */
+		PFM_REG_RETFLAG_SET(tmp.reg_flags, 0);
 
 		/*
 		 * update register return value, abort all if problem during copy.
+		 * we only modify the reg_flags field. no check mode is fine because
+		 * access has been verified upfront in sys_perfmonctl().
+		 *
+		 * If this fails, then the software state is not modified
 		 */
-		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
+		if (__put_user(tmp.reg_flags, &req->reg_flags)) return -EFAULT;
 
 		/*
-		 * if there was something wrong on this register, don't touch
-		 * the hardware at all and abort write request for others.
-		 *
-		 * On error, the user mut sequentially scan the table and the first
-		 * entry which has a return flag set is the one that caused the error.
+		 * Now we commit the changes to the software state
 		 */
-		if (ret != 0) {
-			DBprintk(("[%d] pmc[%u]=0x%lx error %d\n",
-				  task->pid, cnum, tmp.reg_value, reg_retval));
-			break;
-		}
 
 		/* 
-		 * We can proceed with this register!
+		 * full flag update each time a register is programmed
 		 */
+		ctx->ctx_soft_pmds[cnum].flags = flags;
+
+		if (PMC_IS_COUNTING(cnum)) {
+			/*
+			 * copy reset vector
+			 */
+			ctx->ctx_soft_pmds[cnum].reset_pmds[0] = tmp.reg_reset_pmds[0];
+			ctx->ctx_soft_pmds[cnum].reset_pmds[1] = tmp.reg_reset_pmds[1];
+			ctx->ctx_soft_pmds[cnum].reset_pmds[2] = tmp.reg_reset_pmds[2];
+			ctx->ctx_soft_pmds[cnum].reset_pmds[3] = tmp.reg_reset_pmds[3];
+		}
 
 		/*
 		 * Needed in case the user does not initialize the equivalent
@@ -1325,16 +1355,26 @@
 		/* 
 		 * keep copy the pmc, used for register reload
 		 */
-		th->pmc[cnum] = tmp.reg_value;
+		th->pmc[cnum] = value;
 
-		ia64_set_pmc(cnum, tmp.reg_value);
+		ia64_set_pmc(cnum, value);
 
 		DBprintk(("[%d] pmc[%u]=0x%lx flags=0x%x used_pmds=0x%lx\n", 
-			  task->pid, cnum, tmp.reg_value, 
+			  task->pid, cnum, value, 
 			  ctx->ctx_soft_pmds[cnum].flags, 
 			  ctx->ctx_used_pmds[0]));
 
 	}
+
+	return 0;
+
+error:
+	PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL);
+
+	if (__put_user(tmp.reg_flags, &req->reg_flags)) ret = -EFAULT;
+
+	DBprintk(("[%d] pmc[%u]=0x%lx error %d\n", task->pid, cnum, value, ret));
+
 	return ret;
 }
 
@@ -1342,9 +1382,10 @@
 pfm_write_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg;
+	unsigned long value, hw_value;
 	unsigned int cnum;
 	int i;
-	int ret = 0, reg_retval = 0;
+	int ret;
 
 	/* we don't quite support this right now */
 	if (task != current) return -EINVAL;
@@ -1354,65 +1395,74 @@
 	 */
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
 
-
 	/* XXX: ctx locking may be required here */
 
+	ret = -EINVAL;
+
 	for (i = 0; i < count; i++, req++) {
 
-		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+		if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+
+		cnum  = tmp.reg_num;
+		value = tmp.reg_value;
 
-		cnum = tmp.reg_num;
 		if (!PMD_IS_IMPL(cnum)) {
-			ret = -EINVAL;
+			DBprintk(("pmd[%u] is unimplemented or invalid\n", cnum));
 			goto abort_mission;
 		}
 
-		/* update virtualized (64bits) counter */
-		if (PMD_IS_COUNTING(cnum)) {
-			ctx->ctx_soft_pmds[cnum].ival = tmp.reg_value;
-			ctx->ctx_soft_pmds[cnum].val  = tmp.reg_value & ~pmu_conf.perf_ovfl_val;
-			ctx->ctx_soft_pmds[cnum].long_reset = tmp.reg_long_reset;
-			ctx->ctx_soft_pmds[cnum].short_reset = tmp.reg_short_reset;
-
-		}
 		/*
 		 * execute write checker, if any
 		 */
-		if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
-abort_mission:
-		if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
-
-		PFM_REG_RETFLAG_SET(tmp.reg_flags, reg_retval);
+		if (PMD_WR_FUNC(cnum)) {
+			unsigned long v = value;
+			ret = PMD_WR_FUNC(cnum)(task, cnum, &v, regs);
+			if (ret) goto abort_mission;
+			value = v;
+			ret = -EINVAL;
+		}
+		hw_value = value;
+		/*
+		 * no error on this register
+		 */
+		PFM_REG_RETFLAG_SET(tmp.reg_flags, 0);
 
-		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
+		if (__put_user(tmp.reg_flags, &req->reg_flags)) return -EFAULT;
 
 		/*
-		 * if there was something wrong on this register, don't touch
-		 * the hardware at all and abort write request for others.
-		 *
-		 * On error, the user mut sequentially scan the table and the first
-		 * entry which has a return flag set is the one that caused the error.
+		 * now commit changes to software state
 		 */
-		if (ret != 0) {
-			DBprintk(("[%d] pmc[%u]=0x%lx error %d\n",
-				  task->pid, cnum, tmp.reg_value, reg_retval));
-			break;
+
+		/* update virtualized (64bits) counter */
+		if (PMD_IS_COUNTING(cnum)) {
+			ctx->ctx_soft_pmds[cnum].lval = value;
+			ctx->ctx_soft_pmds[cnum].val  = value & ~pmu_conf.perf_ovfl_val;
+
+			hw_value = value & pmu_conf.perf_ovfl_val; 
+
+			ctx->ctx_soft_pmds[cnum].long_reset  = tmp.reg_long_reset;
+			ctx->ctx_soft_pmds[cnum].short_reset = tmp.reg_short_reset;
+
+			ctx->ctx_soft_pmds[cnum].seed = tmp.reg_random_seed;
+			ctx->ctx_soft_pmds[cnum].mask = tmp.reg_random_mask;
 		}
 
 		/* keep track of what we use */
 		CTX_USED_PMD(ctx, pmu_conf.pmd_desc[(cnum)].dep_pmd[0]);
+
 		/* mark this register as used as well */
 		CTX_USED_PMD(ctx, RDEP(cnum));
 
 		/* writes to unimplemented part is ignored, so this is safe */
-		ia64_set_pmd(cnum, tmp.reg_value & pmu_conf.perf_ovfl_val);
+		ia64_set_pmd(cnum, hw_value);
 
 		/* to go away */
 		ia64_srlz_d();
 
-		DBprintk(("[%d] pmd[%u]: soft_pmd=0x%lx  short_reset=0x%lx "
+		DBprintk(("[%d] pmd[%u]: value=0x%lx hw_value=0x%lx soft_pmd=0x%lx  short_reset=0x%lx "
 			  "long_reset=0x%lx hw_pmd=%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx\n",
 				task->pid, cnum,
+				value, hw_value,
 				ctx->ctx_soft_pmds[cnum].val,
 				ctx->ctx_soft_pmds[cnum].short_reset,
 				ctx->ctx_soft_pmds[cnum].long_reset,
@@ -1421,17 +1471,36 @@
 				ctx->ctx_used_pmds[0],
 				ctx->ctx_soft_pmds[cnum].reset_pmds[0]));
 	}
+
+	return 0;
+
+abort_mission:
+	/*
+	 * for now, we have only one possibility for error
+	 */
+	PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL);
+
+	/*
+	 * we change the return value to EFAULT in case we cannot write register return code.
+	 * The caller first must correct this error, then a resubmission of the request will
+	 * eventually yield the EINVAL.
+	 */
+	if (__put_user(tmp.reg_flags, &req->reg_flags)) ret = -EFAULT;
+
+	DBprintk(("[%d] pmc[%u]=0x%lx ret %d\n", task->pid, cnum, value, ret));
+
 	return ret;
 }
 
+
 static int
 pfm_read_pmds(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	struct thread_struct *th = &task->thread;
-	unsigned long val=0;
-	pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg;
-	unsigned int cnum;
-	int i, ret = 0;
+	unsigned long val = 0UL;
+	pfarg_reg_t *req = (pfarg_reg_t *)arg;
+	unsigned int cnum, reg_flags = 0;
+	int i, ret = -EINVAL;
 
 	if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
 
@@ -1447,11 +1516,9 @@
 	DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
 
 	for (i = 0; i < count; i++, req++) {
-		unsigned long ctx_val = ~0UL;
 
-		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
-
-		cnum = tmp.reg_num;
+		if (__get_user(cnum, &req->reg_num)) return -EFAULT;
+		if (__get_user(reg_flags, &req->reg_flags)) return -EFAULT;
 
 		if (!PMD_IS_IMPL(cnum)) goto abort_mission;
 		/*
@@ -1501,34 +1568,40 @@
 			 */
 
 			val &= pmu_conf.perf_ovfl_val;
-			val += ctx_val = ctx->ctx_soft_pmds[cnum].val;
+			val += ctx->ctx_soft_pmds[cnum].val;
 		} 
 
-		tmp.reg_value = val;
-
 		/*
 		 * execute read checker, if any
 		 */
 		if (PMD_RD_FUNC(cnum)) {
-			ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
+			unsigned long v = val;
+			ret = PMD_RD_FUNC(cnum)(task, cnum, &v, regs);
+			val = v;
 		}
 
-		PFM_REG_RETFLAG_SET(tmp.reg_flags, ret);
+		PFM_REG_RETFLAG_SET(reg_flags, 0);
 
 		DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", 
-					cnum, ret, val, ia64_get_pmc(cnum)));
-
-		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
+			cnum, ret, val, ia64_get_pmc(cnum)));
+		/*
+		 * update register return value, abort all if problem during copy.
+		 * we only modify the reg_flags field. no check mode is fine because
+		 * access has been verified upfront in sys_perfmonctl().
+		 */
+		if (__put_user(cnum, &req->reg_num)) return -EFAULT;
+		if (__put_user(val, &req->reg_value)) return -EFAULT;
+		if (__put_user(reg_flags, &req->reg_flags)) return -EFAULT;
 	}
+
 	return 0;
+
 abort_mission:
-	PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL);
-	/* 
-	 * XXX: if this fails, we stick with the original failure, flag not updated!
-	 */
-	copy_to_user(req, &tmp, sizeof(tmp));
-	return -EINVAL;
+	PFM_REG_RETFLAG_SET(reg_flags, PFM_REG_RETFL_EINVAL);
 
+	if (__put_user(reg_flags, &req->reg_flags)) ret = -EFAULT;
+
+	return ret;
 }
 
 #ifdef PFM_PMU_USES_DBR
@@ -1697,44 +1770,6 @@
 	return 0;
 }
 
-#ifndef CONFIG_SMP
-/*
- * On UP kernels, we do not need to constantly set the psr.pp bit
- * when a task is scheduled. The psr.pp bit can only be changed in
- * the kernel because of a user request. Given we are on a UP non preeemptive 
- * kernel we know that no other task is running, so we cna simply update their
- * psr.pp from their saved state. There is this no impact on the context switch
- * code compared to the SMP case.
- */
-static void
-pfm_tasklist_toggle_pp(unsigned int val)
-{
-	struct task_struct *p;
-	struct pt_regs *regs;
-
-	DBprintk(("invoked by [%d] pp=%u\n", current->pid, val));
-
-	read_lock(&tasklist_lock);
-
-	for_each_task(p) {
-       		regs = (struct pt_regs *)((unsigned long) p + IA64_STK_OFFSET);
-
-		/*
-		 * position on pt_regs saved on stack on 1st entry into the kernel
-		 */
-		regs--;
-
-		/*
-		 * update psr.pp
-		 */
-		ia64_psr(regs)->pp = val;
-	}
-	read_unlock(&tasklist_lock);
-}
-#endif
-
-
-
 static int
 pfm_stop(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, 
 	 struct pt_regs *regs)
@@ -1763,11 +1798,8 @@
 
 		ia64_srlz_i();
 
-#ifdef CONFIG_SMP
 		__get_cpu_var(pfm_dcr_pp)  = 0;
-#else
-		pfm_tasklist_toggle_pp(0);
-#endif
+
 		ia64_psr(regs)->pp = 0;
 
 	} else {
@@ -2013,7 +2045,7 @@
 	for (i = 0; i < count; i++, req++) {
 
 		
-		if (copy_from_user(&tmp, req, sizeof(tmp))) goto abort_mission;
+		if (__copy_from_user(&tmp, req, sizeof(tmp))) goto abort_mission;
 		
 		rnum      = tmp.dbreg_num;
 		dbreg.val = tmp.dbreg_value;
@@ -2046,7 +2078,7 @@
 
 		PFM_REG_RETFLAG_SET(tmp.dbreg_flags, 0);
 
-		if (copy_to_user(req, &tmp, sizeof(tmp))) goto abort_mission;
+		if (__copy_to_user(req, &tmp, sizeof(tmp))) goto abort_mission;
 
 		/*
 		 * Debug registers, just like PMC, can only be modified
@@ -2101,7 +2133,7 @@
 		 * XXX: for now we can only come here on EINVAL
 		 */
 		PFM_REG_RETFLAG_SET(tmp.dbreg_flags, PFM_REG_RETFL_EINVAL);
-		copy_to_user(req, &tmp, sizeof(tmp));
+		__put_user(tmp.dbreg_flags, &req->dbreg_flags);
 	}
 	return ret;
 }
@@ -2142,7 +2174,7 @@
 	tmp.ft_version      = PFM_VERSION;
 	tmp.ft_smpl_version = PFM_SMPL_VERSION;
 
-	if (copy_to_user(arg, &tmp, sizeof(tmp))) return -EFAULT;
+	if (__copy_to_user(arg, &tmp, sizeof(tmp))) return -EFAULT;
 
 	return 0;
 }
@@ -2171,11 +2203,8 @@
 
 	if (ctx->ctx_fl_system) {
 		
-#ifdef CONFIG_SMP
 		__get_cpu_var(pfm_dcr_pp)  = 1;
-#else
-		pfm_tasklist_toggle_pp(1);
-#endif
+
 		/* set user level psr.pp */
 		ia64_psr(regs)->pp = 1;
 
@@ -2226,10 +2255,8 @@
 		__asm__ __volatile__ ("rsm psr.pp;;"::: "memory");
 		ia64_srlz_i();
 
-#ifdef CONFIG_SMP
-		__get_cpu_var(pfm_syst_wide) = 1;
 		__get_cpu_var(pfm_dcr_pp)    = 0;
-#endif
+		__get_cpu_var(pfm_syst_wide) = 1;
 	} else {
 		/*
 		 * needed in case the task was a passive task during
@@ -2270,11 +2297,11 @@
 {
 	pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg;
 	unsigned int cnum;
-	int i;
+	int i, ret = -EINVAL;
 
 	for (i = 0; i < count; i++, req++) {
 
-		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
+		if (__copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
 
 		cnum = tmp.reg_num;
 
@@ -2286,16 +2313,13 @@
 
 		DBprintk(("pmc_reset_val pmc[%u]=0x%lx\n", cnum, tmp.reg_value)); 
 
-		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
+		if (__copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
 	}
 	return 0;
 abort_mission:
 	PFM_REG_RETFLAG_SET(tmp.reg_flags, PFM_REG_RETFL_EINVAL);
-	/* 
-	 * XXX: if this fails, we stick with the original failure, flag not updated!
-	 */
-	copy_to_user(req, &tmp, sizeof(tmp));
-	return -EINVAL;
+	if (__copy_to_user(req, &tmp, sizeof(tmp))) ret = -EFAULT;
+	return ret;
 }
 
 /*
@@ -2303,21 +2327,21 @@
  */
 static pfm_cmd_desc_t pfm_cmd_tab[]={
 /* 0  */{ NULL, 0, 0, 0}, /* not used */
-/* 1  */{ pfm_write_pmcs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, 
-/* 2  */{ pfm_write_pmds, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)},
-/* 3  */{ pfm_read_pmds,PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, 
+/* 1  */{ pfm_write_pmcs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, 
+/* 2  */{ pfm_write_pmds, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)},
+/* 3  */{ pfm_read_pmds,PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)}, 
 /* 4  */{ pfm_stop, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
 /* 5  */{ pfm_start, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
 /* 6  */{ pfm_enable, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
 /* 7  */{ pfm_disable, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
-/* 8  */{ pfm_context_create, PFM_CMD_PID|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, 1, sizeof(pfarg_context_t)},
+/* 8  */{ pfm_context_create, PFM_CMD_PID|PFM_CMD_ARG_RW, 1, sizeof(pfarg_context_t)},
 /* 9  */{ pfm_context_destroy, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
 /* 10 */{ pfm_restart, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_NOCHK, 0, 0},
 /* 11 */{ pfm_protect_context, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
-/* 12 */{ pfm_get_features, PFM_CMD_ARG_WRITE, 0, 0},
+/* 12 */{ pfm_get_features, PFM_CMD_ARG_RW, 0, 0},
 /* 13 */{ pfm_debug, 0, 1, sizeof(unsigned int)},
 /* 14 */{ pfm_context_unprotect, PFM_CMD_PID|PFM_CMD_CTX, 0, 0},
-/* 15 */{ pfm_get_pmc_reset, PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)},
+/* 15 */{ pfm_get_pmc_reset, PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_reg_t)},
 /* 16 */{ NULL, 0, 0, 0}, /* not used */
 /* 17 */{ NULL, 0, 0, 0}, /* not used */
 /* 18 */{ NULL, 0, 0, 0}, /* not used */
@@ -2335,8 +2359,8 @@
 /* 30 */{ NULL, 0, 0, 0}, /* not used */
 /* 31 */{ NULL, 0, 0, 0}, /* not used */
 #ifdef PFM_PMU_USES_DBR
-/* 32 */{ pfm_write_ibrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)},
-/* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_READ|PFM_CMD_ARG_WRITE, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)}
+/* 32 */{ pfm_write_ibrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)},
+/* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)}
 #endif
 };
 #define PFM_CMD_COUNT	(sizeof(pfm_cmd_tab)/sizeof(pfm_cmd_desc_t))
@@ -2345,19 +2369,22 @@
 check_task_state(struct task_struct *task)
 {
 	int ret = 0;
-
+#ifdef CONFIG_SMP
 	/* We must wait until the state has been completely
 	 * saved. There can be situations where the reader arrives before
 	 * after the task is marked as STOPPED but before pfm_save_regs()
 	 * is completed.
 	 */
+	if (task->state != TASK_ZOMBIE && task->state != TASK_STOPPED) return -EBUSY;
+	DBprintk(("before wait_task_inactive [%d] state %ld\n", task->pid, task->state));
+	wait_task_inactive(task);
+	DBprintk(("after wait_task_inactive [%d] state %ld\n", task->pid, task->state));
+#else
 	if (task->state != TASK_ZOMBIE && task->state != TASK_STOPPED) {
 		DBprintk(("warning [%d] not in stable state %ld\n", task->pid, task->state));
 		ret = -EBUSY;
 	}
-	DBprintk(("before wait_task_inactive [%d] state %ld\n", task->pid, task->state));
-	wait_task_inactive(task);
-	DBprintk(("after wait_task_inactive [%d] state %ld\n", task->pid, task->state));
+#endif
 	return ret;
 }
 
@@ -2389,7 +2416,7 @@
 
 	if (PFM_CMD_READ_ARG(cmd) && !access_ok(VERIFY_READ, arg, sz*count)) return -EFAULT;
 
-	if (PFM_CMD_WRITE_ARG(cmd) && !access_ok(VERIFY_WRITE, arg, sz*count)) return -EFAULT;
+	if (PFM_CMD_RW_ARG(cmd) && !access_ok(VERIFY_WRITE, arg, sz*count)) return -EFAULT;
 
 	if (PFM_CMD_USE_PID(cmd))  {
 		/* 
@@ -2551,9 +2578,16 @@
 	 */
 	h->pid  = current->pid;
 	h->cpu  = smp_processor_id();
-	h->rate = 0; /* XXX: add the sampling rate used here */
-	h->ip   = regs ? regs->cr_iip : 0x0;	/* where did the fault happened */
-	h->regs = ovfl_mask; 			/* which registers overflowed */
+	h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL;
+	/* 
+	 * where did the fault happen
+	 */
+	h->ip   = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL;	
+
+	/* 
+	 * which registers overflowed
+	 */
+	h->regs = ovfl_mask;
 
 	/* guaranteed to monotonically increase on each cpu */
 	h->stamp  = pfm_get_stamp();
@@ -2572,15 +2606,13 @@
 
 		if (PMD_IS_COUNTING(j)) {
 			*e  =  pfm_read_soft_counter(ctx, j);
-			/* check if this pmd overflowed as well */
-			*e +=  ovfl_mask & (1UL<<j) ? 1 + pmu_conf.perf_ovfl_val : 0;
 		} else {
 			*e = ia64_get_pmd(j); /* slow */
 		}
 		DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
 		e++;
 	}
-	pfm_stats.pfm_recorded_samples_count++;
+	pfm_stats[smp_processor_id()].pfm_recorded_samples_count++;
 
 	/*
 	 * make the new entry visible to user, needs to be atomic
@@ -2597,7 +2629,7 @@
 		/*
 		 * XXX: must reset buffer in blocking mode and lost notified
 		 */
-		pfm_stats.pfm_full_smpl_buffer_count++;
+		pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++;
 		return 1;
 	}
 	return 0;
@@ -2674,23 +2706,13 @@
 			  i, ia64_get_pmd(i), ctx->ctx_soft_pmds[i].val));
 
 		/*
-		 * Because we sometimes (EARS/BTB) reset to a specific value, we cannot simply use
-		 * val to count the number of times we overflowed. Otherwise we would loose the 
-		 * current value in the PMD (which can be >0). So to make sure we don't loose
-		 * the residual counts we set val to contain full 64bits value of the counter.
+		 * Note that the pmd is not necessarily 0 at this point as qualified events
+		 * may have happened before the PMU was frozen. The residual count is not
+		 * taken into consideration here but will be with any read of the pmd via
+		 * pfm_read_pmds().
 		 */
 		old_val = ctx->ctx_soft_pmds[i].val;
-		ctx->ctx_soft_pmds[i].val = 1 + pmu_conf.perf_ovfl_val + pfm_read_soft_counter(ctx, i);
-
-		DBprintk_ovfl(("soft_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx\n", 
-			  i, ctx->ctx_soft_pmds[i].val, old_val, 
-			  ia64_get_pmd(i) & pmu_conf.perf_ovfl_val));
-
-		/*
-		 * now that we have extracted the hardware counter, we can clear it to ensure
-		 * that a subsequent PFM_READ_PMDS will not include it again.
-		 */
-		ia64_set_pmd(i, 0UL);
+		ctx->ctx_soft_pmds[i].val += 1 + pmu_conf.perf_ovfl_val;
 
 		/*
 		 * check for overflow condition
@@ -2699,12 +2721,15 @@
 
 			ovfl_pmds |= 1UL << i;
 
-			DBprintk_ovfl(("soft_pmd[%d] overflowed flags=0x%x, ovfl=0x%lx\n", i, ctx->ctx_soft_pmds[i].flags, ovfl_pmds));
-
 			if (PMC_OVFL_NOTIFY(ctx, i)) {
 				ovfl_notify |= 1UL << i;
 			}
 		}
+		DBprintk_ovfl(("soft_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n", 
+			  i, ctx->ctx_soft_pmds[i].val, old_val, 
+			  ia64_get_pmd(i) & pmu_conf.perf_ovfl_val, ovfl_pmds, ovfl_notify));
+
+
 	}
 
 	/*
@@ -2893,7 +2918,7 @@
 	struct task_struct *task;
 	pfm_context_t *ctx;
 
-	pfm_stats.pfm_ovfl_intr_count++;
+	pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++;
 
 	/* 
 	 * srlz.d done before arriving here
@@ -2951,10 +2976,7 @@
 		atomic_set(&ctx->ctx_is_busy, 0);
 #endif
 	} else {
-		pfm_stats.pfm_spurious_ovfl_intr_count++;
-
-		printk("perfmon: Spurious PMU overflow interrupt on CPU%d: pmc0=0x%lx owner=%p\n", 
-			smp_processor_id(), pmc0, (void *)PMU_OWNER());
+		pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++;
 	}
 }
 
@@ -2965,28 +2987,24 @@
 	char *p = page;
 	int i;
 
-	p += sprintf(p, "enabled          : %s\n", pmu_conf.pfm_is_disabled ? "No": "Yes");
-	p += sprintf(p, "fastctxsw        : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No");
-	p += sprintf(p, "ovfl_mask        : 0x%lx\n", pmu_conf.perf_ovfl_val);
-	p += sprintf(p, "overflow intrs   : %lu\n", pfm_stats.pfm_ovfl_intr_count);
-	p += sprintf(p, "spurious intrs   : %lu\n", pfm_stats.pfm_spurious_ovfl_intr_count);
-	p += sprintf(p, "recorded samples : %lu\n", pfm_stats.pfm_recorded_samples_count);
-	p += sprintf(p, "smpl buffer full : %lu\n", pfm_stats.pfm_full_smpl_buffer_count);
+	p += sprintf(p, "enabled                : %s\n", pmu_conf.pfm_is_disabled ? "No": "Yes");
+	p += sprintf(p, "fastctxsw              : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No");
+	p += sprintf(p, "ovfl_mask              : 0x%lx\n", pmu_conf.perf_ovfl_val);
 
-#ifdef CONFIG_SMP
-	p += sprintf(p, "CPU%d syst_wide   : %d\n"
-			"CPU%d dcr_pp      : %d\n", 
-			smp_processor_id(), 
-			__get_cpu_var(pfm_syst_wide), 
-			smp_processor_id(), 
-			__get_cpu_var(pfm_dcr_pp));
-#endif
+	for(i=0; i < NR_CPUS; i++) {
+		if (cpu_is_online(i) == 0) continue;
+		p += sprintf(p, "CPU%-2d overflow intrs   : %lu\n", i, pfm_stats[i].pfm_ovfl_intr_count);
+		p += sprintf(p, "CPU%-2d spurious intrs   : %lu\n", i, pfm_stats[i].pfm_spurious_ovfl_intr_count);
+		p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count);
+		p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count);
+		p += sprintf(p, "CPU%-2d owner            : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
+	}
 
 	LOCK_PFS();
-	p += sprintf(p, "proc_sessions    : %lu\n"
-			"sys_sessions     : %lu\n"
-			"sys_use_dbregs   : %lu\n"
-			"ptrace_use_dbregs: %lu\n", 
+	p += sprintf(p, "proc_sessions          : %lu\n"
+			"sys_sessions           : %lu\n"
+			"sys_use_dbregs         : %lu\n"
+			"ptrace_use_dbregs      : %lu\n", 
 			pfm_sessions.pfs_task_sessions, 
 			pfm_sessions.pfs_sys_sessions,
 			pfm_sessions.pfs_sys_use_dbregs,
@@ -2994,30 +3012,6 @@
 
 	UNLOCK_PFS();
 
-	for(i=0; i < NR_CPUS; i++) {
-		if (cpu_is_online(i)) {
-			p += sprintf(p, "CPU%d owner : %-6d\n",
-					i, 
-					pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
-		}
-	}
-
-	for(i=0; pmd_desc[i].type != PFM_REG_NONE; i++) {
-		p += sprintf(p, "PMD%-2d: %d 0x%lx 0x%lx\n", 
-				i,
-				pmd_desc[i].type, 
-				pmd_desc[i].dep_pmd[0], 
-				pmd_desc[i].dep_pmc[0]); 
-	}
-
-	for(i=0; pmc_desc[i].type != PFM_REG_NONE; i++) {
-		p += sprintf(p, "PMC%-2d: %d 0x%lx 0x%lx\n", 
-				i, 
-				pmc_desc[i].type, 
-				pmc_desc[i].dep_pmd[0], 
-				pmc_desc[i].dep_pmc[0]); 
-	}
-
 	return p - page;
 }
 
@@ -3038,7 +3032,6 @@
 	return len;
 }
 
-#ifdef CONFIG_SMP
 void
 pfm_syst_wide_update_task(struct task_struct *task, int mode)
 {
@@ -3051,8 +3044,6 @@
 	 */
 	ia64_psr(regs)->pp = mode ? __get_cpu_var(pfm_dcr_pp) : 0;
 }
-#endif
-
 
 void
 pfm_save_regs (struct task_struct *task)
@@ -3292,6 +3283,30 @@
 
 	owner = PMU_OWNER();
 	ctx   = task->thread.pfm_context;
+	t     = &task->thread;
+
+	/*
+	 * we restore ALL the debug registers to avoid picking up 
+	 * stale state.
+	 *
+	 * This must be done even when the task is still the owner
+	 * as the registers may have been modified via ptrace()
+	 * (not perfmon) by the previous task. 
+	 *
+	 * XXX: dealing with this in a lazy fashion requires modifications
+	 * to the way the the debug registers are managed. This is will done
+	 * in the next version of perfmon.
+	 */
+	if (ctx->ctx_fl_using_dbreg) {
+		for (i=0; i < pmu_conf.num_ibrs; i++) {
+			ia64_set_ibr(i, t->ibr[i]);
+		}
+		ia64_srlz_i();
+		for (i=0; i < pmu_conf.num_dbrs; i++) {
+			ia64_set_dbr(i, t->dbr[i]);
+		}
+		ia64_srlz_d();
+	}
 
 	/*
 	 * if we were the last user, then nothing to do except restore psr
@@ -3327,7 +3342,6 @@
 		pfm_fetch_regs(cpu, task, ctx);
 	}
 #endif
-	t = &task->thread;
 
 	/*
 	 * To avoid leaking information to the user level when psr.sp=0,
@@ -3357,21 +3371,6 @@
 		if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
 	}
 
-	/*
-	 * we restore ALL the debug registers to avoid picking up 
-	 * stale state.
-	 */
-	if (ctx->ctx_fl_using_dbreg) {
-		for (i=0; i < pmu_conf.num_ibrs; i++) {
-			ia64_set_ibr(i, t->ibr[i]);
-		}
-		ia64_srlz_i();
-		for (i=0; i < pmu_conf.num_dbrs; i++) {
-			ia64_set_dbr(i, t->dbr[i]);
-		}
-	}
-	ia64_srlz_d();
-
 	if (t->pmc[0] & ~0x1) {
 		pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
 	}
@@ -3542,12 +3541,8 @@
 
 		ia64_srlz_i();
 
-#ifdef CONFIG_SMP
 		__get_cpu_var(pfm_syst_wide) = 0;
 		__get_cpu_var(pfm_dcr_pp)    = 0;
-#else
-		pfm_tasklist_toggle_pp(0);
-#endif
 	} else  {
 
 		/* stop monitoring */
@@ -3766,18 +3761,12 @@
 	m = nctx->ctx_used_pmds[0] >> PMU_FIRST_COUNTER;
 	for(i = PMU_FIRST_COUNTER ; m ; m>>=1, i++) {
 		if ((m & 0x1) && pmu_conf.pmd_desc[i].type == PFM_REG_COUNTING) {
-			nctx->ctx_soft_pmds[i].val = nctx->ctx_soft_pmds[i].ival & ~pmu_conf.perf_ovfl_val;
-			thread->pmd[i]	      	   = nctx->ctx_soft_pmds[i].ival & pmu_conf.perf_ovfl_val;
+			nctx->ctx_soft_pmds[i].val = nctx->ctx_soft_pmds[i].lval & ~pmu_conf.perf_ovfl_val;
+			thread->pmd[i]	      	   = nctx->ctx_soft_pmds[i].lval & pmu_conf.perf_ovfl_val;
+		} else {
+			thread->pmd[i]	      	   = 0UL; /* reset to initial state */
 		}
-		/* what about the other pmds? zero or keep as is */
-
 	}
-	/*
-	 * clear BTB index register
-	 * XXX: CPU-model specific knowledge!
-	 */
-	thread->pmd[16] = 0;
-
 
 	nctx->ctx_fl_frozen    = 0;
 	nctx->ctx_ovfl_regs[0] = 0UL;
@@ -3947,7 +3936,8 @@
 		pfm_sessions.pfs_sys_session[ctx->ctx_cpu] = NULL;
 		pfm_sessions.pfs_sys_sessions--;
 		DBprintk(("freeing syswide session on CPU%ld\n", ctx->ctx_cpu));
-		/* update perfmon debug register counter */
+
+		/* update perfmon debug register usage counter */
 		if (ctx->ctx_fl_using_dbreg) {
 			if (pfm_sessions.pfs_sys_use_dbregs == 0) {
 				printk("perfmon: invalid release for [%d] sys_use_dbregs=0\n", task->pid);
@@ -3990,7 +3980,8 @@
 	 * Walk through the list and free the sampling buffer and psb
 	 */
 	while (psb) {
-		DBprintk(("[%d] freeing smpl @%p size %ld\n", current->pid, psb->psb_hdr, psb->psb_size));
+		DBprintk(("[%d] freeing smpl @%p size %ld\n", 
+			current->pid, psb->psb_hdr, psb->psb_size));
 
 		pfm_rvfree(psb->psb_hdr, psb->psb_size);
 		tmp = psb->psb_next;
@@ -4011,14 +4002,14 @@
 void
 pfm_cleanup_owners(struct task_struct *task)
 {
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	pfm_context_t *ctx;
 
 	DBprintk(("called by [%d] for [%d]\n", current->pid, task->pid));
 
 	read_lock(&tasklist_lock);
 
-	for_each_task(p) {
+	do_each_thread(g, p) {
 		/*
 		 * It is safe to do the 2-step test here, because thread.ctx
 		 * is cleaned up only in release_thread() and at that point
@@ -4056,7 +4047,8 @@
 
 			DBprintk(("done for notifier [%d] in [%d]\n", task->pid, p->pid));
 		}
-	}
+	} while_each_thread(g, p);
+
 	read_unlock(&tasklist_lock);
 
 	atomic_set(&task->thread.pfm_owners_check, 0);
@@ -4070,23 +4062,21 @@
 void
 pfm_cleanup_notifiers(struct task_struct *task)
 {
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	pfm_context_t *ctx;
 
 	DBprintk(("called by [%d] for [%d]\n", current->pid, task->pid));
 
 	read_lock(&tasklist_lock);
 
-	for_each_task(p) {
+	do_each_thread(g, p) {
 		/*
-		 * It is safe to do the 2-step test here, because thread.ctx
-		 * is cleaned up only in release_thread() and at that point
-		 * the task has been detached from the tasklist which is an
-		 * operation which uses the write_lock() on the tasklist_lock
-		 * so it cannot run concurrently to this loop. So we have the
-		 * guarantee that if we find p and it has a perfmon ctx then
-		 * it is going to stay like this for the entire execution of this
-		 * loop.
+		 * It is safe to do the 2-step test here, because thread.ctx is cleaned up
+		 * only in release_thread() and at that point the task has been detached
+		 * from the tasklist which is an operation which uses the write_lock() on
+		 * the tasklist_lock so it cannot run concurrently to this loop. So we
+		 * have the guarantee that if we find p and it has a perfmon ctx then it
+		 * is going to stay like this for the entire execution of this loop.
 		 */
 		ctx = p->thread.pfm_context;
 
@@ -4095,16 +4085,16 @@
 		if (ctx && ctx->ctx_notify_task == task) {
 			DBprintk(("trying for notifier [%d] in [%d]\n", task->pid, p->pid));
 			/*
-			 * the spinlock is required to take care of a race condition
-			 * with the send_sig_info() call. We must make sure that 
-			 * either the send_sig_info() completes using a valid task,
-			 * or the notify_task is cleared before the send_sig_info()
-			 * can pick up a stale value. Note that by the time this
-			 * function is executed the 'task' is already detached from the
-			 * tasklist. The problem is that the notifiers have a direct
-			 * pointer to it. It is okay to send a signal to a task in this
-			 * stage, it simply will have no effect. But it is better than sending
-			 * to a completely destroyed task or worse to a new task using the same
+			 * the spinlock is required to take care of a race condition with
+			 * the send_sig_info() call. We must make sure that either the
+			 * send_sig_info() completes using a valid task, or the
+			 * notify_task is cleared before the send_sig_info() can pick up a
+			 * stale value. Note that by the time this function is executed
+			 * the 'task' is already detached from the tasklist. The problem
+			 * is that the notifiers have a direct pointer to it. It is okay
+			 * to send a signal to a task in this stage, it simply will have
+			 * no effect. But it is better than sending to a completely
+			 * destroyed task or worse to a new task using the same
 			 * task_struct address.
 			 */
 			LOCK_CTX(ctx);
@@ -4115,7 +4105,8 @@
 
 			DBprintk(("done for notifier [%d] in [%d]\n", task->pid, p->pid));
 		}
-	}
+	} while_each_thread(g, p);
+
 	read_unlock(&tasklist_lock);
 
 	atomic_set(&task->thread.pfm_notifiers_check, 0);
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/process.c	Sat Sep 21 21:25:45 2002
@@ -81,6 +81,12 @@
 }
 
 void
+dump_stack (void)
+{
+	show_stack(NULL);
+}
+
+void
 show_regs (struct pt_regs *regs)
 {
 	unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
@@ -248,18 +254,15 @@
  *	|                     | <-- sp (lowest addr)
  *	+---------------------+
  *
- * Note: if we get called through kernel_thread() then the memory
- * above "(highest addr)" is valid kernel stack memory that needs to
- * be copied as well.
- *
- * Observe that we copy the unat values that are in pt_regs and
- * switch_stack.  Spilling an integer to address X causes bit N in
- * ar.unat to be set to the NaT bit of the register, with N=(X &
- * 0x1ff)/8.  Thus, copying the unat value preserves the NaT bits ONLY
- * if the pt_regs structure in the parent is congruent to that of the
- * child, modulo 512.  Since the stack is page aligned and the page
- * size is at least 4KB, this is always the case, so there is nothing
- * to worry about.
+ * Note: if we get called through kernel_thread() then the memory above "(highest addr)"
+ * is valid kernel stack memory that needs to be copied as well.
+ *
+ * Observe that we copy the unat values that are in pt_regs and switch_stack.  Spilling an
+ * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register,
+ * with N=(X & 0x1ff)/8.  Thus, copying the unat value preserves the NaT bits ONLY if the
+ * pt_regs structure in the parent is congruent to that of the child, modulo 512.  Since
+ * the stack is page aligned and the page size is at least 4KB, this is always the case,
+ * so there is nothing to worry about.
  */
 int
 copy_thread (int nr, unsigned long clone_flags,
@@ -300,6 +303,8 @@
 	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
 
 	if (user_mode(child_ptregs)) {
+		if (clone_flags & CLONE_SETTLS)
+			child_ptregs->r13 = regs->r16;	/* see sys_clone2() in entry.S */
 		if (user_stack_base) {
 			child_ptregs->r12 = user_stack_base + user_stack_size - 16;
 			child_ptregs->ar_bspstore = user_stack_base;
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/kernel/ptrace.c	Sat Sep 21 21:25:48 2002
@@ -474,7 +474,7 @@
 {
 	struct switch_stack *sw;
 	unsigned long urbs_end;
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	struct mm_struct *mm;
 	struct pt_regs *pt;
 	long multi_threaded;
@@ -495,7 +495,7 @@
 	} else {
 		read_lock(&tasklist_lock);
 		{
-			for_each_task(p) {
+			do_each_thread(g, p) {
 				if (p->mm == mm && p->state != TASK_RUNNING) {
 					sw = (struct switch_stack *) (p->thread.ksp + 16);
 					pt = ia64_task_regs(p);
@@ -504,7 +504,7 @@
 					if (make_writable)
 						user_flushrs(p, pt);
 				}
-			}
+			} while_each_thread(g, p);
 		}
 		read_unlock(&tasklist_lock);
 	}
diff -Nru a/arch/ia64/kernel/semaphore.c b/arch/ia64/kernel/semaphore.c
--- a/arch/ia64/kernel/semaphore.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/semaphore.c	Sat Sep 21 21:25:45 2002
@@ -15,8 +15,8 @@
  * test if they need to do any extra work (up needs to do something
  * only if count was negative before the increment operation.
  *
- * "sleepers" and the contention routine ordering is protected by the
- * semaphore spinlock.
+ * "sleeping" and the contention routine ordering is protected
+ * by the spinlock in the semaphore's waitqueue head.
  *
  * Note that these functions are only called when there is contention
  * on the lock, and as such all this is the "non-critical" part of the
@@ -44,40 +44,42 @@
 	wake_up(&sem->wait);
 }
 
-static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
-
 void
 __down (struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
+	unsigned long flags;
+
 	tsk->state = TASK_UNINTERRUPTIBLE;
-	add_wait_queue_exclusive(&sem->wait, &wait);
+	spin_lock_irqsave(&sem->wait.lock, flags);
+	add_wait_queue_exclusive_locked(&sem->wait, &wait);
 
-	spin_lock_irq(&semaphore_lock);
 	sem->sleepers++;
 	for (;;) {
 		int sleepers = sem->sleepers;
 
 		/*
 		 * Add "everybody else" into it. They aren't
-		 * playing, because we own the spinlock.
+		 * playing, because we own the spinlock in
+		 * the wait_queue_head.
 		 */
 		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
 			sem->sleepers = 0;
 			break;
 		}
 		sem->sleepers = 1;	/* us - see -1 above */
-		spin_unlock_irq(&semaphore_lock);
+		spin_unlock_irqrestore(&sem->wait.lock, flags);
 
 		schedule();
+
+		spin_lock_irqsave(&sem->wait.lock, flags);
 		tsk->state = TASK_UNINTERRUPTIBLE;
-		spin_lock_irq(&semaphore_lock);
 	}
-	spin_unlock_irq(&semaphore_lock);
-	remove_wait_queue(&sem->wait, &wait);
+	remove_wait_queue_locked(&sem->wait, &wait);
+	wake_up_locked(&sem->wait);
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
 	tsk->state = TASK_RUNNING;
-	wake_up(&sem->wait);
 }
 
 int
@@ -86,10 +88,12 @@
 	int retval = 0;
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
+	unsigned long flags;
+
 	tsk->state = TASK_INTERRUPTIBLE;
-	add_wait_queue_exclusive(&sem->wait, &wait);
+	spin_lock_irqsave(&sem->wait.lock, flags);
+	add_wait_queue_exclusive_locked(&sem->wait, &wait);
 
-	spin_lock_irq(&semaphore_lock);
 	sem->sleepers ++;
 	for (;;) {
 		int sleepers = sem->sleepers;
@@ -110,25 +114,27 @@
 
 		/*
 		 * Add "everybody else" into it. They aren't
-		 * playing, because we own the spinlock. The
-		 * "-1" is because we're still hoping to get
-		 * the lock.
+		 * playing, because we own the spinlock in
+		 * wait_queue_head. The "-1" is because we're
+		 * still hoping to get the semaphore.
 		 */
 		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
 			sem->sleepers = 0;
 			break;
 		}
 		sem->sleepers = 1;	/* us - see -1 above */
-		spin_unlock_irq(&semaphore_lock);
+		spin_unlock_irqrestore(&sem->wait.lock, flags);
 
 		schedule();
+
+		spin_lock_irqsave(&sem->wait.lock, flags);
 		tsk->state = TASK_INTERRUPTIBLE;
-		spin_lock_irq(&semaphore_lock);
 	}
-	spin_unlock_irq(&semaphore_lock);
+	remove_wait_queue_locked(&sem->wait, &wait);
+	wake_up_locked(&sem->wait);
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
+
 	tsk->state = TASK_RUNNING;
-	remove_wait_queue(&sem->wait, &wait);
-	wake_up(&sem->wait);
 	return retval;
 }
 
@@ -142,17 +148,19 @@
 	unsigned long flags;
 	int sleepers;
 
-	spin_lock_irqsave(&semaphore_lock, flags);
+	spin_lock_irqsave(&sem->wait.lock, flags);
 	sleepers = sem->sleepers + 1;
 	sem->sleepers = 0;
 
 	/*
 	 * Add "everybody else" and us into it. They aren't
-	 * playing, because we own the spinlock.
+	 * playing, because we own the spinlock in the
+	 * wait_queue_head.
 	 */
-	if (!atomic_add_negative(sleepers, &sem->count))
-		wake_up(&sem->wait);
+	if (!atomic_add_negative(sleepers, &sem->count)) {
+		wake_up_locked(&sem->wait);
+	}
 
-	spin_unlock_irqrestore(&semaphore_lock, flags);
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
 	return 1;
 }
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/signal.c	Sat Sep 21 21:25:45 2002
@@ -354,6 +354,15 @@
 	return err;
 }
 
+/*
+ * Check whether the register-backing store is already on the signal stack.
+ */
+static inline int
+rbs_on_sig_stack (unsigned long bsp)
+{
+	return (bsp - current->sas_ss_sp < current->sas_ss_size);
+}
+
 static long
 setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	     struct sigscratch *scr)
@@ -366,10 +375,17 @@
 
 	frame = (void *) scr->pt.r12;
 	tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section);
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack((unsigned long) frame)) {
-		new_rbs  = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
-		frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
-				  & ~(STACK_ALIGN - 1));
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		/*
+		 * We need to check the memory and register stacks separately, because
+		 * they're switched separately (memory stack is switched in the kernel,
+		 * register stack is switched in the signal trampoline).
+		 */
+		if (!on_sig_stack((unsigned long) frame))
+			frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
+					  & ~(STACK_ALIGN - 1));
+		if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
+			new_rbs  = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
 	}
 	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
 
@@ -460,7 +476,6 @@
 long
 ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 {
-	struct signal_struct *sig;
 	struct k_sigaction *ka;
 	siginfo_t info;
 	long restart = in_syscall;
@@ -487,7 +502,7 @@
 		}
 	} else
 #endif
-	if (scr->pt.r10 != -1) {
+	if (scr->pt.r10 != -1)
 		/*
 		 * A system calls has to be restarted only if one of the error codes
 		 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned.  If r10
@@ -495,101 +510,14 @@
 		 * restart the syscall, so we can clear the "restart" flag here.
 		 */
 		restart = 0;
-	}
-
-	for (;;) {
-		unsigned long signr;
 
-		spin_lock_irq(&current->sigmask_lock);
-		signr = dequeue_signal(&current->blocked, &info);
-		spin_unlock_irq(&current->sigmask_lock);
+	while (1) {
+		int signr = get_signal_to_deliver(&info, &scr->pt);
 
-		if (!signr)
+		if (signr <= 0)
 			break;
 
-		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
-			/* Let the debugger run.  */
-			current->exit_code = signr;
-			current->thread.siginfo = &info;
-			current->state = TASK_STOPPED;
-			notify_parent(current, SIGCHLD);
-			schedule();
-
-			signr = current->exit_code;
-			current->thread.siginfo = 0;
-
-			/* We're back.  Did the debugger cancel the sig?  */
-			if (!signr)
-				continue;
-			current->exit_code = 0;
-
-			/* The debugger continued.  Ignore SIGSTOP.  */
-			if (signr == SIGSTOP)
-				continue;
-
-			/* Update the siginfo structure.  Is this good?  */
-			if (signr != info.si_signo) {
-				info.si_signo = signr;
-				info.si_errno = 0;
-				info.si_code = SI_USER;
-				info.si_pid = current->parent->pid;
-				info.si_uid = current->parent->uid;
-			}
-
-			/* If the (new) signal is now blocked, requeue it.  */
-			if (sigismember(&current->blocked, signr)) {
-				send_sig_info(signr, &info, current);
-				continue;
-			}
-		}
-
 		ka = &current->sig->action[signr - 1];
-		if (ka->sa.sa_handler == SIG_IGN) {
-			if (signr != SIGCHLD)
-				continue;
-			/* Check for SIGCHLD: it's special.  */
-			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
-				/* nothing */;
-			continue;
-		}
-
-		if (ka->sa.sa_handler == SIG_DFL) {
-			int exit_code = signr;
-
-			/* Init gets no signals it doesn't want.  */
-			if (current->pid == 1)
-				continue;
-
-			switch (signr) {
-			      case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
-				continue;
-
-			      case SIGTSTP: case SIGTTIN: case SIGTTOU:
-				if (is_orphaned_pgrp(current->pgrp))
-					continue;
-				/* FALLTHRU */
-
-			      case SIGSTOP:
-				current->state = TASK_STOPPED;
-				current->exit_code = signr;
-				sig = current->parent->sig;
-				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
-					notify_parent(current, SIGCHLD);
-				schedule();
-				continue;
-
-			      case SIGQUIT: case SIGILL: case SIGTRAP:
-			      case SIGABRT: case SIGFPE: case SIGSEGV:
-			      case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
-				if (do_coredump(signr, &scr->pt))
-					exit_code |= 0x80;
-				/* FALLTHRU */
-
-			      default:
-				sig_exit(signr, exit_code, &info);
-				/* NOTREACHED */
-			}
-		}
 
 		if (restart) {
 			switch (errno) {
@@ -601,7 +529,7 @@
 						scr->pt.r8 = -EINTR;
 					else
 #endif
-					scr->pt.r8 = EINTR;
+						scr->pt.r8 = EINTR;
 					/* note: scr->pt.r10 is already -1 */
 					break;
 				}
@@ -612,13 +540,14 @@
 					scr->pt.cr_iip -= 2;
 				} else
 #endif
-				ia64_decrement_ip(&scr->pt);
+					ia64_decrement_ip(&scr->pt);
 			}
 		}
 
-		/* Whee!  Actually deliver the signal.  If the
-		   delivery failed, we need to continue to iterate in
-		   this loop so we can deliver the SIGSEGV... */
+		/*
+		 * Whee!  Actually deliver the signal.  If the delivery failed, we need to
+		 * continue to iterate in this loop so we can deliver the SIGSEGV...
+		 */
 		if (handle_signal(signr, ka, &info, oldset, scr))
 			return 1;
 	}
@@ -634,9 +563,8 @@
 			} else
 #endif
 			/*
-			 * Note: the syscall number is in r15 which is
-			 * saved in pt_regs so all we need to do here
-			 * is adjust ip so that the "break"
+			 * Note: the syscall number is in r15 which is saved in pt_regs so
+			 * all we need to do here is adjust ip so that the "break"
 			 * instruction gets re-executed.
 			 */
 			ia64_decrement_ip(&scr->pt);
diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
--- a/arch/ia64/kernel/smpboot.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/smpboot.c	Sat Sep 21 21:25:45 2002
@@ -257,31 +257,6 @@
 	local_cpu_data->prof_multiplier = 1;
 }
 
-/*
- * Architecture specific routine called by the kernel just before init is
- * fired off. This allows the BP to have everything in order [we hope].
- * At the end of this all the APs will hit the system scheduling and off
- * we go. Each AP will jump through the kernel
- * init into idle(). At this point the scheduler will one day take over
- * and give them jobs to do. smp_callin is a standard routine
- * we use to track CPUs as they power up.
- */
-
-static volatile atomic_t smp_commenced = ATOMIC_INIT(0);
-
-static void __init
-smp_commence (void)
-{
-	/*
-	 * Lets the callins below out of their loop.
-	 */
-	Dprintk("Setting commenced=1, go go go\n");
-
-	wmb();
-	atomic_set(&smp_commenced, 1);
-}
-
-
 static void __init
 smp_callin (void)
 {
@@ -361,7 +336,7 @@
 	 * don't care about the eip and regs settings since we'll never reschedule the
 	 * forked task.
 	 */
-	return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0);
+	return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL);
 }
 
 static int __init
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/sys_ia64.c	Sat Sep 21 21:25:45 2002
@@ -19,6 +19,12 @@
 #include <asm/shmparam.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_HUGETLB_PAGE
+# define SHMLBA_HPAGE		HPAGE_SIZE
+# define COLOR_HALIGN(addr)	(((addr) + SHMLBA_HPAGE - 1) & ~(SHMLBA_HPAGE - 1))
+# define TASK_HPAGE_BASE	((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE)
+#endif
+
 unsigned long
 arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
 			unsigned long pgoff, unsigned long flags)
@@ -56,16 +62,14 @@
 }
 
 asmlinkage long
-ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6,
-		  long arg7, long stack)
+ia64_getpriority (int which, int who)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
 	extern long sys_getpriority (int, int);
 	long prio;
 
 	prio = sys_getpriority(which, who);
 	if (prio >= 0) {
-		regs->r8 = 0;	/* ensure negative priority is not mistaken as error code */
+		force_successful_syscall_return();
 		prio = 20 - prio;
 	}
 	return prio;
@@ -79,10 +83,8 @@
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6,
-	    long arg7, long stack)
+ia64_shmat (int shmid, void *shmaddr, int shmflg)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long raddr;
 	int retval;
 
@@ -90,16 +92,14 @@
 	if (retval < 0)
 		return retval;
 
-	regs->r8 = 0;	/* ensure negative addresses are not mistaken as an error code */
+	force_successful_syscall_return();
 	return raddr;
 }
 
 asmlinkage unsigned long
-ia64_brk (unsigned long brk, long arg1, long arg2, long arg3,
-	  long arg4, long arg5, long arg6, long arg7, long stack)
+ia64_brk (unsigned long brk)
 {
 	extern int vm_enough_memory (long pages);
-	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long rlim, retval, newbrk, oldbrk;
 	struct mm_struct *mm = current->mm;
 
@@ -145,7 +145,7 @@
 out:
 	retval = mm->brk;
 	up_write(&mm->mmap_sem);
-	regs->r8 = 0;		/* ensure large retval isn't mistaken as error code */
+	force_successful_syscall_return();
 	return retval;
 }
 
@@ -222,32 +222,98 @@
  * of) files that are larger than the address space of the CPU.
  */
 asmlinkage unsigned long
-sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff,
-	   long arg6, long arg7, long stack)
+sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
-
 	addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
 	if (!IS_ERR((void *) addr))
-		regs->r8 = 0;	/* ensure large addresses are not mistaken as failures... */
+		force_successful_syscall_return();
 	return addr;
 }
 
 asmlinkage unsigned long
-sys_mmap (unsigned long addr, unsigned long len, int prot, int flags,
-	  int fd, long off, long arg6, long arg7, long stack)
+sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, long off)
 {
-	struct pt_regs *regs = (struct pt_regs *) &stack;
-
 	if ((off & ~PAGE_MASK) != 0)
 		return -EINVAL;
 
 	addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 	if (!IS_ERR((void *) addr))
-		regs->r8 = 0;	/* ensure large addresses are not mistaken as failures... */
+		force_successful_syscall_return();
 	return addr;
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+
+asmlinkage unsigned long
+sys_alloc_hugepages (int key, unsigned long addr, size_t len, int prot, int flag)
+{
+	struct mm_struct *mm = current->mm;
+	long retval;
+	extern int alloc_hugetlb_pages (int, unsigned long, unsigned long, int, int);
+
+	if ((key < 0) || (len & (HPAGE_SIZE - 1)))
+		return -EINVAL;
+
+	if (addr && ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))))
+		addr = TASK_HPAGE_BASE;
+
+	if (!addr)
+		addr = TASK_HPAGE_BASE;
+	down_write(&mm->mmap_sem);
+	{
+		retval = arch_get_unmapped_area(NULL, COLOR_HALIGN(addr), len, 0, 0);
+		if (retval != -ENOMEM)
+			retval = alloc_hugetlb_pages(key, retval, len, prot, flag);
+	}
+	up_write(&mm->mmap_sem);
+
+	if (IS_ERR((void *) retval))
+		return retval;
+
+	force_successful_syscall_return();
+	return retval;
+}
+
+asmlinkage int
+sys_free_hugepages (unsigned long  addr)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	extern int free_hugepages(struct vm_area_struct *);
+	int retval;
+
+	vma = find_vma(mm, addr);
+	if (!vma || !is_vm_hugetlb_page(vma) || (vma->vm_start != addr))
+		return -EINVAL;
+
+	down_write(&mm->mmap_sem);
+	{
+		spin_lock(&mm->page_table_lock);
+		{
+			retval = free_hugepages(vma);
+		}
+		spin_unlock(&mm->page_table_lock);
+	}
+	up_write(&mm->mmap_sem);
+	return retval;
+}
+
+#else /* !CONFIG_HUGETLB_PAGE */
+
+asmlinkage unsigned long
+sys_alloc_hugepages (int key, size_t addr, unsigned long len, int prot, int flag)
+{
+	return -ENOSYS;
+}
+
+asmlinkage unsigned long
+sys_free_hugepages (unsigned long  addr)
+{
+	return -ENOSYS;
+}
+
+#endif /* !CONFIG_HUGETLB_PAGE */
+
 asmlinkage long
 sys_vm86 (long arg0, long arg1, long arg2, long arg3)
 {
@@ -256,16 +322,14 @@
 }
 
 asmlinkage unsigned long
-ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
-		    long arg4, long arg5, long arg6, long arg7, long stack)
+ia64_create_module (const char *name_user, size_t size)
 {
 	extern unsigned long sys_create_module (const char *, size_t);
-	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long   addr;
 
 	addr = sys_create_module (name_user, size);
 	if (!IS_ERR((void *) addr))
-		regs->r8 = 0;	/* ensure large addresses are not mistaken as failures... */
+		force_successful_syscall_return();
 	return addr;
 }
 
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/kernel/time.c	Sat Sep 21 21:25:45 2002
@@ -104,7 +104,8 @@
 			tv->tv_sec--;
 		}
 
-		xtime = *tv;
+		xtime.tv_sec = tv->tv_sec;
+		xtime.tv_nsec = 1000 * tv->tv_usec;
 		time_adjust = 0;		/* stop active adjtime() */
 		time_status |= STA_UNSYNC;
 		time_maxerror = NTP_PHASE_LIMIT;
@@ -135,7 +136,7 @@
 		} while (cmpxchg(&last_time_offset, old, usec) != old);
 
 		sec = xtime.tv_sec;
-		usec += xtime.tv_usec;
+		usec += xtime.tv_nsec / 1000;
 	}
 	read_unlock_irqrestore(&xtime_lock, flags);
 
diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
--- a/arch/ia64/lib/Makefile	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/lib/Makefile	Sat Sep 21 21:25:48 2002
@@ -15,6 +15,7 @@
 
 obj-$(CONFIG_ITANIUM)	+= copy_page.o copy_user.o memcpy.o
 obj-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
+obj-$(CONFIG_PERFMON)	+= carta_random.o
 
 IGNORE_FLAGS_OBJS =	__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
 			__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
diff -Nru a/arch/ia64/lib/carta_random.S b/arch/ia64/lib/carta_random.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/lib/carta_random.S	Sat Sep 21 21:25:48 2002
@@ -0,0 +1,54 @@
+/*
+ * Fast, simple, yet decent quality random number generator based on
+ * a paper by David G. Carta ("Two Fast Implementations of the
+ * `Minimal Standard' Random Number Generator," Communications of the
+ * ACM, January, 1990).
+ *
+ * Copyright (C) 2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/asmmacro.h>
+
+#define a	r2
+#define m	r3
+#define lo	r8
+#define hi	r9
+#define t0	r16
+#define t1	r17
+#define	seed	r32
+
+GLOBAL_ENTRY(carta_random32)
+	movl	a = (16807 << 16) | 16807
+	;;
+	pmpyshr2.u t0 = a, seed, 0
+	pmpyshr2.u t1 = a, seed, 16
+	;;
+	unpack2.l t0 = t1, t0
+	dep	m = -1, r0, 0, 31
+	;;
+	zxt4	lo = t0
+	shr.u	hi = t0, 32
+	;;
+	dep	t0 = 0, hi, 15, 49	// t0 = (hi & 0x7fff)
+	;;
+	shl	t0 = t0, 16		// t0 = (hi & 0x7fff) << 16
+	shr	t1 = hi, 15		// t1 = (hi >> 15)
+	;;
+	add	lo = lo, t0
+	;;
+	cmp.gtu	p6, p0 = lo, m
+	;;
+(p6)	and	lo = lo, m
+	;;
+(p6)	add	lo = 1, lo
+	;;
+	add	lo = lo, t1
+	;;
+	cmp.gtu p6, p0 = lo, m
+	;;
+(p6)	and	lo = lo, m
+	;;
+(p6)	add	lo = 1, lo
+	br.ret.sptk.many rp
+END(carta_random32)
diff -Nru a/arch/ia64/mm/Makefile b/arch/ia64/mm/Makefile
--- a/arch/ia64/mm/Makefile	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/mm/Makefile	Sat Sep 21 21:25:45 2002
@@ -7,8 +7,7 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-O_TARGET := mm.o
-
 obj-y	 := init.o fault.o tlb.o extable.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/mm/hugetlbpage.c	Sat Sep 21 21:25:48 2002
@@ -0,0 +1,546 @@
+/*
+ * IA-64 Huge TLB Page Support for Kernel.
+ *
+ * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+
+#include <asm/mman.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+static struct vm_operations_struct hugetlb_vm_ops;
+struct list_head htlbpage_freelist;
+spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
+extern long htlbpagemem;
+
+static void zap_hugetlb_resources (struct vm_area_struct *);
+
+#define MAX_ID 	32
+struct htlbpagekey {
+	struct inode *in;
+	int key;
+} htlbpagek[MAX_ID];
+
+static struct inode *
+find_key_inode(int key)
+{
+	int i;
+
+	for (i = 0; i < MAX_ID; i++) {
+		if (htlbpagek[i].key == key)
+			return (htlbpagek[i].in);
+	}
+	return NULL;
+}
+
+static struct page *
+alloc_hugetlb_page (void)
+{
+	struct list_head *curr, *head;
+	struct page *page;
+
+	spin_lock(&htlbpage_lock);
+
+	head = &htlbpage_freelist;
+	curr = head->next;
+
+	if (curr == head) {
+		spin_unlock(&htlbpage_lock);
+		return NULL;
+	}
+	page = list_entry(curr, struct page, list);
+	list_del(curr);
+	htlbpagemem--;
+	spin_unlock(&htlbpage_lock);
+	set_page_count(page, 1);
+	memset(page_address(page), 0, HPAGE_SIZE);
+	return page;
+}
+
+static void
+free_hugetlb_page (struct page *page)
+{
+	spin_lock(&htlbpage_lock);
+	if ((page->mapping != NULL) && (page_count(page) == 2)) {
+		struct inode *inode = page->mapping->host;
+		int i;
+
+		ClearPageDirty(page);
+		remove_from_page_cache(page);
+		set_page_count(page, 1);
+		if ((inode->i_size -= HPAGE_SIZE) == 0) {
+			for (i = 0; i < MAX_ID; i++)
+				if (htlbpagek[i].key == inode->i_ino) {
+					htlbpagek[i].key = 0;
+					htlbpagek[i].in = NULL;
+					break;
+				}
+			kfree(inode);
+		}
+	}
+	if (put_page_testzero(page)) {
+		list_add(&page->list, &htlbpage_freelist);
+		htlbpagemem++;
+	}
+	spin_unlock(&htlbpage_lock);
+}
+
+static pte_t *
+huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
+{
+	unsigned long taddr = htlbpage_to_page(addr);
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte = NULL;
+
+	pgd = pgd_offset(mm, taddr);
+	pmd = pmd_alloc(mm, pgd, taddr);
+	if (pmd)
+		pte = pte_alloc_map(mm, pmd, taddr);
+	return pte;
+}
+
+static pte_t *
+huge_pte_offset (struct mm_struct *mm, unsigned long addr)
+{
+	unsigned long taddr = htlbpage_to_page(addr);
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte = NULL;
+
+	pgd = pgd_offset(mm, taddr);
+	pmd = pmd_offset(pgd, taddr);
+	pte = pte_offset_map(pmd, taddr);
+	return pte;
+}
+
+#define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
+
+static void
+set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
+	      struct page *page, pte_t * page_table, int write_access)
+{
+	pte_t entry;
+
+	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	if (write_access) {
+		entry =
+		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	} else
+		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+	entry = pte_mkyoung(entry);
+	mk_pte_huge(entry);
+	set_pte(page_table, entry);
+	return;
+}
+
+static int
+anon_get_hugetlb_page (struct mm_struct *mm, struct vm_area_struct *vma,
+		       int write_access, pte_t * page_table)
+{
+	struct page *page;
+
+	page = alloc_hugetlb_page();
+	if (page == NULL)
+		return -1;
+	set_huge_pte(mm, vma, page, page_table, write_access);
+	return 1;
+}
+
+static int
+make_hugetlb_pages_present (unsigned long addr, unsigned long end, int flags)
+{
+	int write;
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	pte_t *pte;
+
+	vma = find_vma(mm, addr);
+	if (!vma)
+		goto out_error1;
+
+	write = (vma->vm_flags & VM_WRITE) != 0;
+	if ((vma->vm_end - vma->vm_start) & (HPAGE_SIZE - 1))
+		goto out_error1;
+	spin_lock(&mm->page_table_lock);
+	do {
+		pte = huge_pte_alloc(mm, addr);
+		if ((pte) && (pte_none(*pte))) {
+			if (anon_get_hugetlb_page(mm, vma, write ? VM_WRITE : VM_READ, pte) == -1)
+				goto out_error;
+		} else
+			goto out_error;
+		addr += HPAGE_SIZE;
+	} while (addr < end);
+	spin_unlock(&mm->page_table_lock);
+	vma->vm_flags |= (VM_HUGETLB | VM_RESERVED);
+	if (flags & MAP_PRIVATE)
+		vma->vm_flags |= VM_DONTCOPY;
+	vma->vm_ops = &hugetlb_vm_ops;
+	return 0;
+out_error:
+	if (addr > vma->vm_start) {
+		vma->vm_end = addr;
+		zap_hugetlb_resources(vma);
+		vma->vm_end = end;
+	}
+	spin_unlock(&mm->page_table_lock);
+out_error1:
+	return -1;
+}
+
+int
+copy_hugetlb_page_range (struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma)
+{
+	pte_t *src_pte, *dst_pte, entry;
+	struct page *ptepage;
+	unsigned long addr = vma->vm_start;
+	unsigned long end = vma->vm_end;
+
+	while (addr < end) {
+		dst_pte = huge_pte_alloc(dst, addr);
+		if (!dst_pte)
+			goto nomem;
+		src_pte = huge_pte_offset(src, addr);
+		entry = *src_pte;
+		ptepage = pte_page(entry);
+		get_page(ptepage);
+		set_pte(dst_pte, entry);
+		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		addr += HPAGE_SIZE;
+	}
+	return 0;
+
+      nomem:
+	return -ENOMEM;
+}
+
+int
+follow_hugetlb_page (struct mm_struct *mm, struct vm_area_struct *vma,
+		     struct page **pages, struct vm_area_struct **vmas,
+		     unsigned long *st, int *length, int i)
+{
+	pte_t *ptep, pte;
+	unsigned long start = *st;
+	unsigned long pstart;
+	int len = *length;
+	struct page *page;
+
+	do {
+		pstart = start & HPAGE_MASK;
+		ptep = huge_pte_offset(mm, start);
+		pte = *ptep;
+
+back1:
+		page = pte_page(pte);
+		if (pages) {
+			page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT);
+			pages[i] = page;
+		}
+		if (vmas)
+			vmas[i] = vma;
+		i++;
+		len--;
+		start += PAGE_SIZE;
+		if (((start & HPAGE_MASK) == pstart) && len
+		    && (start < vma->vm_end))
+			goto back1;
+	} while (len && start < vma->vm_end);
+	*length = len;
+	*st = start;
+	return i;
+}
+
+static void
+zap_hugetlb_resources (struct vm_area_struct *mpnt)
+{
+	struct mm_struct *mm = mpnt->vm_mm;
+	unsigned long len, addr, end;
+	pte_t *ptep;
+	struct page *page;
+
+	addr = mpnt->vm_start;
+	end = mpnt->vm_end;
+	len = end - addr;
+	do {
+		ptep = huge_pte_offset(mm, addr);
+		page = pte_page(*ptep);
+		pte_clear(ptep);
+		free_hugetlb_page(page);
+		addr += HPAGE_SIZE;
+	} while (addr < end);
+	mm->rss -= (len >> PAGE_SHIFT);
+	mpnt->vm_ops = NULL;
+	flush_tlb_range(mpnt, end - len, end);
+}
+
+static void
+unlink_vma (struct vm_area_struct *mpnt)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+
+	vma = mm->mmap;
+	if (vma == mpnt) {
+		mm->mmap = vma->vm_next;
+	} else {
+		while (vma->vm_next != mpnt) {
+			vma = vma->vm_next;
+		}
+		vma->vm_next = mpnt->vm_next;
+	}
+	rb_erase(&mpnt->vm_rb, &mm->mm_rb);
+	mm->mmap_cache = NULL;
+	mm->map_count--;
+}
+
+int
+free_hugepages (struct vm_area_struct *mpnt)
+{
+	unlink_vma(mpnt);
+	zap_hugetlb_resources(mpnt);
+	kmem_cache_free(vm_area_cachep, mpnt);
+	return 1;
+}
+
+static struct inode *
+set_new_inode (unsigned long len, int prot, int flag, int key)
+{
+	struct inode *inode;
+	int i;
+
+	for (i = 0; i < MAX_ID; i++) {
+		if (htlbpagek[i].key == 0)
+			break;
+	}
+	if (i == MAX_ID)
+		return NULL;
+	inode = kmalloc(sizeof (struct inode), GFP_ATOMIC);
+	if (inode == NULL)
+		return NULL;
+
+	inode_init_once(inode);
+	atomic_inc(&inode->i_writecount);
+	inode->i_mapping = &inode->i_data;
+	inode->i_mapping->host = inode;
+	inode->i_ino = (unsigned long) key;
+
+	htlbpagek[i].key = key;
+	htlbpagek[i].in = inode;
+	inode->i_uid = current->fsuid;
+	inode->i_gid = current->fsgid;
+	inode->i_mode = prot;
+	inode->i_size = len;
+	return inode;
+}
+
+static int
+check_size_prot (struct inode *inode, unsigned long len, int prot, int flag)
+{
+	if (inode->i_uid != current->fsuid)
+		return -1;
+	if (inode->i_gid != current->fsgid)
+		return -1;
+	if (inode->i_size != len)
+		return -1;
+	return 0;
+}
+
+int
+alloc_shared_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	struct inode *inode;
+	struct address_space *mapping;
+	struct page *page;
+	int idx;
+	int retval = -ENOMEM;
+	int newalloc = 0;
+
+try_again:
+	spin_lock(&htlbpage_lock);
+	inode = find_key_inode(key);
+	if (inode == NULL) {
+		if (!capable(CAP_SYS_ADMIN)) {
+			if (!in_group_p(0)) {
+				retval = -EPERM;
+				goto out_err;
+			}
+		}
+		if (!(flag & IPC_CREAT)) {
+			retval = -ENOENT;
+			goto out_err;
+		}
+		inode = set_new_inode(len, prot, flag, key);
+		if (inode == NULL)
+			goto out_err;
+		newalloc = 1;
+	} else {
+		if (check_size_prot(inode, len, prot, flag) < 0) {
+			retval =  -EINVAL;
+			goto out_err;
+		}
+		else if (atomic_read(&inode->i_writecount)) {
+			spin_unlock(&htlbpage_lock);
+			goto try_again;
+		}
+	}
+	spin_unlock(&htlbpage_lock);
+	mapping = inode->i_mapping;
+
+	addr = do_mmap_pgoff(NULL, addr, len, (unsigned long) prot,
+			     MAP_NORESERVE|MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0);
+	if (IS_ERR((void *) addr))
+		goto freeinode;
+
+	vma = find_vma(mm, addr);
+	if (!vma) {
+		retval = -EINVAL;
+		goto freeinode;
+	}
+
+	spin_lock(&mm->page_table_lock);
+	do {
+		pte_t *pte = huge_pte_alloc(mm, addr);
+		if ((pte) && (pte_none(*pte))) {
+			idx = (addr - vma->vm_start) >> HPAGE_SHIFT;
+			page = find_get_page(mapping, idx);
+			if (page == NULL) {
+				page = alloc_hugetlb_page();
+				if (page == NULL)
+					goto out;
+				add_to_page_cache(page, mapping, idx);
+			}
+			set_huge_pte(mm, vma, page, pte,
+				     (vma->vm_flags & VM_WRITE));
+		} else
+			goto out;
+		addr += HPAGE_SIZE;
+	} while (addr < vma->vm_end);
+	retval = 0;
+	vma->vm_flags |= (VM_HUGETLB | VM_RESERVED);
+	vma->vm_ops = &hugetlb_vm_ops;
+	spin_unlock(&mm->page_table_lock);
+	spin_lock(&htlbpage_lock);
+	atomic_set(&inode->i_writecount, 0);
+	spin_unlock(&htlbpage_lock);
+	return retval;
+out:
+	if (addr > vma->vm_start) {
+		unsigned long raddr = vma->vm_end;
+		vma->vm_end = addr;
+		zap_hugetlb_resources(vma);
+		vma->vm_end = raddr;
+	}
+	spin_unlock(&mm->page_table_lock);
+	do_munmap(mm, vma->vm_start, len);
+	if (newalloc)
+		goto freeinode;
+	return retval;
+
+out_err:
+	spin_unlock(&htlbpage_lock);
+freeinode:
+	if (newalloc) {
+		for (idx = 0; idx < MAX_ID; idx++)
+			if (htlbpagek[idx].key == inode->i_ino) {
+				htlbpagek[idx].key = 0;
+				htlbpagek[idx].in = NULL;
+				break;
+			}
+		kfree(inode);
+	}
+	return retval;
+}
+
+static int
+alloc_private_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag)
+{
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (!in_group_p(0))
+			return -EPERM;
+	}
+	addr = do_mmap_pgoff(NULL, addr, len, prot,
+			     MAP_NORESERVE | MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0);
+	if (IS_ERR((void *) addr))
+		return -ENOMEM;
+	if (make_hugetlb_pages_present(addr, (addr + len), flag) < 0) {
+		do_munmap(current->mm, addr, len);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+int
+alloc_hugetlb_pages (int key, unsigned long addr, unsigned long len, int prot, int flag)
+{
+	if (key > 0)
+		return alloc_shared_hugetlb_pages(key, addr, len, prot, flag);
+	else
+		return alloc_private_hugetlb_pages(key, addr, len, prot, flag);
+}
+
+int
+set_hugetlb_mem_size (int count)
+{
+	int j, lcount;
+	struct page *page, *map;
+	extern long htlbzone_pages;
+	extern struct list_head htlbpage_freelist;
+
+	if (count < 0)
+		lcount = count;
+	else
+		lcount = count - htlbzone_pages;
+	if (lcount > 0) {	/*Increase the mem size. */
+		while (lcount--) {
+			page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER);
+			if (page == NULL)
+				break;
+			map = page;
+			for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) {
+				SetPageReserved(map);
+				map++;
+			}
+			spin_lock(&htlbpage_lock);
+			list_add(&page->list, &htlbpage_freelist);
+			htlbpagemem++;
+			htlbzone_pages++;
+			spin_unlock(&htlbpage_lock);
+		}
+		return (int) htlbzone_pages;
+	}
+	/*Shrink the memory size. */
+	while (lcount++) {
+		page = alloc_hugetlb_page();
+		if (page == NULL)
+			break;
+		spin_lock(&htlbpage_lock);
+		htlbzone_pages--;
+		spin_unlock(&htlbpage_lock);
+		map = page;
+		for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) {
+			map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced |
+					1 << PG_dirty | 1 << PG_active | 1 << PG_reserved |
+					1 << PG_private | 1<< PG_writeback);
+			map++;
+		}
+		set_page_count(page, 1);
+		__free_pages(page, HUGETLB_PAGE_ORDER);
+	}
+	return (int) htlbzone_pages;
+}
+
+static struct vm_operations_struct hugetlb_vm_ops = {
+	.close =	zap_hugetlb_resources
+};
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/mm/init.c	Sat Sep 21 21:25:45 2002
@@ -78,7 +78,7 @@
 		vma->vm_mm = current->mm;
 		vma->vm_start = IA64_RBS_BOT;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
-		vma->vm_page_prot = PAGE_COPY;
+		vma->vm_page_prot = protection_map[VM_READ | VM_WRITE];
 		vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
 		vma->vm_ops = NULL;
 		vma->vm_pgoff = 0;
@@ -339,6 +339,14 @@
 /*
  * Set up the page tables.
  */
+
+#ifdef CONFIG_HUGETLB_PAGE
+long htlbpagemem;
+int htlbpage_max;
+extern long htlbzone_pages;
+extern struct list_head htlbpage_freelist;
+#endif
+
 void
 paging_init (void)
 {
@@ -438,5 +446,30 @@
 
 #ifdef CONFIG_IA32_SUPPORT
 	ia32_gdt_init();
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	{
+		long i;
+		int j;
+		struct page *page, *map;
+
+		if ((htlbzone_pages << (HPAGE_SHIFT - PAGE_SHIFT)) >= max_low_pfn)
+			htlbzone_pages = (max_low_pfn >> ((HPAGE_SHIFT - PAGE_SHIFT) + 1));
+		INIT_LIST_HEAD(&htlbpage_freelist);
+		for (i = 0; i < htlbzone_pages; i++) {
+			page = alloc_pages(__GFP_HIGHMEM, HUGETLB_PAGE_ORDER);
+			if (!page)
+				break;
+			map = page;
+			for (j = 0; j < (HPAGE_SIZE/PAGE_SIZE); j++) {
+				SetPageReserved(map);
+				map++;
+			}
+			list_add(&page->list, &htlbpage_freelist);
+		}
+		printk("Total Huge_TLB_Page memory pages allocated %ld \n", i);
+		htlbzone_pages = htlbpagemem = i;
+		htlbpage_max = (int)i;
+	}
 #endif
 }
diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c	Sat Sep 21 21:25:46 2002
+++ b/arch/ia64/mm/tlb.c	Sat Sep 21 21:25:46 2002
@@ -63,7 +63,7 @@
 
 	read_lock(&tasklist_lock);
   repeat:
-	for_each_task(tsk) {
+	for_each_process(tsk) {
 		if (!tsk->mm)
 			continue;
 		tsk_context = tsk->mm->context;
diff -Nru a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/pci/Makefile	Sat Sep 21 21:25:48 2002
@@ -0,0 +1,3 @@
+obj-y		:= pci.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/pci/pci.c	Sat Sep 21 21:25:45 2002
@@ -0,0 +1,278 @@
+/*
+ * pci.c - Low-Level PCI Access in IA-64
+ *
+ * Derived from bios32.c of i386 tree.
+ *
+ * Copyright (C) 2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Note: Above list of copyright holders is incomplete...
+ */
+#include <linux/config.h>
+
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+
+#include <asm/machvec.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <asm/sal.h>
+
+
+#ifdef CONFIG_SMP
+# include <asm/smp.h>
+#endif
+#include <asm/irq.h>
+
+
+#undef DEBUG
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#ifdef CONFIG_IA64_MCA
+extern void ia64_mca_check_errors( void );
+#endif
+
+struct pci_fixup pcibios_fixups[1];
+
+/*
+ * Low-level SAL-based PCI configuration access functions. Note that SAL
+ * calls are already serialized (via sal_lock), so we don't need another
+ * synchronization mechanism here.  Not using segment number (yet).
+ */
+
+#define PCI_SAL_ADDRESS(bus, dev, fn, reg) \
+	((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))
+
+static int
+__pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
+{
+	int result = 0;
+	u64 data = 0;
+
+	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data);
+
+	*value = (u32) data;
+
+	return result;
+}
+
+static int
+__pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
+{
+	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
+		return -EINVAL;
+
+	return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value);
+}
+
+
+static int
+pci_sal_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	return __pci_sal_read(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
+			      where, size, value);
+}
+
+static int
+pci_sal_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+{
+	return __pci_sal_write(0, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
+			       where, size, value);
+}
+
+struct pci_ops pci_sal_ops = {
+	.read = 	pci_sal_read,
+	.write =	pci_sal_write
+};
+
+struct pci_ops *pci_root_ops = &pci_sal_ops;	/* default to SAL */
+
+static int __init
+pci_acpi_init (void)
+{
+	if (!acpi_pci_irq_init())
+		printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+	else
+		printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
+	return 0;
+}
+
+subsys_initcall(pci_acpi_init);
+
+/* Called by ACPI when it finds a new root bus.  */
+struct pci_bus *
+pcibios_scan_root (int bus)
+{
+	struct list_head *list;
+	struct pci_bus *pci_bus;
+
+	list_for_each(list, &pci_root_buses) {
+		pci_bus = pci_bus_b(list);
+		if (pci_bus->number == bus) {
+			/* Already scanned */
+			printk("PCI: Bus (%02x) already probed\n", bus);
+			return pci_bus;
+		}
+	}
+
+	printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
+	return pci_scan_bus(bus, pci_root_ops, NULL);
+}
+
+/*
+ *  Called after each bus is probed, but before its children are examined.
+ */
+void __init
+pcibios_fixup_bus (struct pci_bus *b)
+{
+	return;
+}
+
+void __init
+pcibios_update_resource (struct pci_dev *dev, struct resource *root,
+			 struct resource *res, int resource)
+{
+	unsigned long where, size;
+	u32 reg;
+
+	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	size = res->end - res->start;
+	pci_read_config_dword(dev, where, &reg);
+	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+	pci_write_config_dword(dev, where, reg);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+void __init
+pcibios_update_irq (struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+void __init
+pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+{
+}
+
+static inline int
+pcibios_enable_resources (struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	if (!dev)
+		return -EINVAL;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx=0; idx<6; idx++) {
+		/* Only set up the desired resources.  */
+		if (!(mask & (1 << idx)))
+			continue;
+
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR
+			       "PCI: Device %s not available because of resource collisions\n",
+			       dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+int
+pcibios_enable_device (struct pci_dev *dev, int mask)
+{
+	int ret;
+
+	ret = pcibios_enable_resources(dev, mask);
+	if (ret < 0)
+		return ret;
+
+	printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name);
+	return acpi_pci_irq_enable(dev);
+}
+
+void
+pcibios_align_resource (void *data, struct resource *res,
+		        unsigned long size, unsigned long align)
+{
+}
+
+/*
+ * PCI BIOS setup, always defaults to SAL interface
+ */
+char * __init
+pcibios_setup (char *str)
+{
+	return NULL;
+}
+
+int
+pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
+		     enum pci_mmap_state mmap_state, int write_combine)
+{
+	/*
+	 * I/O space cannot be accessed via normal processor loads and stores on this
+	 * platform.
+	 */
+	if (mmap_state == pci_mmap_io)
+		/*
+		 * XXX we could relax this for I/O spaces for which ACPI indicates that
+		 * the space is 1-to-1 mapped.  But at the moment, we don't support
+		 * multiple PCI address spaces and the legacy I/O space is not 1-to-1
+		 * mapped, so this is moot.
+		 */
+		return -EINVAL;
+
+	/*
+	 * Leave vm_pgoff as-is, the PCI space address is the physical address on this
+	 * platform.
+	 */
+	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
+
+	if (write_combine)
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
diff -Nru a/arch/ia64/tools/print_offsets.awk b/arch/ia64/tools/print_offsets.awk
--- a/arch/ia64/tools/print_offsets.awk	Sat Sep 21 21:25:45 2002
+++ b/arch/ia64/tools/print_offsets.awk	Sat Sep 21 21:25:45 2002
@@ -9,6 +9,7 @@
 	print " */"
 	print ""
 	print "#define CLONE_IDLETASK_BIT	12"
+	print "#define CLONE_SETTLS_BIT	19"
 }
 
 # look for .tab:
diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c
--- a/arch/ia64/tools/print_offsets.c	Sat Sep 21 21:25:48 2002
+++ b/arch/ia64/tools/print_offsets.c	Sat Sep 21 21:25:48 2002
@@ -202,6 +202,7 @@
     }
 
   printf ("\n#define CLONE_IDLETASK_BIT	%ld\n", ia64_fls (CLONE_IDLETASK));
+  printf ("\n#define CLONE_SETTLS_BIT	%ld\n", ia64_fls (CLONE_SETTLS));
 
   printf ("\n#endif /* _ASM_IA64_OFFSETS_H */\n");
   return 0;
diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
--- a/arch/m68k/atari/stram.c	Sat Sep 21 21:25:45 2002
+++ b/arch/m68k/atari/stram.c	Sat Sep 21 21:25:45 2002
@@ -974,8 +974,6 @@
 /*								ST-RAM device								*/
 /* ------------------------------------------------------------------------ */
 
-static int stram_sizes[14] = {
-	0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0 };
 static int refcnt = 0;
 
 static void do_stram_request(request_queue_t *q)
@@ -1048,28 +1046,33 @@
 	.release =	stram_release,
 };
 
+static struct gendisk stram_disk = {
+	.major = STRAM_MAJOR,
+	.first_minor = STRAM_MINOR,
+	.minor_shift = 0,
+	.fops = &stram_fops,
+	.major_name = "stram"
+};
+
 int __init stram_device_init(void)
 {
+	if (!MACH_IS_ATARI)
+		/* no point in initializing this, I hope */
+		return -ENXIO;
+
+	if (!max_swap_size)
+		/* swapping not enabled */
+		return -ENXIO;
+
+	if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
+		printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR);
+		return -ENXIO;
+	}
 
-    if (!MACH_IS_ATARI)
-    	/* no point in initializing this, I hope */
-	return( -ENXIO );
-
-    if (!max_swap_size)
-	/* swapping not enabled */
-	return( -ENXIO );
-	
-    if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
-	printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR );
-	return( -ENXIO );
-    }
-
-    blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request);
-	stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024;
-    blk_size[STRAM_MAJOR] = stram_sizes;
-	register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
-			(swap_end-swap_start)>>9);
-	return( 0 );
+	blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request);
+	set_capacity(&stram_disk, (swap_end - swap_start)/512);
+	add_disk(&stram_disk);
+	return 0;
 }
 
 
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acorn/block/fd1772.c	Sat Sep 21 21:25:45 2002
@@ -203,7 +203,8 @@
  */
 #define MAX_DISK_SIZE 720
 
-static int floppy_sizes[256];
+static struct gendisk disks[FD_MAX_UNIT];
+static char names[FD_MAX_UNIT][4];
 
 /* current info on each unit */
 static struct archy_floppy_struct {
@@ -962,16 +963,16 @@
 			if (unit[SelectedDrive].disktype > disk_type) {
 				/* try another disk type */
 				unit[SelectedDrive].disktype--;
-				floppy_sizes[SelectedDrive]
-				    = unit[SelectedDrive].disktype->blocks >> 1;
+				set_capacity(&disks[SelectedDrive],
+				    unit[SelectedDrive].disktype->blocks);
 			} else
 				Probing = 0;
 		} else {
 			/* record not found, but not probing. Maybe stretch wrong ? Restart probing */
 			if (unit[SelectedDrive].autoprobe) {
 				unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
-				floppy_sizes[SelectedDrive]
-				    = unit[SelectedDrive].disktype->blocks >> 1;
+				set_capacity(&disks[SelectedDrive],
+				    unit[SelectedDrive].disktype->blocks);
 				Probing = 1;
 			}
 		}
@@ -1243,7 +1244,7 @@
 		if (!floppy->disktype) {
 			Probing = 1;
 			floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
-			floppy_sizes[drive] = floppy->disktype->blocks >> 1;
+			set_capacity(&disks[drive], floppy->disktype->blocks);
 			floppy->autoprobe = 1;
 		}
 	} else {
@@ -1255,7 +1256,7 @@
 			goto repeat;
 		}
 		floppy->disktype = &disk_type[type];
-		floppy_sizes[drive] = disk_type[type].blocks >> 1;
+		set_capacity(&disks[drive], floppy->disktype->blocks);
 		floppy->autoprobe = 0;
 	}
 
@@ -1474,14 +1475,9 @@
 
 static int floppy_open(struct inode *inode, struct file *filp)
 {
-	int drive;
+	int drive = minor(inode->i_rdev) & 3;
 	int old_dev;
 
-	if (!filp) {
-		DPRINT(("Weird, open called with filp=0\n"));
-		return -EIO;
-	}
-	drive = minor(inode->i_rdev) & 3;
 	if ((minor(inode->i_rdev) >> 2) > NUM_DISK_TYPES)
 		return -ENXIO;
 
@@ -1543,6 +1539,13 @@
 	.revalidate		= floppy_revalidate,
 };
 
+static struct gendisk *floppy_find(int minor)
+{
+	int drive = minor & 3;
+	if ((minor>> 2) > NUM_DISK_TYPES || minor >= FD_MAX_UNITS)
+		return NULL;
+	return &disks[drive];
+}
 
 int fd1772_init(void)
 {
@@ -1580,19 +1583,20 @@
 	   out of some special memory... */
 	DMABuffer = (char *) kmalloc(2048);	/* Copes with pretty large sectors */
 #endif
-
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request);
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].track = -1;
+		disks[i].major = MAJOR_NR;
+		disks[i].first_minor = 0;
+		disks[i].fops = &floppy_fops;
+		sprintf(names[i], "fd%d", i);
+		disks[i].major_name = names[i];
+		set_capacity(&disks[i], MAX_DISK_SIZE * 2);
 	}
+	blk_set_probe(MAJOR_NR, floppy_find);
 
-	for (i = 0; i < 256; i++)
-		if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
-			floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
-		else
-			floppy_sizes[i] = MAX_DISK_SIZE;
-
-	blk_size[MAJOR_NR] = floppy_sizes;
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request);
+	for (i = 0; i < FD_MAX_UNITS; i++)
+		add_disk(disks + i);
 
 	config_types();
 
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acorn/block/mfmhd.c	Sat Sep 21 21:25:45 2002
@@ -1014,13 +1014,17 @@
 /*
  * Tell the user about the drive if we decided it exists.
  */
-static void mfm_geometry (int drive)
+static void mfm_geometry(int drive)
 {
-	if (mfm_info[drive].cylinders)
-		printk ("mfm%c: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", 'a' + drive,
-			mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096,
-			mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors,
-			mfm_info[drive].lowcurrent, mfm_info[drive].precomp);
+	struct mfm_info *p = mfm_info + drive;
+	struct gendisk *disk = mfm_gendisk + drive;
+	if (p->cylinders)
+		printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n",
+			disk->major_name,
+			p->cylinders * p->heads * p->sectors / 4096,
+			p->cylinders, p->heads, p->sectors,
+			p->lowcurrent, p->precomp);
+	set_capacity(disk, p->cylinders * p->heads * p->sectors / 2);
 }
 
 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
@@ -1241,7 +1245,6 @@
 		if (raw_cmd.dev == drive)
 			mfm_specify ();
 		mfm_geometry (drive);
-		set_capacity(&mfm_gendisk[drive], mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2);
 	}
 }
 
@@ -1267,12 +1270,8 @@
 		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
 
 	for (i = 0; i < mfm_drives; i++) {
-		add_gendisk(mfm_gendisk + i);
-		mfm_geometry (i);
-		register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
-				&mfm_fops,
-				mfm_info[i].cylinders * mfm_info[i].heads *
-				mfm_info[i].sectors / 2);
+		mfm_geometry(i);
+		add_disk(mfm_gendisk + i);
 	}
 }
 
diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c
--- a/drivers/acpi/ac.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/ac.c	Sat Sep 21 21:25:45 2002
@@ -33,13 +33,6 @@
 #include "acpi_drivers.h"
 
 
-#define _COMPONENT		ACPI_AC_COMPONENT
-ACPI_MODULE_NAME		("acpi_ac")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
 #define ACPI_AC_COMPONENT		0x00020000
 #define ACPI_AC_CLASS			"ac_adapter"
 #define ACPI_AC_HID 			"ACPI0003"
@@ -50,6 +43,13 @@
 #define ACPI_AC_STATUS_OFFLINE		0x00
 #define ACPI_AC_STATUS_ONLINE		0x01
 #define ACPI_AC_STATUS_UNKNOWN		0xFF
+
+#define _COMPONENT		ACPI_AC_COMPONENT
+ACPI_MODULE_NAME		("acpi_ac")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
+MODULE_LICENSE("GPL");
 
 int acpi_ac_add (struct acpi_device *device);
 int acpi_ac_remove (struct acpi_device *device, int type);
diff -Nru a/drivers/acpi/battery.c b/drivers/acpi/battery.c
--- a/drivers/acpi/battery.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/battery.c	Sat Sep 21 21:25:45 2002
@@ -33,14 +33,6 @@
 #include "acpi_drivers.h"
 
 
-#define _COMPONENT		ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME		("acpi_battery")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-
 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
 
 #define ACPI_BATTERY_FORMAT_BIF	"NNNNNNNNNSSSS"
@@ -58,6 +50,14 @@
 #define ACPI_BATTERY_NOTIFY_INFO	0x81
 #define ACPI_BATTERY_UNITS_WATTS	"mW"
 #define ACPI_BATTERY_UNITS_AMPS		"mA"
+
+
+#define _COMPONENT		ACPI_BATTERY_COMPONENT
+ACPI_MODULE_NAME		("acpi_battery")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
+MODULE_LICENSE("GPL");
 
 static int acpi_battery_add (struct acpi_device *device);
 static int acpi_battery_remove (struct acpi_device *device, int type);
diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c
--- a/drivers/acpi/button.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/button.c	Sat Sep 21 21:25:45 2002
@@ -33,13 +33,6 @@
 #include "acpi_drivers.h"
 
 
-#define _COMPONENT		ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME		("acpi_button")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
 #define ACPI_BUTTON_COMPONENT		0x00080000
 #define ACPI_BUTTON_DRIVER_NAME		"ACPI Button Driver"
 #define ACPI_BUTTON_CLASS		"button"
@@ -65,6 +58,13 @@
 #define ACPI_BUTTON_HID_LID		"PNP0C0D"
 #define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
 #define ACPI_BUTTON_TYPE_LID		0x05
+
+#define _COMPONENT		ACPI_BUTTON_COMPONENT
+ACPI_MODULE_NAME		("acpi_button")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
+MODULE_LICENSE("GPL");
 
 
 int acpi_button_add (struct acpi_device *device);
diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c
--- a/drivers/acpi/fan.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/fan.c	Sat Sep 21 21:25:45 2002
@@ -33,13 +33,6 @@
 #include "acpi_drivers.h"
 
 
-#define _COMPONENT		ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME		("acpi_fan")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
 #define ACPI_FAN_COMPONENT		0x00200000
 #define ACPI_FAN_CLASS			"fan"
 #define ACPI_FAN_HID			"PNP0C0B"
@@ -47,6 +40,13 @@
 #define ACPI_FAN_DEVICE_NAME		"Fan"
 #define ACPI_FAN_FILE_STATE		"state"
 #define ACPI_FAN_NOTIFY_STATUS		0x80
+
+#define _COMPONENT		ACPI_FAN_COMPONENT
+ACPI_MODULE_NAME		("acpi_fan")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
+MODULE_LICENSE("GPL");
 
 int acpi_fan_add (struct acpi_device *device);
 int acpi_fan_remove (struct acpi_device *device, int type);
diff -Nru a/drivers/acpi/numa.c b/drivers/acpi/numa.c
--- a/drivers/acpi/numa.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/acpi/numa.c	Sat Sep 21 21:25:48 2002
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/acpi.h>
+#include "acpi_bus.h"
 
 extern int __init acpi_table_parse_madt_family (enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler);
 
diff -Nru a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
--- a/drivers/acpi/pci_bind.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/pci_bind.c	Sat Sep 21 21:25:45 2002
@@ -185,7 +185,7 @@
 	 */
 	data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
 	if (!data->dev) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
 			"Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
 			data->id.segment, data->id.bus, 
 			data->id.device, data->id.function));
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/acpi/processor.c	Sat Sep 21 21:25:46 2002
@@ -43,14 +43,6 @@
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
-
-#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME		("acpi_processor")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
 #define ACPI_PROCESSOR_COMPONENT	0x01000000
 #define ACPI_PROCESSOR_CLASS		"processor"
 #define ACPI_PROCESSOR_DRIVER_NAME	"ACPI Processor Driver"
@@ -83,6 +75,14 @@
 
 #define ACPI_PROCESSOR_LIMIT_USER	0
 #define ACPI_PROCESSOR_LIMIT_THERMAL	1
+
+#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME		("acpi_processor")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
 
 static int acpi_processor_add (struct acpi_device *device);
 static int acpi_processor_remove (struct acpi_device *device, int type);
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/acpi/thermal.c	Sat Sep 21 21:25:45 2002
@@ -42,18 +42,6 @@
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
-
-#define _COMPONENT		ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME		("acpi_thermal")
-
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-static int tzp = 0;
-MODULE_PARM(tzp, "i");
-MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
-
 #define ACPI_THERMAL_COMPONENT		0x04000000
 #define ACPI_THERMAL_CLASS		"thermal_zone"
 #define ACPI_THERMAL_DRIVER_NAME	"ACPI Thermal Zone Driver"
@@ -75,6 +63,18 @@
 #define ACPI_THERMAL_MAX_ACTIVE	10
 
 #define KELVIN_TO_CELSIUS(t)	((t-2732+5)/10)
+
+#define _COMPONENT		ACPI_THERMAL_COMPONENT
+ACPI_MODULE_NAME		("acpi_thermal")
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+static int tzp = 0;
+MODULE_PARM(tzp, "i");
+MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
+
 
 static int acpi_thermal_add (struct acpi_device *device);
 static int acpi_thermal_remove (struct acpi_device *device, int type);
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/block/DAC960.c	Sat Sep 21 21:25:48 2002
@@ -1973,7 +1973,6 @@
 	disk->major_name = names + 9 * n;
 	disk->minor_shift = DAC960_MaxPartitionsBits;
 	disk->fops = &DAC960_BlockDeviceOperations;
-	add_gendisk(disk);
    }
   /*
     Indicate the Block Device Registration completed successfully,
@@ -2622,10 +2621,8 @@
       if (Controller == NULL) continue;
       DAC960_InitializeController(Controller);
       for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
-	long size = disk_size(Controller, disk);
-	register_disk(&Controller->disks[disk],
-	    DAC960_KernelDevice(Controller->ControllerNumber, disk, 0),
-	    DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size);
+	set_capacity(&Controller->disks[disk], disk_size(Controller, disk));
+	add_disk(&Controller->disks[disk]);
       }
     }
   DAC960_CreateProcEntries();
@@ -5268,9 +5265,8 @@
       Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
       size = disk_size(Controller, LogicalDriveNumber);
       /* BROKEN, same as modular ide-floppy/ide-disk; same fix - ->probe() */
-      register_disk(&Controller->disks[LogicalDriveNumber],
-	    DAC960_KernelDevice(Controller->ControllerNumber, LogicalDriveNumber, 0),
-	    DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size);
+      set_capacity(&Controller->disks[LogicalDriveNumber], size);
+      add_disk(&Controller->disks[LogicalDriveNumber]);
     }
   if (!get_capacity(&Controller->disks[LogicalDriveNumber]))
     return -ENXIO;
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/acsi.c	Sat Sep 21 21:25:45 2002
@@ -1698,11 +1698,8 @@
 		disk->major_name = acsi_names + 4*i;
 		disk->minor_shift = (acsi_info[i].type==HARDDISK)?4:0;
 		disk->fops = &acsi_fops;
-		add_gendisk(disk);
-		register_disk(disk, mk_kdev(disk->major, disk->first_minor),
-				1<<disk->minor_shift,
-				disk->fops,
-				acsi_info[i].size);
+		set_capacity(disk, acsi_info[i].size);
+		add_disk(disk);
 	}
 }
 
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/block/cciss.c	Sat Sep 21 21:25:48 2002
@@ -769,11 +769,8 @@
 			continue;
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size;
 		disk->major_name = hba[ctlr]->names + 12 * i;
-		add_gendisk(disk);
-		register_disk(disk,
-			      mk_kdev(disk->major, disk->first_minor),
-			      1<<disk->minor_shift, disk->fops,
-			      drv->nr_blocks);
+		set_capacity(disk, drv->nr_blocks);
+		add_disk(disk);
 	}
         hba[ctlr]->usage_count--;
         return 0;
@@ -1241,12 +1238,8 @@
 	/* setup partitions per disk */
         disk = &hba[ctlr]->gendisk[logvol];
 	disk->major_name = hba[ctlr]->names + 12 * logvol;
-	add_gendisk(disk);
-	register_disk(disk,
-		      mk_kdev(disk->major, disk->first_minor),
-		      1<<disk->minor_shift,
-		      disk->fops,
-		      hba[ctlr]->drv[logvol].nr_blocks);
+	set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks);
+	add_disk(disk);
 	
 	kfree(ld_buff);
 	kfree(size_buff);
@@ -2449,11 +2442,8 @@
 			continue;
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size;
 		disk->major_name = hba[i]->names + 12 * j;
-		add_gendisk(disk);
-		register_disk(disk,
-			      mk_kdev(disk->major, disk->first_minor),
-			      1<<disk->minor_shift, disk->fops,
-			      drv->nr_blocks);
+		set_capacity(disk, drv->nr_blocks);
+		add_disk(disk);
 	}
 
 	cciss_register_scsi(i, 1);  /* hook ourself into SCSI subsystem */
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/cpqarray.c	Sat Sep 21 21:25:45 2002
@@ -449,11 +449,8 @@
 				continue;
 			disk->major_name = ida_names + (i*NWD+j)*10;
 			(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->blk_size;
-			add_gendisk(disk);
-			register_disk(disk,
-				      mk_kdev(disk->major,disk->first_minor),
-				      1<<disk->minor_shift, disk->fops,
-				      drv->nr_blks);
+			set_capacity(disk, drv->nr_blks);
+			add_disk(disk);
 		}
 	}
 	/* done ! */
@@ -1475,11 +1472,8 @@
 			continue;
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
 		disk->major_name = ida_names + (ctlr*NWD+i)*10;
-		add_gendisk(disk);
-		register_disk(disk,
-			      mk_kdev(disk->major,disk->first_minor),
-			      1<<disk->minor_shift, disk->fops,
-			      drv->nr_blks);
+		set_capacity(disk, drv->nr_blks);
+		add_disk(disk);
 	}
 
 	hba[ctlr]->usage_count--;
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/floppy.c	Sat Sep 21 21:25:45 2002
@@ -416,6 +416,8 @@
 static struct floppy_drive_struct drive_state[N_DRIVE];
 static struct floppy_write_errors write_errors[N_DRIVE];
 static struct timer_list motor_off_timer[N_DRIVE];
+static struct gendisk disks[N_DRIVE];
+static char names[N_DRIVE][4];
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
 
 /*
@@ -3775,6 +3777,7 @@
 	}
 
 	UDRS->fd_device = minor(inode->i_rdev);
+	set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]);
 	if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
 		if (buffer_drive == drive)
 			buffer_track = -1;
@@ -3952,6 +3955,7 @@
 			poll_drive(0, FD_RAW_NEED_DISK);
 		process_fd_request();
 	}
+	set_capacity(&disks[drive], floppy_sizes[minor(dev)]);
 	return 0;
 }
 
@@ -4219,6 +4223,16 @@
 	bus_id:		"03?0",
 };
 
+static struct gendisk *floppy_find(int minor)
+{
+	int drive = (minor&3) | ((minor&0x80) >> 5);
+	if (drive >= N_DRIVE ||
+	    !(allowed_drive_mask & (1 << drive)) ||
+	    fdc_state[FDC(drive)].version == FDC_NONE)
+		return NULL;
+	return &disks[drive];
+}
+
 int __init floppy_init(void)
 {
 	int i,unit,drive;
@@ -4231,13 +4245,22 @@
 		return -EBUSY;
 	}
 
+	for (i=0; i<N_DRIVE; i++) {
+		disks[i].major = MAJOR_NR;
+		disks[i].first_minor = TOMINOR(i);
+		disks[i].fops = &floppy_fops;
+		sprintf(names[i], "fd%d", i);
+		disks[i].major_name = names[i];
+	}
+
+	blk_set_probe(MAJOR_NR, floppy_find);
+
 	for (i=0; i<256; i++)
 		if (ITYPE(i))
 			floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1;
 		else
 			floppy_sizes[i] = MAX_DISK_SIZE;
 
-	blk_size[MAJOR_NR] = floppy_sizes;
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock);
 	reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
 	config_types();
@@ -4262,6 +4285,7 @@
 		unregister_blkdev(MAJOR_NR,"fd");
 		del_timer(&fd_timeout);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+		blk_set_probe(MAJOR_NR, NULL);
 		return -ENODEV;
 	}
 #if N_FDC > 1
@@ -4273,6 +4297,7 @@
 		del_timer(&fd_timeout);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		unregister_blkdev(MAJOR_NR,"fd");
+		blk_set_probe(MAJOR_NR, NULL);
 		return -EBUSY;
 	}
 
@@ -4336,6 +4361,7 @@
 			floppy_release_irq_and_dma();
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		unregister_blkdev(MAJOR_NR,"fd");
+		blk_set_probe(MAJOR_NR, NULL);
 	}
 	
 	for (drive = 0; drive < N_DRIVE; drive++) {
@@ -4345,9 +4371,7 @@
 			continue;
 		if (fdc_state[FDC(drive)].version == FDC_NONE)
 			continue;
-		for (i = 0; i<NUMBER(floppy_type); i++)
-			register_disk(NULL, mk_kdev(MAJOR_NR,TOMINOR(drive)+i*4),
-					1, &floppy_fops, 0);
+		add_disk(disks + drive);
 	}
 
 	register_sys_device(&device_floppy);
@@ -4532,15 +4556,21 @@
 
 void cleanup_module(void)
 {
-	int dummy;
+	int i;
 		
 	unregister_sys_device(&device_floppy);
 	devfs_unregister (devfs_handle);
 	unregister_blkdev(MAJOR_NR, "fd");
+	blk_set_probe(MAJOR_NR, NULL);
+	for (drive = 0; drive < N_DRIVE; drive++) {
+		if ((allowed_drive_mask & (1 << drive)) &&
+		    fdc_state[FDC(drive)].version != FDC_NONE)
+			del_gendisk(disks + drive);
+	}
 
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	/* eject disk, if any */
-	dummy = fd_eject(0);
+	fd_eject(0);
 }
 
 MODULE_PARM(floppy,"s");
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/genhd.c	Sat Sep 21 21:25:45 2002
@@ -33,6 +33,23 @@
  */
 static struct gendisk *gendisk_head;
 
+/*
+ *  TEMPORARY KLUDGE.
+ */
+static struct {
+	struct list_head list;
+	struct gendisk *(*get)(int minor);
+} gendisks[MAX_BLKDEV];
+
+void blk_set_probe(int major, struct gendisk *(p)(int))
+{
+	write_lock(&gendisk_lock);
+	gendisks[major].get = p;
+	write_unlock(&gendisk_lock);
+}
+EXPORT_SYMBOL(blk_set_probe);	/* Will go away */
+	
+
 /**
  * add_gendisk - add partitioning information to kernel list
  * @gp: per-device partitioning information
@@ -40,10 +57,8 @@
  * This function registers the partitioning information in @gp
  * with the kernel.
  */
-void
-add_gendisk(struct gendisk *gp)
+static void add_gendisk(struct gendisk *gp)
 {
-	struct gendisk *sgp;
 	struct hd_struct *p = NULL;
 
 	if (gp->minor_shift) {
@@ -59,28 +74,20 @@
 	gp->part = p;
 
 	write_lock(&gendisk_lock);
-
-	/*
- 	 *	In 2.5 this will go away. Fix the drivers who rely on
- 	 *	old behaviour.
- 	 */
-
-	for (sgp = gendisk_head; sgp; sgp = sgp->next)
-	{
-		if (sgp == gp)
-		{
-			printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
-				sgp->major);
-			goto out;
-		}
-	}
+	list_add(&gp->list, &gendisks[gp->major].list);
 	gp->next = gendisk_head;
 	gendisk_head = gp;
-out:
 	write_unlock(&gendisk_lock);
 }
 
-EXPORT_SYMBOL(add_gendisk);
+void add_disk(struct gendisk *disk)
+{
+	add_gendisk(disk);
+	register_disk(disk, mk_kdev(disk->major, disk->first_minor),
+			1<<disk->minor_shift, disk->fops, get_capacity(disk));
+}
+
+EXPORT_SYMBOL(add_disk);
 EXPORT_SYMBOL(del_gendisk);
 
 void unlink_gendisk(struct gendisk *disk)
@@ -92,6 +99,7 @@
 			break;
 	if (*p)
 		*p = (*p)->next;
+	list_del_init(&disk->list);
 	write_unlock(&gendisk_lock);
 }
 
@@ -105,20 +113,25 @@
 struct gendisk *
 get_gendisk(kdev_t dev)
 {
-	struct gendisk *gp = NULL;
+	struct gendisk *disk;
+	struct list_head *p;
 	int major = major(dev);
 	int minor = minor(dev);
 
 	read_lock(&gendisk_lock);
-	for (gp = gendisk_head; gp; gp = gp->next) {
-		if (gp->major != major)
-			continue;
-		if (gp->first_minor > minor)
+	if (gendisks[major].get) {
+		disk = gendisks[major].get(minor);
+		read_unlock(&gendisk_lock);
+		return disk;
+	}
+	list_for_each(p, &gendisks[major].list) {
+		disk = list_entry(p, struct gendisk, list);
+		if (disk->first_minor > minor)
 			continue;
-		if (gp->first_minor + (1<<gp->minor_shift) <= minor)
+		if (disk->first_minor + (1<<disk->minor_shift) <= minor)
 			continue;
 		read_unlock(&gendisk_lock);
-		return gp;
+		return disk;
 	}
 	read_unlock(&gendisk_lock);
 	return NULL;
@@ -161,6 +174,10 @@
 	if (sgp == gendisk_head)
 		seq_puts(part, "major minor  #blocks  name\n\n");
 
+	/* Don't show non-partitionable devices or empty devices */
+	if (!sgp->minor_shift || !get_capacity(sgp))
+		return 0;
+
 	/* show the full disk and all non-0 size partitions of it */
 	seq_printf(part, "%4d  %4d %10ld %s\n",
 		sgp->major, sgp->first_minor,
@@ -194,7 +211,10 @@
 
 int __init device_init(void)
 {
+	int i;
 	rwlock_init(&gendisk_lock);
+	for (i = 0; i < MAX_BLKDEV; i++)
+		INIT_LIST_HEAD(&gendisks[i].list);
 	blk_dev_init();
 #ifdef CONFIG_FC4_SOC
 	/* This has to be done before scsi_dev_init */
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/loop.c	Sat Sep 21 21:25:45 2002
@@ -83,7 +83,8 @@
 
 static int max_loop = 8;
 static struct loop_device *loop_dev;
-static int *loop_sizes;
+static struct gendisk *disks;
+static char *names;
 static devfs_handle_t devfs_handle;      /*  For the directory */
 
 /*
@@ -165,8 +166,8 @@
 
 static void figure_loop_size(struct loop_device *lo)
 {
-	loop_sizes[lo->lo_number] = compute_loop_size(lo,
-					lo->lo_backing_file->f_dentry);
+	set_capacity(disks + lo->lo_number, compute_loop_size(lo,
+					lo->lo_backing_file->f_dentry));
 					
 }
 
@@ -792,8 +793,8 @@
 	lo->lo_flags = 0;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_name, 0, LO_NAME_SIZE);
-	loop_sizes[lo->lo_number] = 0;
 	invalidate_bdev(bdev, 0);
+	set_capacity(disks + lo->lo_number, 0);
 	filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp;
 	lo->lo_state = Lo_unbound;
 	fput(filp);
@@ -906,20 +907,6 @@
 	case LOOP_GET_STATUS:
 		err = loop_get_status(lo, (struct loop_info *) arg);
 		break;
-	case BLKGETSIZE:
-		if (lo->lo_state != Lo_bound) {
-			err = -ENXIO;
-			break;
-		}
-		err = put_user((unsigned long) loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
-		break;
-	case BLKGETSIZE64:
-		if (lo->lo_state != Lo_bound) {
-			err = -ENXIO;
-			break;
-		}
-		err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)arg);
-		break;
 	default:
 		err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
 	}
@@ -932,18 +919,11 @@
 	struct loop_device *lo;
 	int	dev, type;
 
-	if (!inode)
-		return -EINVAL;
-	if (major(inode->i_rdev) != MAJOR_NR) {
-		printk(KERN_WARNING "lo_open: pseudo-major != %d\n", MAJOR_NR);
-		return -ENODEV;
-	}
 	dev = minor(inode->i_rdev);
 	if (dev >= max_loop)
 		return -ENODEV;
 
 	lo = &loop_dev[dev];
-	MOD_INC_USE_COUNT;
 	down(&lo->lo_ctl_mutex);
 
 	type = lo->lo_encrypt_type; 
@@ -959,13 +939,6 @@
 	struct loop_device *lo;
 	int	dev, type;
 
-	if (!inode)
-		return 0;
-	if (major(inode->i_rdev) != MAJOR_NR) {
-		printk(KERN_WARNING "lo_release: pseudo-major != %d\n",
-		       MAJOR_NR);
-		return 0;
-	}
 	dev = minor(inode->i_rdev);
 	if (dev >= max_loop)
 		return 0;
@@ -978,7 +951,6 @@
 		xfer_funcs[type]->unlock(lo);
 
 	up(&lo->lo_ctl_mutex);
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -1051,46 +1023,56 @@
 	if (!loop_dev)
 		return -ENOMEM;
 
-	loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
-	if (!loop_sizes)
+	disks = kmalloc(max_loop * sizeof(struct gendisk), GFP_KERNEL);
+	if (!disks)
 		goto out_mem;
 
+	names = kmalloc(max_loop * 8, GFP_KERNEL);
+
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), loop_make_request);
 	blk_queue_bounce_limit(BLK_DEFAULT_QUEUE(MAJOR_NR), BLK_BOUNCE_HIGH);
 
 	for (i = 0; i < max_loop; i++) {
 		struct loop_device *lo = &loop_dev[i];
+		struct gendisk *disk = disks + i;
 		memset(lo, 0, sizeof(struct loop_device));
 		init_MUTEX(&lo->lo_ctl_mutex);
 		init_MUTEX_LOCKED(&lo->lo_sem);
 		init_MUTEX_LOCKED(&lo->lo_bh_mutex);
 		lo->lo_number = i;
 		spin_lock_init(&lo->lo_lock);
+		memset(disk, 0, sizeof(struct gendisk));
+		disk->major = LOOP_MAJOR;
+		disk->first_minor = i;
+		disk->fops = &lo_fops;
+		sprintf(names + 8*i, "loop%d", i);
+		disk->major_name = names + 8 * i;
+		add_disk(disk);
 	}
 
-	memset(loop_sizes, 0, max_loop * sizeof(int));
-	blk_size[MAJOR_NR] = loop_sizes;
-	for (i = 0; i < max_loop; i++)
-		register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &lo_fops, 0);
-
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
 
 out_mem:
+	kfree(names);
+	kfree(disks);
 	kfree(loop_dev);
-	kfree(loop_sizes);
 	printk(KERN_ERR "loop: ran out of memory\n");
 	return -ENOMEM;
 }
 
 void loop_exit(void) 
 {
+	int i;
+	for (i = 0; i < max_loop; i++)
+		del_gendisk(disks + i);
 	devfs_unregister(devfs_handle);
 	if (unregister_blkdev(MAJOR_NR, "loop"))
 		printk(KERN_WARNING "loop: cannot unregister blkdev\n");
 
+	kfree(names);
+	kfree(disks);
 	kfree(loop_dev);
-	kfree(loop_sizes);
 }
 
 module_init(loop_init);
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/nbd.c	Sat Sep 21 21:25:45 2002
@@ -59,8 +59,8 @@
 
 static int nbd_blksizes[MAX_NBD];
 static int nbd_blksize_bits[MAX_NBD];
-static int nbd_sizes[MAX_NBD];
 static u64 nbd_bytesizes[MAX_NBD];
+static char nbd_names[MAX_NBD][7];
 
 static struct nbd_device nbd_dev[MAX_NBD];
 static devfs_handle_t devfs_handle;
@@ -78,11 +78,7 @@
 
 static int nbd_open(struct inode *inode, struct file *file)
 {
-	int dev;
-
-	if (!inode)
-		return -EINVAL;
-	dev = minor(inode->i_rdev);
+	int dev = minor(inode->i_rdev);
 	if (dev >= MAX_NBD)
 		return -ENODEV;
 
@@ -387,21 +383,15 @@
 static int nbd_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	struct nbd_device *lo;
-	int dev, error, temp;
+	int dev = minor(inode->i_rdev);
+	struct nbd_device *lo = &nbd_dev[dev];
+	int error, temp;
 	struct request sreq ;
 
 	/* Anyone capable of this syscall can do *real bad* things */
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (!inode)
-		return -EINVAL;
-	dev = minor(inode->i_rdev);
-	if (dev >= MAX_NBD)
-		return -ENODEV;
-
-	lo = &nbd_dev[dev];
 	switch (cmd) {
 	case NBD_DISCONNECT:
 	        printk(KERN_INFO "NBD_DISCONNECT\n");
@@ -455,15 +445,15 @@
 			temp >>= 1;
 		}
 		nbd_bytesizes[dev] &= ~(nbd_blksizes[dev]-1); 
-		nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
+		set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9);
 		return 0;
 	case NBD_SET_SIZE:
 		nbd_bytesizes[dev] = arg & ~(nbd_blksizes[dev]-1); 
-		nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
+		set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9);
 		return 0;
 	case NBD_SET_SIZE_BLOCKS:
 		nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev]; 
-		nbd_sizes[dev] = nbd_bytesizes[dev] >> BLOCK_SIZE_BITS;
+		set_capacity(&lo->disk, nbd_bytesizes[dev] >> 9);
 		return 0;
 	case NBD_DO_IT:
 		if (!lo->file)
@@ -479,25 +469,14 @@
 		       dev, lo->queue_head.next, lo->queue_head.prev, requests_in, requests_out);
 		return 0;
 #endif
-	case BLKGETSIZE:
-		return put_user(nbd_bytesizes[dev] >> 9, (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user((u64)nbd_bytesizes[dev], (u64 *) arg);
 	}
 	return -EINVAL;
 }
 
 static int nbd_release(struct inode *inode, struct file *file)
 {
-	struct nbd_device *lo;
-	int dev;
-
-	if (!inode)
-		return -ENODEV;
-	dev = minor(inode->i_rdev);
-	if (dev >= MAX_NBD)
-		return -ENODEV;
-	lo = &nbd_dev[dev];
+	int dev = minor(inode->i_rdev);
+	struct nbd_device *lo = &nbd_dev[dev];
 	if (lo->refcnt <= 0)
 		printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
 	lo->refcnt--;
@@ -535,9 +514,9 @@
 #ifdef MODULE
 	printk("nbd: registered device at major %d\n", MAJOR_NR);
 #endif
-	blk_size[MAJOR_NR] = nbd_sizes;
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request, &nbd_lock);
 	for (i = 0; i < MAX_NBD; i++) {
+		struct gendisk *disk = &nbd_dev[i].disk;
 		nbd_dev[i].refcnt = 0;
 		nbd_dev[i].file = NULL;
 		nbd_dev[i].magic = LO_MAGIC;
@@ -548,9 +527,14 @@
 		nbd_blksizes[i] = 1024;
 		nbd_blksize_bits[i] = 10;
 		nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
-		nbd_sizes[i] = nbd_bytesizes[i] >> BLOCK_SIZE_BITS;
-		register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &nbd_fops,
-				nbd_bytesizes[i]>>9);
+		disk->major = MAJOR_NR;
+		disk->first_minor = i;
+		disk->minor_shift = 0;
+		disk->fops = &nbd_fops;
+		sprintf(nbd_names[i], "nbd%d", i);
+		disk->major_name = nbd_names[i];
+		set_capacity(disk, 0x3ffffe);
+		add_disk(disk);
 	}
 	devfs_handle = devfs_mk_dir (NULL, "nbd", NULL);
 	devfs_register_series (devfs_handle, "%u", MAX_NBD,
@@ -563,6 +547,9 @@
 
 static void __exit nbd_cleanup(void)
 {
+	int i;
+	for (i = 0; i < MAX_NBD; i++)
+		del_gendisk(&nbd_dev[i].disk);
 	devfs_unregister (devfs_handle);
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/paride/pcd.c	Sat Sep 21 21:25:45 2002
@@ -176,8 +176,6 @@
 /* set up defines for blk.h,  why don't all drivers do it this way ? */
 
 #define MAJOR_NR	major
-#define DEVICE_NR(device) (minor(device))
-#define DEVICE_OFF(device)
 
 #include <linux/blk.h>
 
@@ -224,6 +222,7 @@
 	int present;		/* does this unit exist ? */
 	char *name;		/* pcd0, pcd1, etc */
 	struct cdrom_device_info info;	/* uniform cdrom interface */
+	struct gendisk disk;
 };
 
 struct pcd_unit pcd[PCD_UNITS];
@@ -282,6 +281,7 @@
 
 	pcd_drive_count = 0;
 	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+		struct gendisk *disk = &cd->disk;
 		cd->pi = &cd->pia;
 		cd->present = 0;
 		cd->last_sense = 0;
@@ -298,6 +298,11 @@
 		cd->info.speed = 0;
 		cd->info.capacity = 1;
 		cd->info.mask = 0;
+		disk->major = major;
+		disk->first_minor = unit;
+		disk->minor_shift = 0;
+		disk->major_name = cd->name;
+		disk->fops = &pcd_bdops;
 	}
 }
 
@@ -925,8 +930,9 @@
 
 	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 		if (cd->present) {
+			struct gendisk *disk = &cd->disk;
 			register_cdrom(&cd->info);
-			devfs_plain_cdrom(&cd->info, &pcd_bdops);
+			add_disk(disk);
 		}
 	}
 
@@ -942,6 +948,7 @@
 
 	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
 		if (cd->present) {
+			del_gendisk(&cd->disk);
 			pi_release(cd->pi);
 			unregister_cdrom(&cd->info);
 		}
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/block/paride/pd.c	Sat Sep 21 21:25:48 2002
@@ -687,10 +687,8 @@
 			PD.gd.fops = &pd_fops;
 			PD.gd.major = major;
 			PD.gd.first_minor = unit << PD_BITS;
-			add_gendisk(&PD.gd);
-			register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
-					PD_PARTNS,&pd_fops,
-					PD.capacity);
+			set_capacity(&PD.gd, PD.capacity);
+			add_disk(&PD.gd);
 		}
 	}
 	if (k)
diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
--- a/drivers/block/paride/pf.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/block/paride/pf.c	Sat Sep 21 21:25:46 2002
@@ -124,34 +124,25 @@
 
 */
 
-static int	verbose = 0;
-static int	major = PF_MAJOR;
-static char	*name = PF_NAME;
-static int      cluster = 64;
-static int      nice = 0;
-static int      disable = 0;
-
-static int drive0[7] = {0,0,0,-1,-1,-1,-1};
-static int drive1[7] = {0,0,0,-1,-1,-1,-1};
-static int drive2[7] = {0,0,0,-1,-1,-1,-1};
-static int drive3[7] = {0,0,0,-1,-1,-1,-1};
+static int verbose = 0;
+static int major = PF_MAJOR;
+static char *name = PF_NAME;
+static int cluster = 64;
+static int nice = 0;
+static int disable = 0;
+
+static int drive0[7] = { 0, 0, 0, -1, -1, -1, -1 };
+static int drive1[7] = { 0, 0, 0, -1, -1, -1, -1 };
+static int drive2[7] = { 0, 0, 0, -1, -1, -1, -1 };
+static int drive3[7] = { 0, 0, 0, -1, -1, -1, -1 };
 
-static int (*drives[4])[7] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[7] = {&drive0, &drive1, &drive2, &drive3};
 static int pf_drive_count;
 
-#define D_PRT   0
-#define D_PRO   1
-#define D_UNI   2
-#define D_MOD   3
-#define D_SLV   4
-#define D_LUN   5
-#define D_DLY   6
-
-#define DU              (*drives[unit])
+enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
 
 /* end of parameters */
 
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
@@ -168,30 +159,32 @@
 
 #include "setup.h"
 
-static STT pf_stt[7] = {{"drive0",7,drive0},
-                        {"drive1",7,drive1},
-                        {"drive2",7,drive2},
-                        {"drive3",7,drive3},
-			{"disable",1,&disable},
-                        {"cluster",1,&cluster},
-                        {"nice",1,&nice}};
-
-void pf_setup( char *str, int *ints)
+static STT pf_stt[7] = {
+	{"drive0", 7, drive0},
+	{"drive1", 7, drive1},
+	{"drive2", 7, drive2},
+	{"drive3", 7, drive3},
+	{"disable", 1, &disable},
+	{"cluster", 1, &cluster},
+	{"nice", 1, &nice}
+};
 
-{       generic_setup(pf_stt,7,str);
+void pf_setup(char *str, int *ints)
+{
+	generic_setup(pf_stt, 7, str);
 }
 
 #endif
 
-MODULE_PARM(verbose,"i");
-MODULE_PARM(major,"i");
-MODULE_PARM(name,"s");
-MODULE_PARM(cluster,"i");
-MODULE_PARM(nice,"i");
-MODULE_PARM(drive0,"1-7i");
-MODULE_PARM(drive1,"1-7i");
-MODULE_PARM(drive2,"1-7i");
-MODULE_PARM(drive3,"1-7i");
+MODULE_PARM(verbose, "i");
+MODULE_PARM(major, "i");
+MODULE_PARM(name, "s");
+MODULE_PARM(cluster, "i");
+MODULE_PARM(nice, "i");
+MODULE_PARM(drive0, "1-7i");
+MODULE_PARM(drive1, "1-7i");
+MODULE_PARM(drive2, "1-7i");
+MODULE_PARM(drive3, "1-7i");
 
 #include "paride.h"
 
@@ -199,7 +192,6 @@
 
 #define MAJOR_NR   major
 #define DEVICE_NR(device) minor(device)
-#define DEVICE_OFF(device)
 
 #include <linux/blk.h>
 #include <linux/blkpg.h>
@@ -208,15 +200,15 @@
 
 /* constants for faking geometry numbers */
 
-#define PF_FD_MAX	8192		/* use FD geometry under this size */
+#define PF_FD_MAX	8192	/* use FD geometry under this size */
 #define PF_FD_HDS	2
 #define PF_FD_SPT	18
 #define PF_HD_HDS	64
 #define PF_HD_SPT	32
 
 #define PF_MAX_RETRIES  5
-#define PF_TMO          800             /* interrupt timeout in jiffies */
-#define PF_SPIN_DEL     50              /* spin delay in micro-seconds  */
+#define PF_TMO          800	/* interrupt timeout in jiffies */
+#define PF_SPIN_DEL     50	/* spin delay in micro-seconds  */
 
 #define PF_SPIN         (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)
 
@@ -239,27 +231,22 @@
 #define ATAPI_WRITE_10		0x2a
 
 #ifdef MODULE
-void cleanup_module( void );
+void cleanup_module(void);
 #endif
 static int pf_open(struct inode *inode, struct file *file);
 static void do_pf_request(request_queue_t * q);
-static int pf_ioctl(struct inode *inode,struct file *file,
-                    unsigned int cmd, unsigned long arg);
+static int pf_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg);
 
-static int pf_release (struct inode *inode, struct file *file);
+static int pf_release(struct inode *inode, struct file *file);
 
 static int pf_detect(void);
 static void do_pf_read(void);
 static void do_pf_read_start(void);
 static void do_pf_write(void);
 static void do_pf_write_start(void);
-static void do_pf_read_drq( void );
-static void do_pf_write_done( void );
-
-static int pf_identify (int unit);
-static void pf_lock(int unit, int func);
-static void pf_eject(int unit);
-static int pf_check_media(kdev_t dev);
+static void do_pf_read_drq(void);
+static void do_pf_write_done(void);
 
 #define PF_NM           0
 #define PF_RO           1
@@ -268,714 +255,715 @@
 #define PF_NAMELEN      8
 
 struct pf_unit {
-	struct pi_adapter pia;    /* interface to paride layer */
+	struct pi_adapter pia;	/* interface to paride layer */
 	struct pi_adapter *pi;
-	int removable;		  /* removable media device  ?  */
-	int media_status;	  /* media present ?  WP ? */
-	int drive;		  /* drive */
+	int removable;		/* removable media device  ?  */
+	int media_status;	/* media present ?  WP ? */
+	int drive;		/* drive */
 	int lun;
-	int access;               /* count of active opens ... */
-	int capacity;             /* Size of this volume in sectors */
-	int present;		  /* device present ? */
-	char name[PF_NAMELEN];	  /* pf0, pf1, ... */
-	};
-
-struct pf_unit pf[PF_UNITS];
+	int access;		/* count of active opens ... */
+	int present;		/* device present ? */
+	char name[PF_NAMELEN];	/* pf0, pf1, ... */
+	struct gendisk disk;
+};
 
-/*  'unit' must be defined in all functions - either as a local or a param */
+struct pf_unit units[PF_UNITS];
 
-#define PF pf[unit]
-#define PI PF.pi
+static int pf_identify(struct pf_unit *pf);
+static void pf_lock(struct pf_unit *pf, int func);
+static void pf_eject(struct pf_unit *pf);
+static int pf_check_media(kdev_t dev);
 
-static char pf_scratch[512];            /* scratch block buffer */
+static char pf_scratch[512];	/* scratch block buffer */
 
 /* the variables below are used mainly in the I/O request engine, which
    processes only one request at a time.
 */
 
-static int pf_retries = 0;              /* i/o error retry count */
-static int pf_busy = 0;                 /* request being processed ? */
-static int pf_block;                    /* address of next requested block */
-static int pf_count;                    /* number of blocks still to do */
-static int pf_run;			/* sectors in current cluster */
-static int pf_cmd;			/* current command READ/WRITE */
-static int pf_unit;			/* unit of current request */
-static int pf_mask;			/* stopper for pseudo-int */
-static char * pf_buf;                   /* buffer for request in progress */
+static int pf_retries = 0;	/* i/o error retry count */
+static int pf_busy = 0;		/* request being processed ? */
+static struct request *pf_req;	/* current request */
+static int pf_block;		/* address of next requested block */
+static int pf_count;		/* number of blocks still to do */
+static int pf_run;		/* sectors in current cluster */
+static int pf_cmd;		/* current command READ/WRITE */
+static struct pf_unit *pf_current;/* unit of current request */
+static int pf_mask;		/* stopper for pseudo-int */
+static char *pf_buf;		/* buffer for request in progress */
 
 /* kernel glue structures */
 
 static struct block_device_operations pf_fops = {
-	owner:			THIS_MODULE,
-	open:			pf_open,
-	release:		pf_release,
-	ioctl:			pf_ioctl,
-	check_media_change:	pf_check_media,
+	.owner			= THIS_MODULE,
+	.open			= pf_open,
+	.release		= pf_release,
+	.ioctl			= pf_ioctl,
+	.check_media_change	= pf_check_media,
 };
 
-void pf_init_units( void )
-
-{       int     unit, j;
+void pf_init_units(void)
+{
+	struct pf_unit *pf;
+	int unit;
 
-        pf_drive_count = 0;
-        for (unit=0;unit<PF_UNITS;unit++) {
-                PF.pi = & PF.pia;
-                PF.access = 0;
-                PF.media_status = PF_NM;
-                PF.capacity = 0;
-                PF.present = 0;
-		PF.drive = DU[D_SLV];
-		PF.lun = DU[D_LUN];
-                j = 0;
-                while ((j < PF_NAMELEN-2) && (PF.name[j]=name[j])) j++;
-                PF.name[j++] = '0' + unit;
-                PF.name[j] = 0;
-                if (DU[D_PRT]) pf_drive_count++;
-        }
-} 
-
-static int pf_open (struct inode *inode, struct file *file)
+	pf_drive_count = 0;
+	for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
+		struct gendisk *disk = &pf->disk;
+		pf->pi = &pf->pia;
+		pf->media_status = PF_NM;
+		pf->drive = (*drives[unit])[D_SLV];
+		pf->lun = (*drives[unit])[D_LUN];
+		snprintf(pf->name, PF_NAMELEN, "%s%d", name, unit);
+		disk->major = MAJOR_NR;
+		disk->first_minor = unit;
+		disk->major_name = pf->name;
+		disk->minor_shift = 0;
+		disk->fops = &pf_fops;
+		if (!(*drives[unit])[D_PRT])
+			pf_drive_count++;
+	}
+}
 
-{       int	unit = DEVICE_NR(inode->i_rdev);
+static int pf_open(struct inode *inode, struct file *file)
+{
+	int unit = DEVICE_NR(inode->i_rdev);
+	struct pf_unit *pf = units + unit;
 
-        if ((unit >= PF_UNITS) || (!PF.present)) return -ENODEV;
+	if ((unit >= PF_UNITS) || (!pf->present))
+		return -ENODEV;
 
-	pf_identify(unit);
+	pf_identify(pf);
 
-	if (PF.media_status == PF_NM)
+	if (pf->media_status == PF_NM)
 		return -ENODEV;
 
-	if ((PF.media_status == PF_RO) && (file ->f_mode & 2))
+	if ((pf->media_status == PF_RO) && (file->f_mode & 2))
 		return -EROFS;
 
-        PF.access++;
-        if (PF.removable) pf_lock(unit,1);
+	pf->access++;
+	if (pf->removable)
+		pf_lock(pf, 1);
 
-        return 0;
+	return 0;
 }
 
-static int pf_ioctl(struct inode *inode,struct file *file,
-                    unsigned int cmd, unsigned long arg)
-
-{       int err, unit;
+static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int unit = DEVICE_NR(inode->i_rdev);
 	struct hd_geometry *geo = (struct hd_geometry *) arg;
+	struct hd_geometry g;
+	struct pf_unit *pf = units + unit;
+	sector_t capacity;
+
+	if (unit >= PF_UNITS)
+		return -EINVAL;
+	if (!pf->present)
+		return -ENODEV;
 
-        if ((!inode) || kdev_none(inode->i_rdev)) return -EINVAL;
-        unit = DEVICE_NR(inode->i_rdev);
-        if (unit >= PF_UNITS) return -EINVAL;
-        if (!PF.present) return -ENODEV;
-
-        switch (cmd) {
-	    case CDROMEJECT: 
-		if (PF.access == 1) {
-			pf_eject(unit);
+	if (cmd == CDROMEJECT) {
+		if (pf->access == 1) {
+			pf_eject(pf);
 			return 0;
 		}
-	    case HDIO_GETGEO:
-                if (!geo) return -EINVAL;
-                err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
-                if (err) return err;
-                if (PF.capacity < PF_FD_MAX) {
-                    put_user(PF.capacity/(PF_FD_HDS*PF_FD_SPT),
-                                (short *) &geo->cylinders);
-                    put_user(PF_FD_HDS, (char *) &geo->heads);
-                    put_user(PF_FD_SPT, (char *) &geo->sectors);
-                } else {
-                    put_user(PF.capacity/(PF_HD_HDS*PF_HD_SPT), 
-				(short *) &geo->cylinders);
-                    put_user(PF_HD_HDS, (char *) &geo->heads);
-                    put_user(PF_HD_SPT, (char *) &geo->sectors);
-                }
-                put_user(0,(long *)&geo->start);
-                return 0;
-            case BLKGETSIZE:
-                return put_user(PF.capacity,(long *) arg);
-            case BLKGETSIZE64:
-                return put_user((u64)PF.capacity << 9,(u64 *)arg);
-            default:
-                return -EINVAL;
-        }
+		return -EBUSY;
+	}
+	if (cmd != HDIO_GETGEO)
+		return -EINVAL;
+	capacity = get_capacity(&pf->disk);
+	if (capacity < PF_FD_MAX) {
+		g.cylinders = capacity / (PF_FD_HDS * PF_FD_SPT);
+		g.heads = PF_FD_HDS;
+		g.sectors = PF_FD_SPT;
+	} else {
+		g.cylinders = capacity / (PF_HD_HDS * PF_HD_SPT);
+		g.heads = PF_HD_HDS;
+		g.sectors = PF_HD_SPT;
+	}
+	if (copy_to_user(geo, &g, sizeof(g)))
+		return -EFAULT;
+	return 0;
 }
 
+static int pf_release(struct inode *inode, struct file *file)
+{
+	int unit = DEVICE_NR(inode->i_rdev);
+	struct pf_unit *pf = units + unit;
 
-static int pf_release (struct inode *inode, struct file *file)
-
-{       kdev_t devp;
-	int	unit;
-
-        devp = inode->i_rdev;
-        unit = DEVICE_NR(devp);
-
-        if ((unit >= PF_UNITS) || (PF.access <= 0)) 
-                return -EINVAL;
+	if ((unit >= PF_UNITS) || (pf->access <= 0))
+		return -EINVAL;
 
-	PF.access--;
+	pf->access--;
 
-	if (!PF.access && PF.removable)
-		pf_lock(unit,0);
+	if (!pf->access && pf->removable)
+		pf_lock(pf, 0);
 
 	return 0;
 
 }
 
-static int pf_check_media( kdev_t dev)
-
-{       return 1;
+static int pf_check_media(kdev_t dev)
+{
+	return 1;
 }
 
-#define	WR(c,r,v)	pi_write_regr(PI,c,r,v)
-#define	RR(c,r)		(pi_read_regr(PI,c,r))
-
-#define LUN             (0x20*PF.lun)
-#define DRIVE           (0xa0+0x10*PF.drive)
+static inline int status_reg(struct pf_unit *pf)
+{
+	return pi_read_regr(pf->pi, 1, 6);
+}
 
-static int pf_wait( int unit, int go, int stop, char * fun, char * msg )
+static inline int read_reg(struct pf_unit *pf, int reg)
+{
+	return pi_read_regr(pf->pi, 0, reg);
+}
 
-{       int j, r, e, s, p;
+static inline void write_reg(struct pf_unit *pf, int reg, int val)
+{
+	pi_write_regr(pf->pi, 0, reg, val);
+}
 
-        j = 0;
-        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PF_SPIN))
-                udelay(PF_SPIN_DEL);
+static int pf_wait(struct pf_unit *pf, int go, int stop, char *fun, char *msg)
+{
+	int j, r, e, s, p;
 
-        if ((r&(STAT_ERR&stop))||(j>=PF_SPIN)) {
-           s = RR(0,7);
-           e = RR(0,1);
-           p = RR(0,2);
-           if (j >= PF_SPIN) e |= 0x100;
-           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
-                           " loop=%d phase=%d\n",
-                            PF.name,fun,msg,r,s,e,j,p);
-           return (e<<8)+s;
-        }
-        return 0;
+	j = 0;
+	while ((((r = status_reg(pf)) & go) || (stop && (!(r & stop))))
+	       && (j++ < PF_SPIN))
+		udelay(PF_SPIN_DEL);
+
+	if ((r & (STAT_ERR & stop)) || (j >= PF_SPIN)) {
+		s = read_reg(pf, 7);
+		e = read_reg(pf, 1);
+		p = read_reg(pf, 2);
+		if (j >= PF_SPIN)
+			e |= 0x100;
+		if (fun)
+			printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
+			       " loop=%d phase=%d\n",
+			       pf->name, fun, msg, r, s, e, j, p);
+		return (e << 8) + s;
+	}
+	return 0;
 }
 
-static int pf_command( int unit, char * cmd, int dlen, char * fun )
-
-{       pi_connect(PI);
+static int pf_command(struct pf_unit *pf, char *cmd, int dlen, char *fun)
+{
+	pi_connect(pf->pi);
 
-        WR(0,6,DRIVE);
+	write_reg(pf, 6, 0xa0+0x10*pf->drive);
 
-        if (pf_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
-                pi_disconnect(PI);
-                return -1;
-        }
+	if (pf_wait(pf, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
+		pi_disconnect(pf->pi);
+		return -1;
+	}
 
-        WR(0,4,dlen % 256);
-        WR(0,5,dlen / 256);
-        WR(0,7,0xa0);          /* ATAPI packet command */
+	write_reg(pf, 4, dlen % 256);
+	write_reg(pf, 5, dlen / 256);
+	write_reg(pf, 7, 0xa0);	/* ATAPI packet command */
 
-        if (pf_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
-                pi_disconnect(PI);
-                return -1;
-        }
+	if (pf_wait(pf, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
+		pi_disconnect(pf->pi);
+		return -1;
+	}
 
-        if (RR(0,2) != 1) {
-           printk("%s: %s: command phase error\n",PF.name,fun);
-           pi_disconnect(PI);
-           return -1;
-        }
+	if (read_reg(pf, 2) != 1) {
+		printk("%s: %s: command phase error\n", pf->name, fun);
+		pi_disconnect(pf->pi);
+		return -1;
+	}
 
-        pi_write_block(PI,cmd,12);
+	pi_write_block(pf->pi, cmd, 12);
 
-        return 0;
+	return 0;
 }
 
-static int pf_completion( int unit, char * buf, char * fun )
-
-{       int r, s, n;
+static int pf_completion(struct pf_unit *pf, char *buf, char *fun)
+{
+	int r, s, n;
 
-        r = pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
-			fun,"completion");
+	r = pf_wait(pf, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
+		    fun, "completion");
 
-        if ((RR(0,2)&2) && (RR(0,7)&STAT_DRQ)) { 
-                n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
-                pi_read_block(PI,buf,n);
-        }
+	if ((read_reg(pf, 2) & 2) && (read_reg(pf, 7) & STAT_DRQ)) {
+		n = (((read_reg(pf, 4) + 256 * read_reg(pf, 5)) +
+		      3) & 0xfffc);
+		pi_read_block(pf->pi, buf, n);
+	}
 
-        s = pf_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
+	s = pf_wait(pf, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
 
-        pi_disconnect(PI); 
+	pi_disconnect(pf->pi);
 
-        return (r?r:s);
+	return (r ? r : s);
 }
 
-static void pf_req_sense( int unit, int quiet )
-
-{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,LUN,0,0,16,0,0,0,0,0,0,0 };
-        char    buf[16];
-        int     r;
-
-        r = pf_command(unit,rs_cmd,16,"Request sense");
-        mdelay(1);
-        if (!r) pf_completion(unit,buf,"Request sense");
-
-        if ((!r)&&(!quiet)) 
-                printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
-                       PF.name,buf[2]&0xf,buf[12],buf[13]);
+static void pf_req_sense(struct pf_unit *pf, int quiet)
+{
+	char rs_cmd[12] =
+	    { ATAPI_REQ_SENSE, pf->lun << 5, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[16];
+	int r;
+
+	r = pf_command(pf, rs_cmd, 16, "Request sense");
+	mdelay(1);
+	if (!r)
+		pf_completion(pf, buf, "Request sense");
+
+	if ((!r) && (!quiet))
+		printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+		       pf->name, buf[2] & 0xf, buf[12], buf[13]);
 }
 
-static int pf_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
+static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fun)
+{
+	int r;
 
-{       int r;
+	r = pf_command(pf, cmd, dlen, fun);
+	mdelay(1);
+	if (!r)
+		r = pf_completion(pf, buf, fun);
+	if (r)
+		pf_req_sense(pf, !fun);
 
-        r = pf_command(unit,cmd,dlen,fun);
-        mdelay(1);
-        if (!r) r = pf_completion(unit,buf,fun);
-        if (r) pf_req_sense(unit,!fun);
-        
-        return r;
+	return r;
 }
 
 #define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 
-static void pf_lock(int unit, int func)
-
-{	char	lo_cmd[12] = { ATAPI_LOCK,LUN,0,0,func,0,0,0,0,0,0,0 };
+static void pf_lock(struct pf_unit *pf, int func)
+{
+	char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
 
-        pf_atapi(unit,lo_cmd,0,pf_scratch,func?"unlock":"lock");
+	pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");
 }
 
+static void pf_eject(struct pf_unit *pf)
+{
+	char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
 
-static void pf_eject( int unit )
-
-{	char	ej_cmd[12] = { ATAPI_DOOR,LUN,0,0,2,0,0,0,0,0,0,0 };
-
-	pf_lock(unit,0);
-	pf_atapi(unit,ej_cmd,0,pf_scratch,"eject");
+	pf_lock(pf, 0);
+	pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject");
 }
 
-#define PF_RESET_TMO   30              /* in tenths of a second */
-
-static void pf_sleep( int cs )
+#define PF_RESET_TMO   30	/* in tenths of a second */
 
-{       current->state = TASK_INTERRUPTIBLE;
-        schedule_timeout(cs);
+static void pf_sleep(int cs)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(cs);
 }
 
-
-static int pf_reset( int unit )
-
 /* the ATAPI standard actually specifies the contents of all 7 registers
    after a reset, but the specification is ambiguous concerning the last
    two bytes, and different drives interpret the standard differently.
-*/
+ */
+
+static int pf_reset(struct pf_unit *pf)
+{
+	int i, k, flg;
+	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
 
-{	int	i, k, flg;
-	int	expect[5] = {1,1,1,0x14,0xeb};
+	pi_connect(pf->pi);
+	write_reg(pf, 6, 0xa0+0x10*pf->drive);
+	write_reg(pf, 7, 8);
 
-	pi_connect(PI);
-	WR(0,6,DRIVE);
-	WR(0,7,8);
-
-	pf_sleep(20*HZ/1000);
-
-        k = 0;
-        while ((k++ < PF_RESET_TMO) && (RR(1,6)&STAT_BUSY))
-                pf_sleep(HZ/10);
+	pf_sleep(20 * HZ / 1000);
+
+	k = 0;
+	while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY))
+		pf_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(pf, i + 1) == expect[i]);
 
 	if (verbose) {
-		printk("%s: Reset (%d) signature = ",PF.name,k);
-		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
-		if (!flg) printk(" (incorrect)");
+		printk("%s: Reset (%d) signature = ", pf->name, k);
+		for (i = 0; i < 5; i++)
+			printk("%3x", read_reg(pf, i + 1));
+		if (!flg)
+			printk(" (incorrect)");
 		printk("\n");
 	}
-	
-	pi_disconnect(PI);
-	return flg-1;	
-}
 
-static void pf_mode_sense( int unit )
+	pi_disconnect(pf->pi);
+	return flg - 1;
+}
 
-{       char    ms_cmd[12] = { ATAPI_MODE_SENSE,LUN,0,0,0,0,0,0,8,0,0,0};
-	char	buf[8];
+static void pf_mode_sense(struct pf_unit *pf)
+{
+	char ms_cmd[12] =
+	    { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
+	char buf[8];
 
-        pf_atapi(unit,ms_cmd,8,buf,DBMSG("mode sense"));
-	PF.media_status = PF_RW;
-	if (buf[3] & 0x80) PF.media_status = PF_RO;
+	pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));
+	pf->media_status = PF_RW;
+	if (buf[3] & 0x80)
+		pf->media_status = PF_RO;
 }
 
-static void xs( char *buf, char *targ, int offs, int len )
-
-{	int	j,k,l;
+static void xs(char *buf, char *targ, int offs, int len)
+{
+	int j, k, l;
 
-	j=0; l=0;
-	for (k=0;k<len;k++) 
-	   if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
-		l=targ[j++]=buf[k+offs];
-	if (l==0x20) j--;
-	targ[j]=0;
+	j = 0;
+	l = 0;
+	for (k = 0; k < len; k++)
+		if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
+			l = targ[j++] = buf[k + offs];
+	if (l == 0x20)
+		j--;
+	targ[j] = 0;
 }
 
-static int xl( char *buf, int offs )
-
-{	int	v,k;
+static int xl(char *buf, int offs)
+{
+	int v, k;
 
-	v=0; 
-	for(k=0;k<4;k++) v=v*256+(buf[k+offs]&0xff);
+	v = 0;
+	for (k = 0; k < 4; k++)
+		v = v * 256 + (buf[k + offs] & 0xff);
 	return v;
 }
 
-static void pf_get_capacity( int unit )
-
-{	char    rc_cmd[12] = { ATAPI_CAPACITY,LUN,0,0,0,0,0,0,0,0,0,0};
-	char	buf[8];
-        int 	bs;
+static void pf_get_capacity(struct pf_unit *pf)
+{
+	char rc_cmd[12] = { ATAPI_CAPACITY, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[8];
+	int bs;
 
-	if (pf_atapi(unit,rc_cmd,8,buf,DBMSG("get capacity"))) {
-		PF.media_status = PF_NM;
+	if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {
+		pf->media_status = PF_NM;
 		return;
 	}
-	PF.capacity = xl(buf,0) + 1;  
-	bs = xl(buf,4);
+	set_capacity(&pf->disk, xl(buf, 0) + 1);
+	bs = xl(buf, 4);
 	if (bs != 512) {
-		PF.capacity = 0;
-		if (verbose) printk("%s: Drive %d, LUN %d,"
-		       		    " unsupported block size %d\n",
-			            PF.name,PF.drive,PF.lun,bs);
-		}
+		set_capacity(&pf->disk, 0);
+		if (verbose)
+			printk("%s: Drive %d, LUN %d,"
+			       " unsupported block size %d\n",
+			       pf->name, pf->drive, pf->lun, bs);
+	}
 }
 
-static int pf_identify( int unit )
-
-{	int 	dt, s;
-	char	*ms[2] = {"master","slave"};
-	char	mf[10], id[18];
-	char    id_cmd[12] = { ATAPI_IDENTIFY,LUN,0,0,36,0,0,0,0,0,0,0};
-	char	buf[36];
+static int pf_identify(struct pf_unit *pf)
+{
+	int dt, s;
+	char *ms[2] = { "master", "slave" };
+	char mf[10], id[18];
+	char id_cmd[12] =
+	    { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[36];
 
-        s = pf_atapi(unit,id_cmd,36,buf,"identify");
-	if (s) return -1;
+	s = pf_atapi(pf, id_cmd, 36, buf, "identify");
+	if (s)
+		return -1;
 
 	dt = buf[0] & 0x1f;
 	if ((dt != 0) && (dt != 7)) {
-	  	if (verbose) 
-		   printk("%s: Drive %d, LUN %d, unsupported type %d\n",
-				PF.name,PF.drive,PF.lun,dt);
-	  	return -1;
-       	}
-
-	xs(buf,mf,8,8);
-	xs(buf,id,16,16);
-
-	PF.removable = (buf[1] & 0x80);
-
-	pf_mode_sense(unit);
-	pf_mode_sense(unit);
-	pf_mode_sense(unit);
-
-	pf_get_capacity(unit);
-
-        printk("%s: %s %s, %s LUN %d, type %d",
-		PF.name,mf,id,ms[PF.drive],PF.lun,dt);
-        if (PF.removable) printk(", removable");
-        if (PF.media_status == PF_NM) 
-                printk(", no media\n");
-        else {  if (PF.media_status == PF_RO) printk(", RO");
-                printk(", %d blocks\n",PF.capacity);
-        }
+		if (verbose)
+			printk("%s: Drive %d, LUN %d, unsupported type %d\n",
+			       pf->name, pf->drive, pf->lun, dt);
+		return -1;
+	}
+
+	xs(buf, mf, 8, 8);
+	xs(buf, id, 16, 16);
 
+	pf->removable = (buf[1] & 0x80);
+
+	pf_mode_sense(pf);
+	pf_mode_sense(pf);
+	pf_mode_sense(pf);
+
+	pf_get_capacity(pf);
+
+	printk("%s: %s %s, %s LUN %d, type %d",
+	       pf->name, mf, id, ms[pf->drive], pf->lun, dt);
+	if (pf->removable)
+		printk(", removable");
+	if (pf->media_status == PF_NM)
+		printk(", no media\n");
+	else {
+		if (pf->media_status == PF_RO)
+			printk(", RO");
+		printk(", %ld blocks\n", get_capacity(&pf->disk));
+	}
 	return 0;
 }
 
-static int pf_probe( int unit )
-
 /*	returns  0, with id set if drive is detected
 	        -1, if drive detection failed
 */
-
-{	if (PF.drive == -1) {
-	   for (PF.drive=0;PF.drive<=1;PF.drive++)
-		if (!pf_reset(unit)) {
-		   if (PF.lun != -1) return pf_identify(unit);
-		   else for (PF.lun=0;PF.lun<8;PF.lun++) 
-                           if (!pf_identify(unit)) return 0;
-		}
+static int pf_probe(struct pf_unit *pf)
+{
+	if (pf->drive == -1) {
+		for (pf->drive = 0; pf->drive <= 1; pf->drive++)
+			if (!pf_reset(pf)) {
+				if (pf->lun != -1)
+					return pf_identify(pf);
+				else
+					for (pf->lun = 0; pf->lun < 8; pf->lun++)
+						if (!pf_identify(pf))
+							return 0;
+			}
 	} else {
-	   if (pf_reset(unit)) return -1;
-	   if (PF.lun != -1) return pf_identify(unit);
-	   for (PF.lun=0;PF.lun<8;PF.lun++) 
-	      if (!pf_identify(unit)) return 0;
+		if (pf_reset(pf))
+			return -1;
+		if (pf->lun != -1)
+			return pf_identify(pf);
+		for (pf->lun = 0; pf->lun < 8; pf->lun++)
+			if (!pf_identify(pf))
+				return 0;
 	}
-        return -1; 
+	return -1;
 }
 
-static int pf_detect( void )
-
-{	int	k, unit;
+static int pf_detect(void)
+{
+	struct pf_unit *pf = units;
+	int k, unit;
 
 	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
-		name,name,PF_VERSION,major,cluster,nice);
+	       name, name, PF_VERSION, major, cluster, nice);
 
 	k = 0;
 	if (pf_drive_count == 0) {
-	    unit = 0;
-	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pf_scratch,
-                        PI_PF,verbose,PF.name)) {
-	        if (!pf_probe(unit)) {
-			PF.present = 1;
-			k++;
-	        } else pi_release(PI);
-	    }
-
-	} else for (unit=0;unit<PF_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],pf_scratch,PI_PF,verbose,
-			PF.name)) { 
-                if (!pf_probe(unit)) {
-                        PF.present = 1;
-                        k++;
-                } else pi_release(PI);
-            }
+		if (pi_init(pf->pi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF,
+			    verbose, pf->name)) {
+			if (!pf_probe(pf)) {
+				pf->present = 1;
+				k++;
+			} else
+				pi_release(pf->pi);
+		}
 
-	if (k) return 0;
+	} else
+		for (unit = 0; unit < PF_UNITS; unit++, pf++) {
+			int *conf = *drives[unit];
+			if (!conf[D_PRT])
+				continue;
+			if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD],
+				    conf[D_UNI], conf[D_PRO], conf[D_DLY],
+				    pf_scratch, PI_PF, verbose, pf->name)) {
+				if (!pf_probe(pf)) {
+					pf->present = 1;
+					k++;
+				} else
+					pi_release(pf->pi);
+			}
+		}
+	if (k)
+		return 0;
 
-	printk("%s: No ATAPI disk detected\n",name);
+	printk("%s: No ATAPI disk detected\n", name);
 	return -1;
 }
 
 /* The i/o request engine */
 
-static int pf_start( int unit, int cmd, int b, int c )
-
-{	int	i;
-	char	io_cmd[12] = {cmd,LUN,0,0,0,0,0,0,0,0,0,0};
+static int pf_start(struct pf_unit *pf, int cmd, int b, int c)
+{
+	int i;
+	char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	for(i=0;i<4;i++) { 
-	   io_cmd[5-i] = b & 0xff;
-	   b = b >> 8;
+	for (i = 0; i < 4; i++) {
+		io_cmd[5 - i] = b & 0xff;
+		b = b >> 8;
 	}
-	
+
 	io_cmd[8] = c & 0xff;
 	io_cmd[7] = (c >> 8) & 0xff;
 
-	i = pf_command(unit,io_cmd,c*512,"start i/o");
+	i = pf_command(pf, io_cmd, c * 512, "start i/o");
 
-        mdelay(1);
+	mdelay(1);
 
-	return i;	
+	return i;
 }
 
-static int pf_ready( void )
-
-{	int	unit = pf_unit;
-
-	return (((RR(1,6)&(STAT_BUSY|pf_mask)) == pf_mask));
+static int pf_ready(void)
+{
+	return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));
 }
 
-static void do_pf_request (request_queue_t * q)
+static void do_pf_request(request_queue_t * q)
 {
 	int unit;
 
-        if (pf_busy) return;
-repeat:
-	if (blk_queue_empty(QUEUE))
+	if (pf_busy)
+		return;
+      repeat:
+	if (elv_queue_empty(QUEUE))
 		return;
 
-        pf_unit = unit = DEVICE_NR(CURRENT->rq_dev);
-        pf_block = CURRENT->sector;
-        pf_run = CURRENT->nr_sectors;
-        pf_count = CURRENT->current_nr_sectors;
-
-        if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) {
-                end_request(CURRENT, 0);
-                goto repeat;
-        }
-
-	pf_cmd = rq_data_dir(CURRENT);
-        pf_buf = CURRENT->buffer;
-        pf_retries = 0;
-
-	pf_busy = 1;
-        if (pf_cmd == READ) pi_do_claimed(PI,do_pf_read);
-        else if (pf_cmd == WRITE) pi_do_claimed(PI,do_pf_write);
-        else {  pf_busy = 0;
-		end_request(CURRENT, 0);
-                goto repeat;
-        }
-}
-
-static void pf_next_buf( int unit )
+	pf_req = elv_next_request(QUEUE);
+	unit = DEVICE_NR(pf_req->rq_dev);
+	pf_current = units + unit;
+	pf_block = pf_req->sector;
+	pf_run = pf_req->nr_sectors;
+	pf_count = pf_req->current_nr_sectors;
+
+	if ((unit >= PF_UNITS) ||
+	    (pf_block + pf_count > get_capacity(&pf_current->disk))) {
+		end_request(pf_req, 0);
+		goto repeat;
+	}
 
-{	long	saved_flags;
+	pf_cmd = rq_data_dir(pf_req);
+	pf_buf = pf_req->buffer;
+	pf_retries = 0;
 
-	spin_lock_irqsave(&pf_spin_lock,saved_flags);
-	end_request(CURRENT, 1);
-	if (!pf_run) { spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-		       return; 
+	pf_busy = 1;
+	if (pf_cmd == READ)
+		pi_do_claimed(pf_current->pi, do_pf_read);
+	else if (pf_cmd == WRITE)
+		pi_do_claimed(pf_current->pi, do_pf_write);
+	else {
+		pf_busy = 0;
+		end_request(pf_req, 0);
+		goto repeat;
 	}
-	
-/* paranoia */
+}
 
-	if (blk_queue_empty(QUEUE) ||
-	    (rq_data_dir(CURRENT) != pf_cmd) ||
-	    (DEVICE_NR(CURRENT->rq_dev) != pf_unit) ||
-	    (CURRENT->sector != pf_block)) 
-		printk("%s: OUCH: request list changed unexpectedly\n",
-			PF.name);
+static int pf_next_buf(void)
+{
+	long saved_flags;
 
-	pf_count = CURRENT->current_nr_sectors;
-	pf_buf = CURRENT->buffer;
-	spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
+	pf_count--;
+	pf_run--;
+	pf_buf += 512;
+	pf_block++;
+	if (!pf_run)
+		return 0;
+	if (!pf_count)
+		return 1;
+	spin_lock_irqsave(&pf_spin_lock, saved_flags);
+	end_request(pf_req, 1);
+	pf_count = pf_req->current_nr_sectors;
+	pf_buf = pf_req->buffer;
+	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+	return 1;
 }
 
-static void do_pf_read( void )
+static inline void next_request(int success)
+{
+	long saved_flags;
+	spin_lock_irqsave(&pf_spin_lock, saved_flags);
+	end_request(pf_req, success);
+	pf_busy = 0;
+	do_pf_request(NULL);
+	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+}
 
 /* detach from the calling context - in case the spinlock is held */
-
-{	ps_set_intr(do_pf_read_start,0,0,nice);
+static void do_pf_read(void)
+{
+	ps_set_intr(do_pf_read_start, 0, 0, nice);
 }
 
-static void do_pf_read_start( void )
-
-{       int	unit = pf_unit;
-	long	saved_flags;
-
+static void do_pf_read_start(void)
+{
 	pf_busy = 1;
 
-	if (pf_start(unit,ATAPI_READ_10,pf_block,pf_run)) {
-                pi_disconnect(PI);
-                if (pf_retries < PF_MAX_RETRIES) {
-                        pf_retries++;
-                        pi_do_claimed(PI,do_pf_read_start);
+	if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) {
+		pi_disconnect(pf_current->pi);
+		if (pf_retries < PF_MAX_RETRIES) {
+			pf_retries++;
+			pi_do_claimed(pf_current->pi, do_pf_read_start);
 			return;
-                }
-		spin_lock_irqsave(&pf_spin_lock,saved_flags);
-                end_request(CURRENT, 0);
-                pf_busy = 0;
-		do_pf_request(NULL);
-		spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-                return;
-        }
+		}
+		next_request(0);
+		return;
+	}
 	pf_mask = STAT_DRQ;
-        ps_set_intr(do_pf_read_drq,pf_ready,PF_TMO,nice);
+	ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice);
 }
 
-static void do_pf_read_drq( void )
-
-{       int	unit = pf_unit;
-	long	saved_flags;
-	
+static void do_pf_read_drq(void)
+{
 	while (1) {
-            if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
-			"read block","completion") & STAT_ERR) {
-                pi_disconnect(PI);
-                if (pf_retries < PF_MAX_RETRIES) {
-			pf_req_sense(unit,0);
-                        pf_retries++;
-                        pi_do_claimed(PI,do_pf_read_start);
-                        return;
-                }
-		spin_lock_irqsave(&pf_spin_lock,saved_flags);
-                end_request(CURRENT, 0);
-                pf_busy = 0;
-		do_pf_request(NULL);
-		spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-                return;
-            }
-            pi_read_block(PI,pf_buf,512);
-            pf_count--; pf_run--;
-            pf_buf += 512;
-	    pf_block++;
-	    if (!pf_run) break;
-	    if (!pf_count) pf_next_buf(unit);
-        }
-        pi_disconnect(PI);
-	spin_lock_irqsave(&pf_spin_lock,saved_flags); 
-        end_request(CURRENT, 1);
-        pf_busy = 0;
-	do_pf_request(NULL);
-	spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
+		if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
+			    "read block", "completion") & STAT_ERR) {
+			pi_disconnect(pf_current->pi);
+			if (pf_retries < PF_MAX_RETRIES) {
+				pf_req_sense(pf_current, 0);
+				pf_retries++;
+				pi_do_claimed(pf_current->pi, do_pf_read_start);
+				return;
+			}
+			next_request(0);
+			return;
+		}
+		pi_read_block(pf_current->pi, pf_buf, 512);
+		if (pf_next_buf())
+			break;
+	}
+	pi_disconnect(pf_current->pi);
+	next_request(1);
 }
 
-static void do_pf_write( void )
-
-{	ps_set_intr(do_pf_write_start,0,0,nice);
+static void do_pf_write(void)
+{
+	ps_set_intr(do_pf_write_start, 0, 0, nice);
 }
 
-static void do_pf_write_start( void )
-
-{       int	unit = pf_unit;
-	long	saved_flags;
-
+static void do_pf_write_start(void)
+{
 	pf_busy = 1;
 
-	if (pf_start(unit,ATAPI_WRITE_10,pf_block,pf_run)) {
-                pi_disconnect(PI);
-                if (pf_retries < PF_MAX_RETRIES) {
-                        pf_retries++;
-                        pi_do_claimed(PI,do_pf_write_start);
+	if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) {
+		pi_disconnect(pf_current->pi);
+		if (pf_retries < PF_MAX_RETRIES) {
+			pf_retries++;
+			pi_do_claimed(pf_current->pi, do_pf_write_start);
 			return;
-                }
-		spin_lock_irqsave(&pf_spin_lock,saved_flags);
-                end_request(CURRENT, 0);
-                pf_busy = 0;
-		do_pf_request(NULL);
-		spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-                return;
-        }
+		}
+		next_request(0);
+		return;
+	}
 
 	while (1) {
-            if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
-			"write block","data wait") & STAT_ERR) {
-                pi_disconnect(PI);
-                if (pf_retries < PF_MAX_RETRIES) {
-                        pf_retries++;
-                        pi_do_claimed(PI,do_pf_write_start);
-                        return;
-                }
-		spin_lock_irqsave(&pf_spin_lock,saved_flags);
-                end_request(CURRENT, 0);
-                pf_busy = 0;
-		do_pf_request(NULL);
-		spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-                return;
-            }
-            pi_write_block(PI,pf_buf,512);
-	    pf_count--; pf_run--;
-	    pf_buf += 512;
-	    pf_block++;
-	    if (!pf_run) break;
-	    if (!pf_count) pf_next_buf(unit);
+		if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,
+			    "write block", "data wait") & STAT_ERR) {
+			pi_disconnect(pf_current->pi);
+			if (pf_retries < PF_MAX_RETRIES) {
+				pf_retries++;
+				pi_do_claimed(pf_current->pi, do_pf_write_start);
+				return;
+			}
+			next_request(0);
+			return;
+		}
+		pi_write_block(pf_current->pi, pf_buf, 512);
+		if (pf_next_buf())
+			break;
 	}
 	pf_mask = 0;
-        ps_set_intr(do_pf_write_done,pf_ready,PF_TMO,nice);
+	ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice);
 }
 
-static void do_pf_write_done( void )
-
-{       int	unit = pf_unit;
-	long	saved_flags;
-
-        if (pf_wait(unit,STAT_BUSY,0,"write block","done") & STAT_ERR) {
-                pi_disconnect(PI);
-                if (pf_retries < PF_MAX_RETRIES) {
-                        pf_retries++;
-			pi_do_claimed(PI,do_pf_write_start);
-                        return;
-                }
-		spin_lock_irqsave(&pf_spin_lock,saved_flags);
-                end_request(CURRENT, 0);
-                pf_busy = 0;
-		do_pf_request(NULL);
-		spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
-                return;
-        }
-        pi_disconnect(PI);
-	spin_lock_irqsave(&pf_spin_lock,saved_flags);
-        end_request(CURRENT, 1);
-        pf_busy = 0;
-	do_pf_request(NULL);
-	spin_unlock_irqrestore(&pf_spin_lock,saved_flags);
+static void do_pf_write_done(void)
+{
+	if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) {
+		pi_disconnect(pf_current->pi);
+		if (pf_retries < PF_MAX_RETRIES) {
+			pf_retries++;
+			pi_do_claimed(pf_current->pi, do_pf_write_start);
+			return;
+		}
+		next_request(0);
+		return;
+	}
+	pi_disconnect(pf_current->pi);
+	next_request(1);
 }
 
-static int __init pf_init(void)      /* preliminary initialisation */
-{
-	int i;
-	request_queue_t * q; 
+static int __init pf_init(void)
+{				/* preliminary initialisation */
+	struct pf_unit *pf;
+	int unit;
+	request_queue_t *q;
 
 	if (disable)
 		return -1;
@@ -986,7 +974,7 @@
 		return -1;
 	pf_busy = 0;
 
-	if (register_blkdev(MAJOR_NR,name,&pf_fops)) {
+	if (register_blkdev(MAJOR_NR, name, &pf_fops)) {
 		printk("pf_init: unable to get major number %d\n", major);
 		return -1;
 	}
@@ -995,21 +983,28 @@
 	blk_queue_max_phys_segments(q, cluster);
 	blk_queue_max_hw_segments(q, cluster);
 
-	for (i=0;i<PF_UNITS;i++)
-		register_disk(NULL, mk_kdev(MAJOR_NR, i), 1, &pf_fops, 0);
-
+	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
+		struct gendisk *disk = &pf->disk;
+		if (!pf->present)
+			continue;
+		add_disk(disk);
+	}
 	return 0;
 }
 
 static void __exit pf_exit(void)
 {
+	struct pf_unit *pf;
 	int unit;
-	unregister_blkdev(MAJOR_NR,name);
-	for (unit=0;unit<PF_UNITS;unit++)
-		if (PF.present)
-			pi_release(PI);
+	unregister_blkdev(MAJOR_NR, name);
+	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
+		if (!pf->present)
+			continue;
+		del_gendisk(&pf->disk);
+		pi_release(pf->pi);
+	}
 }
- 
+
 MODULE_LICENSE("GPL");
 module_init(pf_init)
 module_exit(pf_exit)
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/block/ps2esdi.c	Sat Sep 21 21:25:43 2002
@@ -435,11 +435,9 @@
 
 	for (i = 0; i < ps2esdi_drives; i++) {
 		struct gendisk *disk = ps2esdi_gendisk + i;
-		add_gendisk(disk);
-		register_disk(disk, mk_kdev(disk->major,disk->first_minor),
-				1<<disk->minor_shift, disk->fops,
-				ps2esdi_info[i].head * ps2esdi_info[i].sect *
+		set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
 				ps2esdi_info[i].cyl);
+		add_disk(disk);
 	}
 	return 0;
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/block/rd.c	Sat Sep 21 21:25:46 2002
@@ -77,7 +77,8 @@
  */
 
 static unsigned long rd_length[NUM_RAMDISKS];	/* Size of RAM disks in bytes   */
-static int rd_kbsize[NUM_RAMDISKS];	/* Size in blocks of 1024 bytes */
+static struct gendisk rd_disks[NUM_RAMDISKS];
+static char rd_names[NUM_RAMDISKS][5];
 static devfs_handle_t devfs_handle;
 static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
 
@@ -286,37 +287,38 @@
 
 static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	int error = -EINVAL;
-	unsigned int minor;
-
-	if (!inode || kdev_none(inode->i_rdev))
-		goto out;
+	int error;
 
-	minor = minor(inode->i_rdev);
+	if (cmd != BLKFLSBUF)
+		return -EINVAL;
 
-	switch (cmd) {
-		case BLKFLSBUF:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-			/* special: we want to release the ramdisk memory,
-			   it's not like with the other blockdevices where
-			   this ioctl only flushes away the buffer cache. */
-			error = -EBUSY;
-			down(&inode->i_bdev->bd_sem);
-			if (inode->i_bdev->bd_openers <= 2) {
-				truncate_inode_pages(inode->i_mapping, 0);
-				error = 0;
-			}
-			up(&inode->i_bdev->bd_sem);
-			break;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	/* special: we want to release the ramdisk memory,
+	   it's not like with the other blockdevices where
+	   this ioctl only flushes away the buffer cache. */
+	error = -EBUSY;
+	down(&inode->i_bdev->bd_sem);
+	if (inode->i_bdev->bd_openers <= 2) {
+		truncate_inode_pages(inode->i_mapping, 0);
+		error = 0;
 	}
-out:
+	up(&inode->i_bdev->bd_sem);
 	return error;
 }
 
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
+static struct block_device_operations rd_bd_op;
+static struct gendisk initrd_disk = {
+	.major = MAJOR_NR,
+	.first_minor = INITRD_MINOR,
+	.minor_shift = 0,
+	.fops = &rd_bd_op,	
+	.major_name = "initrd"
+};
+
 static ssize_t initrd_read(struct file *file, char *buf,
 			   size_t count, loff_t *ppos)
 {
@@ -339,6 +341,7 @@
 	spin_lock(&initrd_users_lock);
 	if (!--initrd_users) {
 		spin_unlock(&initrd_users_lock);
+		del_gendisk(&initrd_disk);
 		free_initrd_mem(initrd_start, initrd_end);
 		initrd_start = 0;
 	} else {
@@ -410,6 +413,7 @@
 			invalidate_bdev(bdev, 1);
 			blkdev_put(bdev, BDEV_FILE);
 		}
+		del_gendisk(rd_disks + i);
 	}
 
 	devfs_unregister (devfs_handle);
@@ -437,9 +441,16 @@
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request);
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
+		struct gendisk *disk = rd_disks + i;
 		/* rd_size is given in kB */
 		rd_length[i] = rd_size << 10;
-		rd_kbsize[i] = rd_size;
+		disk->major = MAJOR_NR;
+		disk->first_minor = 0;
+		disk->minor_shift = 0;
+		disk->fops = &rd_bd_op;
+		sprintf(rd_names[i], "rd%d", i);
+		disk->major_name = rd_names[i];
+		set_capacity(disk, rd_size * 2);
 	}
 	devfs_handle = devfs_mk_dir (NULL, "rd", NULL);
 	devfs_register_series (devfs_handle, "%u", NUM_RAMDISKS,
@@ -448,17 +459,14 @@
 			       &rd_bd_op, NULL);
 
 	for (i = 0; i < NUM_RAMDISKS; i++)
-		register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op,
-			      rd_size<<1);
+		add_disk(rd_disks + i);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* We ought to separate initrd operations here */
-	register_disk(NULL, mk_kdev(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1);
+	add_disk(&initrd_disk);
 	devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR,
 			INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
 #endif
-
-	blk_size[MAJOR_NR] = rd_kbsize;		/* Size of the RAM disk in kB  */
 
 	/* rd_size is given in kB */
 	printk("RAMDISK driver initialized: "
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/block/swim3.c	Sat Sep 21 21:25:45 2002
@@ -38,8 +38,8 @@
 #include <linux/blk.h>
 #include <linux/devfs_fs_kernel.h>
 
-static int floppy_blocksizes[2] = {512,512};
-static int floppy_sizes[2] = {1440,1440};
+static struct gendisk disks[2];
+static char names[2][4];
 
 #define MAX_FLOPPIES	2
 
@@ -1015,6 +1015,7 @@
 int swim3_init(void)
 {
 	struct device_node *swim;
+	int i;
 
 	floppy_devfs_handle = devfs_mk_dir(NULL, "floppy", NULL);
 
@@ -1039,9 +1040,17 @@
 			       MAJOR_NR);
 			return -EBUSY;
 		}
-		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST,&swim3_lock);
-		blksize_size[MAJOR_NR] = floppy_blocksizes;
-		blk_size[MAJOR_NR] = floppy_sizes;
+		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &swim3_lock);
+		for (i = 0; i < floppy_count; i++) {
+			struct gendisk *disk = disks + i;
+			disk->major = MAJOR_NR;
+			disk->first_minor = i;
+			disk->fops = &floppy_fops;
+			sprintf(names[i], "fd%d", i);
+			disk->major_name = names[i];
+			set_capacity(disk, 2880);
+			add_disk(disk);
+		}
 	}
 
 	return 0;
diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
--- a/drivers/block/swim_iop.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/block/swim_iop.c	Sat Sep 21 21:25:43 2002
@@ -83,7 +83,8 @@
 
 static struct floppy_state floppy_states[MAX_FLOPPIES];
 
-static int floppy_sizes[2] = {2880,2880};
+static struct gendisk disks[2];
+static char names[2][4];
 
 static spinlock_t swim_iop_lock = SPIN_LOCK_UNLOCKED;
 
@@ -152,8 +153,6 @@
 	}
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request,
 			&swim_iop_lock);
-	blk_size[MAJOR_NR] = floppy_sizes;
-
 	printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
 		DRIVER_VERSION);
 
@@ -193,6 +192,16 @@
 	printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
 
 	do_floppy = NULL;
+	for (i = 0; i < floppy_count; i++) {
+		struct gendisk *disk = disks + i;
+		disk->major = MAJOR_NR;
+		disk->first_minor = i;
+		disk->fops = &floppy_fops;
+		sprintf(names[i], "fd%d", i);
+		disk->major_name = names[i];
+		set_capacity(disk, 2880 * 2);
+		add_disk(disk);
+	}
 
 	return 0;
 }
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/block/umem.c	Sat Sep 21 21:25:48 2002
@@ -1199,11 +1199,8 @@
 		disk->major_name = mm_names + i*6;
 		disk->minor_shift = MM_SHIFT;
 		disk->fops = &mm_fops;
-		add_gendisk(disk);
-		register_disk(disk, mk_kdev(disk->major, disk->first_minor),
-			      1<<disk->minor_shift,
-			      disk->fops,
-			      cards[i].mm_size << 1);
+		set_capacity(disk, cards[i].mm_size << 1);
+		add_disk(disk);
 	}
 
 	init_battery_timer();
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/block/xd.c	Sat Sep 21 21:25:48 2002
@@ -222,12 +222,9 @@
 
 	for (i = 0; i < xd_drives; i++) {
 		struct gendisk *disk = xd_gendisk + i;
-		add_gendisk(disk);
-		register_disk(disk, mk_kdev(disk->major,disk->first_minor),
-				1<<disk->minor_shift,
-				disk->fops,
-				xd_info[i].heads * xd_info[i].cylinders *
+		set_capacity(disk, xd_info[i].heads * xd_info[i].cylinders *
 				xd_info[i].sectors);
+		add_disk(disk);
 	}
 
 	return 0;
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/cdrom/aztcd.c	Sat Sep 21 21:25:48 2002
@@ -319,27 +319,9 @@
   ###########################################################################
 */
 /* CDROM Drive Low Level I/O Functions */
-void op_ok(void);
-void pa_ok(void);
-void sten_low(void);
-void dten_low(void);
-void statusAzt(void);
 static void aztStatTimer(void);
 
 /* CDROM Drive Command Functions */
-static int aztSendCmd(int cmd);
-static int sendAztCmd(int cmd, struct azt_Play_msf *params);
-static int aztSeek(struct azt_Play_msf *params);
-static int aztSetDiskType(int type);
-static int aztStatus(void);
-static int getAztStatus(void);
-static int aztPlay(struct azt_Play_msf *arg);
-static void aztCloseDoor(void);
-static void aztLockDoor(void);
-static void aztUnlockDoor(void);
-static int aztGetValue(unsigned char *result);
-static int aztGetQChannelInfo(struct azt_Toc *qp);
-static int aztUpdateToc(void);
 static int aztGetDiskInfo(void);
 #if AZT_MULTISESSION
 static int aztGetMultiDiskInfo(void);
@@ -350,21 +332,15 @@
 static int check_aztcd_media_change(kdev_t full_dev);
 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
 		       unsigned long arg);
-static void azt_transfer(void);
-static void do_aztcd_request(request_queue_t *);
-static void azt_invalidate_buffers(void);
-int aztcd_open(struct inode *ip, struct file *fp);
-
+static int aztcd_open(struct inode *ip, struct file *fp);
 static int aztcd_release(struct inode *inode, struct file *file);
 
-int aztcd_init(void);
-
 static struct block_device_operations azt_fops = {
-	owner:THIS_MODULE,
-	open:aztcd_open,
-	release:aztcd_release,
-	ioctl:aztcd_ioctl,
-	check_media_change:check_aztcd_media_change,
+	.owner			= THIS_MODULE,
+	.open			= aztcd_open,
+	.release		= aztcd_release,
+	.ioctl			= aztcd_ioctl,
+	.check_media_change	= check_aztcd_media_change,
 };
 
 /* Aztcd State Machine: Controls Drive Operating State */
@@ -384,7 +360,7 @@
    busy waiting */
 /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
 # define OP_OK op_ok()
-void op_ok(void)
+static void op_ok(void)
 {
 	aztTimeOutCount = 0;
 	do {
@@ -399,7 +375,7 @@
 
 /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
 # define PA_OK pa_ok()
-void pa_ok(void)
+static void pa_ok(void)
 {
 	aztTimeOutCount = 0;
 	do {
@@ -414,7 +390,7 @@
 
 /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
 # define STEN_LOW  sten_low()
-void sten_low(void)
+static void sten_low(void)
 {
 	aztTimeOutCount = 0;
 	do {
@@ -432,7 +408,7 @@
 
 /* Wait for DTEN=Low = handshake signal 'Data available'*/
 # define DTEN_LOW dten_low()
-void dten_low(void)
+static void dten_low(void)
 {
 	aztTimeOutCount = 0;
 	do {
@@ -450,7 +426,7 @@
  * may cause kernel panic when used in the wrong place
 */
 #define STEN_LOW_WAIT   statusAzt()
-void statusAzt(void)
+static void statusAzt(void)
 {
 	AztTimeout = AZT_STATUS_DELAY;
 	SET_TIMER(aztStatTimer, HZ / 100);
@@ -757,7 +733,7 @@
  * Read the current Q-channel info.  Also used for reading the
  * table of contents.
  */
-int aztGetQChannelInfo(struct azt_Toc *qp)
+static int aztGetQChannelInfo(struct azt_Toc *qp)
 {
 	unsigned char notUsed;
 	int st;
@@ -1648,7 +1624,7 @@
 /*
  * Open the device special file.  Check that a disk is in.
  */
-int aztcd_open(struct inode *ip, struct file *fp)
+static int aztcd_open(struct inode *ip, struct file *fp)
 {
 	int st;
 
@@ -1714,13 +1690,19 @@
 	return 0;
 }
 
-
+static struct gendisk azt_disk = {
+	.major = MAJOR_NR,
+	.first_minor = 0,
+	.minor_shift = 0,
+	.fops = &azt_fops,
+	.major_name = "aztcd"
+};
 
 /*
  * Test for presence of drive and initialize it.  Called at boot time.
  */
 
-int __init aztcd_init(void)
+static int __init aztcd_init(void)
 {
 	long int count, max_count;
 	unsigned char result[50];
@@ -1939,7 +1921,7 @@
 	}
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin);
 	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
-	register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &azt_fops, 0);
+	add_disk(&azt_disk);
 
 	azt_invalidate_buffers();
 	aztPresent = 1;
@@ -1955,9 +1937,10 @@
 
 }
 
-void __exit aztcd_exit(void)
+static void __exit aztcd_exit(void)
 {
 	devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	del_gendisk(&azt_disk);
 	if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
 		printk("What's that: can't unregister aztcd\n");
 		return;
@@ -1971,9 +1954,7 @@
 	printk(KERN_INFO "aztcd module released.\n");
 }
 
-#ifdef MODULE
 module_init(aztcd_init);
-#endif
 module_exit(aztcd_exit);
 
 /*##########################################################################
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/cdrom.c	Sat Sep 21 21:25:45 2002
@@ -327,8 +327,6 @@
 static void cdrom_sysctl_register(void);
 #endif /* CONFIG_SYSCTL */ 
 static struct cdrom_device_info *topCdromPtr;
-static devfs_handle_t devfs_handle;
-static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
 
 /* This macro makes sure we don't have to check on cdrom_device_ops
  * existence in the run-time routines below. Change_capability is a
@@ -381,26 +379,6 @@
 	if (check_media_type==1)
 		cdi->options |= (int) CDO_CHECK_TYPE;
 
-	if (!devfs_handle)
-		devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL);
-	cdi->number = devfs_alloc_unique_number (&cdrom_numspace);
-	if (cdi->de) {
-		int pos;
-		devfs_handle_t slave;
-		char rname[64];
-
-		pos = devfs_generate_path (cdi->de, rname + 3,
-					   sizeof rname - 3);
-		if (pos >= 0) {
-			char vname[16];
-			sprintf (vname, "cdrom%d", cdi->number);
-			strncpy (rname + pos, "../", 3);
-			devfs_mk_symlink (devfs_handle, vname,
-					  DEVFS_FL_DEFAULT,
-					  rname + pos, &slave, NULL);
-			devfs_auto_unregister (cdi->de, slave);
-		}
-	}
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
 	cdi->next = topCdromPtr; 	
 	topCdromPtr = cdi;
@@ -432,8 +410,6 @@
 	else
 		topCdromPtr = cdi->next;
 	cdi->ops->n_minors--;
-	devfs_unregister (cdi->de);
-	devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
 	return 0;
 }
@@ -2618,8 +2594,6 @@
 #ifdef CONFIG_SYSCTL
 	cdrom_sysctl_register();
 #endif
-	if (!devfs_handle)
-		devfs_handle = devfs_mk_dir(NULL, "cdroms", NULL);
 	return 0;
 }
 
@@ -2629,7 +2603,6 @@
 #ifdef CONFIG_SYSCTL
 	cdrom_sysctl_unregister();
 #endif
-	devfs_unregister(devfs_handle);
 }
 
 module_init(cdrom_init);
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/cdu31a.c	Sat Sep 21 21:25:45 2002
@@ -3154,41 +3154,50 @@
 
 struct block_device_operations scd_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 scd_dops = {
-	open:scd_open,
-	release:scd_release,
-	drive_status:scd_drive_status,
-	media_changed:scd_media_changed,
-	tray_move:scd_tray_move,
-	lock_door:scd_lock_door,
-	select_speed:scd_select_speed,
-	get_last_session:scd_get_last_session,
-	get_mcn:scd_get_mcn,
-	reset:scd_reset,
-	audio_ioctl:scd_audio_ioctl,
-	dev_ioctl:scd_dev_ioctl,
-	capability:CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
-	    CDC_SELECT_SPEED | CDC_MULTI_SESSION |
-	    CDC_MULTI_SESSION | CDC_MCN |
-	    CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
-	    CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS,
-	n_minors:1,
+	.open			= scd_open,
+	.release		= scd_release,
+	.drive_status		= scd_drive_status,
+	.media_changed		= scd_media_changed,
+	.tray_move		= scd_tray_move,
+	.lock_door		= scd_lock_door,
+	.select_speed		= scd_select_speed,
+	.get_last_session	= scd_get_last_session,
+	.get_mcn		= scd_get_mcn,
+	.reset			= scd_reset,
+	.audio_ioctl		= scd_audio_ioctl,
+	.dev_ioctl		= scd_dev_ioctl,
+	.capability		= CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
+				  CDC_SELECT_SPEED | CDC_MULTI_SESSION |
+				  CDC_MULTI_SESSION | CDC_MCN |
+				  CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
+				  CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS,
+	.n_minors		= 1,
 };
 
 static struct cdrom_device_info scd_info = {
-	ops:&scd_dops,
-	speed:2,
-	capacity:1,
-	name:"cdu31a"
+	.ops		= &scd_dops,
+	.speed		= 2,
+	.capacity	= 1,
+	.name		= "cdu31a"
 };
 
+static struct gendisk scd_gendisk = {
+	.major		= MAJOR_NR,
+	.first_minor	= 0,
+	.minor_shift	= 0,
+	.major_name	= "cdu31a"
+	.fops		= &scd_bdops,
+	.flags		= GENHD_FL_CD,
+}
+
 /* The different types of disc loading mechanisms supported */
 static char *load_mech[] __initdata =
     { "caddy", "tray", "pop-up", "unknown" };
@@ -3291,6 +3300,7 @@
 int __init cdu31a_init(void)
 {
 	struct s_sony_drive_config drive_config;
+	struct gendisk *disk = &scd_gendisk;
 	unsigned int res_size;
 	char msg[255];
 	char buf[40];
@@ -3431,12 +3441,9 @@
 
 		scd_info.dev = mk_kdev(MAJOR_NR, 0);
 		scd_info.mask = deficiency;
-		strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name));
-
-		if (register_cdrom(&scd_info)) {
+		if (register_cdrom(&scd_info))
 			goto errout0;
-		}
-		devfs_plain_cdrom(&scd_info, &scd_bdops);
+		add_disk(disk);
 	}
 
 
@@ -3462,6 +3469,7 @@
 
 void __exit cdu31a_exit(void)
 {
+	del_gendisk(&scd_gendisk);
 	if (unregister_cdrom(&scd_info)) {
 		printk
 		    ("Can't unregister cdu31a from Uniform cdrom driver\n");
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/cdrom/cm206.c	Sat Sep 21 21:25:48 2002
@@ -772,11 +772,11 @@
 
 struct block_device_operations cm206_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,
 };
 
 /* The new open. The real opening strategy is defined in cdrom.c. */
@@ -1330,57 +1330,41 @@
 }
 
 static struct cdrom_device_ops cm206_dops = {
-	open:cm206_open,
-	release:cm206_release,
-	drive_status:cm206_drive_status,
-	media_changed:cm206_media_changed,
-	tray_move:cm206_tray_move,
-	lock_door:cm206_lock_door,
-	select_speed:cm206_select_speed,
-	get_last_session:cm206_get_last_session,
-	get_mcn:cm206_get_upc,
-	reset:cm206_reset,
-	audio_ioctl:cm206_audio_ioctl,
-	dev_ioctl:cm206_ioctl,
-	capability:CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-	    CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-	    CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
-	    CDC_IOCTLS | CDC_DRIVE_STATUS,
-	n_minors:1,
+	.open			= cm206_open,
+	.release		= cm206_release,
+	.drive_status		= cm206_drive_status,
+	.media_changed		= cm206_media_changed,
+	.tray_move		= cm206_tray_move,
+	.lock_door		= cm206_lock_door,
+	.select_speed		= cm206_select_speed,
+	.get_last_session	= cm206_get_last_session,
+	.get_mcn		= cm206_get_upc,
+	.reset			= cm206_reset,
+	.audio_ioctl		= cm206_audio_ioctl,
+	.dev_ioctl		= cm206_ioctl,
+	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
+				  CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
+				  CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
+				  CDC_IOCTLS | CDC_DRIVE_STATUS,
+	.n_minors		= 1,
 };
 
 
 static struct cdrom_device_info cm206_info = {
-	ops:&cm206_dops,
-	speed:2,
-	capacity:1,
-	name:"cm206",
+	.ops		= &cm206_dops,
+	.speed		= 2,
+	.capacity	= 1,
+	.name		= "cm206",
 };
 
-/* This routine gets called during initialization if things go wrong,
- * can be used in cleanup_module as well. */
-static void cleanup(int level)
-{
-	switch (level) {
-	case 4:
-		if (unregister_cdrom(&cm206_info)) {
-			printk("Can't unregister cdrom cm206\n");
-			return;
-		}
-		if (unregister_blkdev(MAJOR_NR, "cm206")) {
-			printk("Can't unregister major cm206\n");
-			return;
-		}
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-	case 3:
-		free_irq(cm206_irq, NULL);
-	case 2:
-	case 1:
-		kfree(cd);
-		release_region(cm206_base, 16);
-	default:;
-	}
-}
+static struct gendisk cm206_gendisk = {
+	.major		= MAJOR_NR,
+	.first_minor	= 0,
+	.minor_shift	= 0,
+	.major_name	= "cm206",
+	.fops		= &cm206_bdops,
+	.flags		= GENHD_FL_CD,
+};
 
 /* This function probes for the adapter card. It returns the base
    address if it has found the adapter card. One can specify a base 
@@ -1435,6 +1419,7 @@
 {
 	uch e = 0;
 	long int size = sizeof(struct cm206_struct);
+	struct gendisk *disk = &cm206_gendisk;
 
 	printk(KERN_INFO "cm206 cdrom driver " REVISION);
 	cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
@@ -1454,7 +1439,7 @@
 	cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
 	if (cm206_irq <= 0) {
 		printk("can't find IRQ!\n");
-		cleanup(1);
+		goto out_probe;
 		return -EIO;
 	} else
 		printk(" IRQ %d found\n", cm206_irq);
@@ -1472,8 +1457,7 @@
 	if (send_receive_polled(c_drive_configuration) !=
 	    c_drive_configuration) {
 		printk(KERN_INFO " drive not there\n");
-		cleanup(1);
-		return -EIO;
+		goto out_probe;
 	}
 	e = send_receive_polled(c_gimme);
 	printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
@@ -1486,24 +1470,19 @@
 		printk(", motorized tray");
 	if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
 		printk("\nUnable to reserve IRQ---aborted\n");
-		cleanup(2);
-		return -EIO;
+		goto out_probe;
 	}
 	printk(".\n");
 	if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
-		printk(KERN_INFO "Cannot register for major %d!\n",
-		       MAJOR_NR);
-		cleanup(3);
-		return -EIO;
+		printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
+		goto out_blkdev;
 	}
 	cm206_info.dev = mk_kdev(MAJOR_NR, 0);
 	if (register_cdrom(&cm206_info) != 0) {
-		printk(KERN_INFO "Cannot register for cdrom %d!\n",
-		       MAJOR_NR);
-		cleanup(3);
-		return -EIO;
+		printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
+		goto out_cdrom;
 	}
-	devfs_plain_cdrom(&cm206_info, &cm206_bdops);
+	add_disk(disk);
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cm206_request,
 		       &cm206_lock);
 	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
@@ -1517,6 +1496,15 @@
 	       " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
 	       size);
 	return 0;
+
+out_cdrom:
+	unregister_blkdev(MAJOR_NR, "cm206");
+out_blkdev:
+	free_irq(cm206_irq, NULL);
+out_probe:
+	kfree(cd);
+	release_region(cm206_base, 16);
+	return -EIO;
 }
 
 #ifdef MODULE
@@ -1548,7 +1536,19 @@
 
 void __exit cm206_exit(void)
 {
-	cleanup(4);
+	del_gendisk(&cm206_gendisk);
+	if (unregister_cdrom(&cm206_info)) {
+		printk("Can't unregister cdrom cm206\n");
+		return;
+	}
+	if (unregister_blkdev(MAJOR_NR, "cm206")) {
+		printk("Can't unregister major cm206\n");
+		return;
+	}
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	free_irq(cm206_irq, NULL);
+	kfree(cd);
+	release_region(cm206_base, 16);
 	printk(KERN_INFO "cm206 removed\n");
 }
 
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/cdrom/gscd.c	Sat Sep 21 21:25:43 2002
@@ -86,14 +86,12 @@
  *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
  */
 
-static void gscd_transfer(void);
 static void gscd_read_cmd(void);
 static void gscd_hsg2msf(long hsg, struct msf *msf);
 static void gscd_bin2bcd(unsigned char *p);
 
 /* Schnittstellen zum Kern/FS */
 
-static void do_gscd_request(request_queue_t *);
 static void __do_gscd_request(unsigned long dummy);
 static int gscd_ioctl(struct inode *, struct file *, unsigned int,
 		      unsigned long);
@@ -103,13 +101,8 @@
 
 /*      GoldStar Funktionen    */
 
-static void cc_Reset(void);
-static int wait_drv_ready(void);
-static int find_drives(void);
 static void cmd_out(int, char *, char *, int);
 static void cmd_status(void);
-static void cc_Ident(char *);
-static void cc_SetSpeed(void);
 static void init_cd_drive(int);
 
 static int get_status(void);
@@ -123,10 +116,6 @@
 static int gscd_bcd2bin(unsigned char bcd);
 #endif
 
-/*    common GoldStar Initialization    */
-
-static int my_gscd_init(void);
-
 
 /*      lo-level cmd-Funktionen    */
 
@@ -164,11 +153,11 @@
 static spinlock_t gscd_lock = SPIN_LOCK_UNLOCKED;
 
 static struct block_device_operations gscd_fops = {
-	owner:THIS_MODULE,
-	open:gscd_open,
-	release:gscd_release,
-	ioctl:gscd_ioctl,
-	check_media_change:check_gscd_med_chg,
+	.owner			= THIS_MODULE,
+	.open			= gscd_open,
+	.release		= gscd_release,
+	.ioctl			= gscd_ioctl,
+	.check_media_change	= check_gscd_med_chg,
 };
 
 /* 
@@ -414,7 +403,7 @@
 }
 
 
-int get_status(void)
+static int get_status(void)
 {
 	int status;
 
@@ -430,7 +419,7 @@
 }
 
 
-void cc_invalidate(void)
+static void cc_invalidate(void)
 {
 	drv_num_read = 0xFF;
 	f_dsk_valid = 0xFF;
@@ -441,7 +430,7 @@
 
 }
 
-void clear_Audio(void)
+static void clear_Audio(void)
 {
 
 	f_AudioPlay = 0;
@@ -457,7 +446,7 @@
  *   waiting ?  
  */
 
-int wait_drv_ready(void)
+static int wait_drv_ready(void)
 {
 	int found, read;
 
@@ -475,7 +464,7 @@
 	return read;
 }
 
-void cc_Ident(char *respons)
+static void cc_Ident(char *respons)
 {
 	char to_do[] = { CMD_IDENT, 0, 0 };
 
@@ -483,7 +472,7 @@
 
 }
 
-void cc_SetSpeed(void)
+static void cc_SetSpeed(void)
 {
 	char to_do[] = { CMD_SETSPEED, 0, 0 };
 	char dummy;
@@ -494,8 +483,7 @@
 	}
 }
 
-
-void cc_Reset(void)
+static void cc_Reset(void)
 {
 	char to_do[] = { CMD_RESET, 0 };
 	char dummy;
@@ -503,9 +491,7 @@
 	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
 }
 
-
-
-void cmd_status(void)
+static void cmd_status(void)
 {
 	char to_do[] = { CMD_STATUS, 0 };
 	char dummy;
@@ -518,7 +504,7 @@
 
 }
 
-void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
+static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
 {
 	int result;
 
@@ -817,7 +803,7 @@
 	return;
 }
 
-int __init find_drives(void)
+static int __init find_drives(void)
 {
 	int *pdrv;
 	int drvnum;
@@ -861,7 +847,7 @@
 	return drvnum;
 }
 
-void __init init_cd_drive(int num)
+static void __init init_cd_drive(int num)
 {
 	char resp[50];
 	int i;
@@ -912,28 +898,20 @@
 }
 #endif
 
-/* Init for the Module-Version */
-int init_gscd(void)
-{
-	long err;
-
-
-	/* call the GoldStar-init */
-	err = my_gscd_init();
-
-	if (err < 0) {
-		return err;
-	} else {
-		printk(KERN_INFO "Happy GoldStar !\n");
-		return 0;
-	}
-}
+static struct gendisk gscd_disk = {
+	.major = MAJOR_NR,
+	.first_minor = 0,
+	,minor_shift = 0,
+	.fops = &gscd_fops,
+	.major_name = "gscd"
+};
 
-void __exit exit_gscd(void)
+static void __exit gscd_exit(void)
 {
 	CLEAR_TIMER;
 
 	devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	del_gendisk(&gscd_disk);
 	if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
 		printk("What's that: can't unregister GoldStar-module\n");
 		return;
@@ -943,22 +921,9 @@
 	printk(KERN_INFO "GoldStar-module released.\n");
 }
 
-#ifdef MODULE
-module_init(init_gscd);
-#endif
-module_exit(exit_gscd);
-
-
-/* Test for presence of drive and initialize it.  Called only at boot time. */
-int __init gscd_init(void)
-{
-	return my_gscd_init();
-}
-
-
 /* This is the common initialisation for the GoldStar drive. */
 /* It is called at boot time AND for module init.           */
-int __init my_gscd_init(void)
+static int __init gscd_init(void)
 {
 	int i;
 	int result;
@@ -1026,7 +991,7 @@
 	disk_state = 0;
 	gscdPresent = 1;
 
-	register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &gscd_fops, 0);
+	add_disk(&gscd_disk);
 
 	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
 	return 0;
@@ -1075,3 +1040,5 @@
 
 MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
 MODULE_LICENSE("GPL");
+module_init(gscd_init);
+module_exit(gscd_exit);
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/cdrom/mcd.c	Sat Sep 21 21:25:46 2002
@@ -194,31 +194,40 @@
 
 struct block_device_operations mcd_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 timer_list mcd_timer;
 
 static struct cdrom_device_ops mcd_dops = {
-	open:mcd_open,
-	release:mcd_release,
-	drive_status:mcd_drive_status,
-	media_changed:mcd_media_changed,
-	tray_move:mcd_tray_move,
-	audio_ioctl:mcd_audio_ioctl,
-	capability:CDC_OPEN_TRAY | CDC_MEDIA_CHANGED |
-	    CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
+	.open			= mcd_open,
+	.release		= mcd_release,
+	.drive_status		= mcd_drive_status,
+	.media_changed		= mcd_media_changed,
+	.tray_move		= mcd_tray_move,
+	.audio_ioctl		= mcd_audio_ioctl,
+	.capability		= CDC_OPEN_TRAY | CDC_MEDIA_CHANGED |
+				  CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
 };
 
 static struct cdrom_device_info mcd_info = {
-	ops:&mcd_dops,
-	speed:2,
-	capacity:1,
-	name:"mcd",
+	.ops		= &mcd_dops,
+	.speed		= 2,
+	.capacity	= 1,
+	.name		= "mcd",
+};
+
+static struct gendisk mcd_gendisk = {
+	.major		= MAJOR_NR,
+	.first_minor	= 0,
+	.minor_shift	= 0,
+	.major_name	= "mcd",
+	.fops		= &mcd_bdops,
+	.flags		= GENHD_FL_CD;
 };
 
 #ifndef MODULE
@@ -1023,39 +1032,13 @@
 	}
 }
 
-
-
-/* This routine gets called during initialization if things go wrong,
- * and is used in mcd_exit as well. */
-static void cleanup(int level)
-{
-	switch (level) {
-	case 3:
-		if (unregister_cdrom(&mcd_info)) {
-			printk(KERN_WARNING "Can't unregister cdrom mcd\n");
-			return;
-		}
-		free_irq(mcd_irq, NULL);
-	case 2:
-		release_region(mcd_port, 4);
-	case 1:
-		if (unregister_blkdev(MAJOR_NR, "mcd")) {
-			printk(KERN_WARNING "Can't unregister major mcd\n");
-			return;
-		}
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-	default:;
-	}
-}
-
-
-
 /*
  * Test for presence of drive and initialize it.  Called at boot time.
  */
 
 int __init mcd_init(void)
 {
+	struct gendisk *disk = &mcd_gendisk;
 	int count;
 	unsigned char result[3];
 	char msg[80];
@@ -1070,9 +1053,8 @@
 		return -EIO;
 	}
 	if (!request_region(mcd_port, 4, "mcd")) {
-		cleanup(1);
 		printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port);
-		return -EIO;
+		goto out_region;
 	}
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mcd_request,
@@ -1092,8 +1074,7 @@
 	if (count >= 2000000) {
 		printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n",
 		       mcd_port, mcd_irq);
-		cleanup(2);
-		return -EIO;
+		goto out_probe;
 	}
 	count = inb(MCDPORT(0));	/* pick up the status */
 
@@ -1102,14 +1083,11 @@
 		if (getValue(result + count)) {
 			printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n",
 			       mcd_port);
-			cleanup(2);
-			return -EIO;
+			goto out_probe;
 		}
 
-	if (result[0] == result[1] && result[1] == result[2]) {
-		cleanup(2);
-		return -EIO;
-	}
+	if (result[0] == result[1] && result[1] == result[2])
+		goto out_probe;
 
 	mcdVersion = result[2];
 
@@ -1120,8 +1098,7 @@
 
 	if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) {
 		printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
-		cleanup(2);
-		return -EIO;
+		goto out_probe;
 	}
 
 	if (result[1] == 'D') {
@@ -1151,13 +1128,20 @@
 
 	if (register_cdrom(&mcd_info) != 0) {
 		printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
-		cleanup(3);
-		return -EIO;
+		goto out_cdrom;
 	}
-	devfs_plain_cdrom(&mcd_info, &mcd_bdops);
+	add_disk(disk);
 	printk(msg);
-
 	return 0;
+
+out_cdrom:
+	free_irq(mcd_irq, NULL);
+out_probe:
+	release_region(mcd_port, 4);
+out_region:
+	unregister_blkdev(MAJOR_NR, "mcd");
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	return -EIO;
 }
 
 
@@ -1522,7 +1506,18 @@
 
 void __exit mcd_exit(void)
 {
-	cleanup(3);
+	del_gendisk(&mcd_gendisk);
+	if (unregister_cdrom(&mcd_info)) {
+		printk(KERN_WARNING "Can't unregister cdrom mcd\n");
+		return;
+	}
+	free_irq(mcd_irq, NULL);
+	release_region(mcd_port, 4);
+	if (unregister_blkdev(MAJOR_NR, "mcd")) {
+		printk(KERN_WARNING "Can't unregister major mcd\n");
+		return;
+	}
+	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	del_timer_sync(&mcd_timer);
 }
 
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/mcdx.c	Sat Sep 21 21:25:45 2002
@@ -206,6 +206,7 @@
 	int status;		/* last operation's error / status */
 	int readerrs;		/* # of blocks read w/o error */
 	struct cdrom_device_info info;
+	struct gendisk disk;
 };
 
 
@@ -1020,6 +1021,7 @@
 		struct s_drive_stuff *stuffp = mcdx_stuffp[i];
 		if (!stuffp)
 			continue;
+		del_gendisk(&stuffp->disk);
 		if (unregister_cdrom(&stuffp->info)) {
 			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
 			return;
@@ -1059,6 +1061,7 @@
 int __init mcdx_init_drive(int drive)
 {
 	struct s_version version;
+	struct gendisk *disk;
 	struct s_drive_stuff *stuffp;
 	int size = sizeof(*stuffp);
 	char msg[80];
@@ -1203,6 +1206,13 @@
 	stuffp->info.handle = stuffp;
 	sprintf(stuffp->info.name, "mcdx%d", drive);
 	stuffp->info.dev = mk_kdev(MAJOR_NR, drive);
+	disk = &stuffp->disk;
+	disk->major = MAJOR_NR;
+	disk->first_minor = drive;
+	disk->minor_shift = 0;
+	disk->major_name = stuffp->info.name;
+	disk->fops = &mcdx_bdops;
+	disk->flags = GENHD_FL_CD;
 
 	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
 		" (Firmware version %c %x)\n",
@@ -1220,7 +1230,7 @@
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		return 2;
 	}
-	devfs_plain_cdrom(&stuffp->info, &mcdx_bdops);
+	add_disk(disk);
 	printk(msg);
 	return 0;
 }
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/optcd.c	Sat Sep 21 21:25:45 2002
@@ -742,7 +742,7 @@
 
 
 #if DEBUG_TOC
-void toc_debug_info(int i)
+static void toc_debug_info(int i)
 {
 	printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
 		"  %2d:%02d.%02d %2d:%02d.%02d\n",
@@ -1973,11 +1973,11 @@
 
 
 static struct block_device_operations opt_fops = {
-	owner:			THIS_MODULE,
-	open:			opt_open,
-	release:		opt_release,
-	ioctl:			opt_ioctl,
-	check_media_change:	opt_media_change,
+	.owner			= THIS_MODULE,
+	.open			= opt_open,
+	.release		= opt_release,
+	.ioctl			= opt_ioctl,
+	.check_media_change	= opt_media_change,
 };
 
 #ifndef MODULE
@@ -1997,9 +1997,17 @@
 
 #endif /* MODULE */
 
+static struct gendisk optcd_disk = {
+	.major = MAJOR_NR,
+	.first_minor = 0,
+	.minor_shift = 0,
+	.fops = &opt_fops,
+	.major_name = "optcd"
+};
+
 /* Test for presence of drive and initialize it. Called at boot time
    or during module initialisation. */
-int __init optcd_init(void)
+static int __init optcd_init(void)
 {
 	int status;
 
@@ -2041,16 +2049,17 @@
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request,
 		       &optcd_lock);
 	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
-	register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &opt_fops, 0);
+	add_disk(&optcd_disk);
 
 	printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
 	return 0;
 }
 
 
-void __exit optcd_exit(void)
+static void __exit optcd_exit(void)
 {
 	devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	del_gendisk(&optcd_disk);
 	if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
 		printk(KERN_ERR "optcd: what's that: can't unregister\n");
 		return;
@@ -2060,10 +2069,7 @@
 	printk(KERN_INFO "optcd: module released.\n");
 }
 
-#ifdef MODULE
 module_init(optcd_init);
-#endif
 module_exit(optcd_exit);
-
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/sbpcd.c	Sat Sep 21 21:25:45 2002
@@ -722,7 +722,7 @@
 	u_char mode_xb_8;
 	u_char delay;
 	struct cdrom_device_info *sbpcd_infop;
-
+	struct gendisk disk;
 } D_S[NR_SBPCD];
 
 static struct sbpcd_drive *current_drive = D_S;
@@ -5777,6 +5777,7 @@
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		struct cdrom_device_info * sbpcd_infop;
+		struct gendisk *disk;
 		struct sbpcd_drive *p = D_S + j;
 
 		if (p->drv_id==-1) continue;
@@ -5829,15 +5830,20 @@
 		sbpcd_infop->dev = mk_kdev(MAJOR_NR, j);
 		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,
-				    &sbpcd_bdops, NULL);
+		disk = &p->disk;
+		disk->major = MAJOR_NR;
+		disk->first_minor = j;
+		disk->minor_shift = 0;
+		disk->fops = &sbpcd_bdops;
+		disk->major_name = sbpcd_infop->name;
+		disk->flags = GENHD_FL_CD;
+		sprintf(nbuff, "c0t%d", p->drv_id);
+		disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL);
 		if (register_cdrom(sbpcd_infop))
 		{
 			printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
 		}
+		add_disk(disk);
 	}
 	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE);
 
@@ -5863,8 +5869,10 @@
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		if (D_S[j].drv_id==-1) continue;
+		del_gendisk(&D_S[j].disk);
 		vfree(D_S[j].sbp_buf);
 		if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
+		devfs_unregister(D_S[j].disk.de);
 		if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
 		{
 			msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/cdrom/sjcd.c	Sat Sep 21 21:25:46 2002
@@ -1528,7 +1528,7 @@
 /*
  * Open the device special file. Check disk is in.
  */
-int sjcd_open(struct inode *ip, struct file *fp)
+static int sjcd_open(struct inode *ip, struct file *fp)
 {
 	/*
 	 * Check the presence of device.
@@ -1647,11 +1647,11 @@
  * A list of file operations allowed for this cdrom.
  */
 static struct block_device_operations sjcd_fops = {
-	owner:THIS_MODULE,
-	open:sjcd_open,
-	release:sjcd_release,
-	ioctl:sjcd_ioctl,
-	check_media_change:sjcd_disk_change,
+	.owner			= THIS_MODULE,
+	.open			= sjcd_open,
+	.release		= sjcd_release,
+	.ioctl			= sjcd_ioctl,
+	.check_media_change	= sjcd_disk_change,
 };
 
 /*
@@ -1664,11 +1664,20 @@
 	unsigned char major, minor;
 } sjcd_version;
 
+static struct gendisk sjcd_disk =
+{
+	.major = MAJOR_NR,
+	.first_minor = 0,
+	.minor_shift = 0,
+	.fops = &sjcd_fops,
+	.major_name = "sjcd"
+};
+
 /*
  * Test for presence of drive and initialize it. Called at boot time.
  * Probe cdrom, find out version and status.
  */
-int __init sjcd_init(void)
+static int __init sjcd_init(void)
 {
 	int i;
 
@@ -1688,7 +1697,6 @@
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock);
 	blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
-	register_disk(NULL, mk_kdev(MAJOR_NR, 0), 1, &sjcd_fops, 0);
 
 	if (check_region(sjcd_base, 4)) {
 		printk
@@ -1782,6 +1790,7 @@
 	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
 	devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
+	add_disk(&sjcd_disk);
 
 	sjcd_present++;
 	return (0);
@@ -1800,19 +1809,17 @@
 }
 
 
-void __exit sjcd_exit(void)
+static void __exit sjcd_exit(void)
 {
 	devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	del_gendisk(&sjcd_disk);
 	if (sjcd_cleanup())
 		printk("SJCD: module: cannot be removed.\n");
 	else
 		printk(KERN_INFO "SJCD: module: removed.\n");
 }
 
-#ifdef MODULE
 module_init(sjcd_init);
-#endif
 module_exit(sjcd_exit);
-
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/cdrom/sonycd535.c	Sat Sep 21 21:25:45 2002
@@ -1448,18 +1448,25 @@
 
 static struct block_device_operations cdu_fops =
 {
-	owner:			THIS_MODULE,
-	open:			cdu_open,
-	release:		cdu_release,
-	ioctl:			cdu_ioctl,
-	check_media_change:	cdu535_check_media_change,
+	.owner			= THIS_MODULE,
+	.open			= cdu_open,
+	.release		= cdu_release,
+	.ioctl			= cdu_ioctl,
+	.check_media_change	= cdu535_check_media_change,
 };
 
+static struct gendisk cdu_disk =
+{
+	.major = MAJOR_NR,
+	.first_minor = 0,
+	.minor_shift = 0,
+	.fops = &cdu_fops,
+	.major_name = "cdu"
+
 /*
  * Initialize the driver.
  */
-int __init 
-sony535_init(void)
+static int __init sony535_init(void)
 {
 	struct s535_sony_drive_config drive_config;
 	Byte cmd_buff[3];
@@ -1648,7 +1655,7 @@
 
 		return -EIO;
 		}
-	register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &cdu_fops, 0);
+	add_disk(&cdu_disk);
 	return 0;
 }
 
@@ -1688,7 +1695,7 @@
 #endif /* MODULE */
 
 void __exit
-sony535_exit(void)
+static sony535_exit(void)
 {
 	int i;
 
@@ -1700,15 +1707,14 @@
 	kfree(sony_toc);
 	devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0,
 				  DEVFS_SPECIAL_BLK, 0);
+	del_gendisk(&cdu_disk);
 	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
 		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
 	else
 		printk(KERN_INFO CDU535_HANDLE " module released\n");
 }
 
-#ifdef MODULE
 module_init(sony535_init);
-#endif
 module_exit(sony535_exit);
 
 
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/ide-cd.c	Sat Sep 21 21:25:45 2002
@@ -2611,12 +2611,6 @@
 	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
 		devinfo->mask |= CDC_CLOSE_TRAY;
 
-	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
-				     drive->disk->major,
-				     drive->disk->first_minor,
-				     S_IFBLK | S_IRUGO | S_IWUGO,
-				     ide_fops, NULL);
-
 	return register_cdrom(devinfo);
 }
 
@@ -3127,6 +3121,9 @@
 	memset(info, 0, sizeof (struct cdrom_info));
 	drive->driver_data = info;
 	DRIVER(drive)->busy++;
+	g->minor_shift = 0;
+	g->de = drive->de;
+	g->flags = GENHD_FL_CD;
 	if (ide_cdrom_setup(drive)) {
 		struct cdrom_device_info *devinfo = &info->devinfo;
 		DRIVER(drive)->busy--;
@@ -3146,14 +3143,7 @@
 	DRIVER(drive)->busy--;
 
 	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,
-		      get_capacity(g));
+	add_disk(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	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/ide-disk.c	Sat Sep 21 21:25:45 2002
@@ -1706,10 +1706,8 @@
 	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,
-		      current_capacity(drive));
+	set_capacity(g, current_capacity(drive));
+	add_disk(g);
 	return 0;
 failed:
 	return 1;
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/ide-floppy.c	Sat Sep 21 21:25:45 2002
@@ -2111,10 +2111,7 @@
 	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,
-		      get_capacity(g));
+	add_disk(g);
 	return 0;
 failed:
 	return 1;
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/ide-probe.c	Sat Sep 21 21:25:45 2002
@@ -563,6 +563,11 @@
 {
 	u32 i = 0;
 
+	/* register with global device tree */
+	strncpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
+	snprintf(hwif->gendev.name,DEVICE_NAME_SIZE,"IDE Controller");
+	device_register(&hwif->gendev);
+
 	if (hwif->mmio == 2)
 		return;
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
@@ -715,8 +720,9 @@
 		u16 unit = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			ide_drive_t *drive = &hwif->drives[unit];
-			if (drive->present)
+			if (drive->present) {
 				ata_attach(drive);
+			}
 		}
 	}
 #endif
@@ -973,6 +979,15 @@
 		gd[unit].major_name = names + 4*unit;
 		gd[unit].minor_shift = PARTN_BITS; 
 		gd[unit].fops = ide_fops;
+
+		snprintf(gd[unit].disk_dev.bus_id,BUS_ID_SIZE,"%u.%u",
+			 hwif->index,unit);
+		snprintf(gd[unit].disk_dev.name,DEVICE_NAME_SIZE,
+			 "%s","IDE Drive");
+		gd[unit].disk_dev.parent = &hwif->gendev;
+		gd[unit].disk_dev.bus = &ide_bus_type;
+		device_register(&gd[unit].disk_dev);
+
 		hwif->drives[unit].disk = gd + unit;
 	}
 
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/ide.c	Sat Sep 21 21:25:45 2002
@@ -152,6 +152,7 @@
 #include <linux/reboot.h>
 #include <linux/cdrom.h>
 #include <linux/seq_file.h>
+#include <linux/device.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -3524,6 +3525,10 @@
 	5
 };
 
+struct bus_type ide_bus_type = {
+	.name		= "ide",
+};
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
@@ -3537,6 +3542,8 @@
 		banner_printed = 1;
 	}
 
+	bus_register(&ide_bus_type);
+
 	init_ide_data();
 
 	initializing = 1;
@@ -3591,6 +3598,8 @@
 	proc_ide_destroy();
 #endif
 	devfs_unregister (ide_devfs_handle);
+
+	bus_unregister(&ide_bus_type);
 }
 
 #else /* !MODULE */
diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
--- a/drivers/ide/legacy/hd.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/ide/legacy/hd.c	Sat Sep 21 21:25:43 2002
@@ -838,11 +838,9 @@
 	}
 
 	for(drive=0; drive < NR_HD; drive++) {
-		add_gendisk(hd_gendisk + drive);
-		register_disk(hd_gendisk + drive,
-			mk_kdev(MAJOR_NR,drive<<6), 1<<6,
-			&hd_fops, hd_info[drive].head * hd_info[drive].sect *
-			hd_info[drive].cyl);
+		struct hd_i_struct *p = hd_info + drive;
+		set_capacity(hd_gendisk + drive, p->head * p->sect * p->cyl);
+		add_disk(hd_gendisk + drive);
 	}
 }
 
diff -Nru a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
--- a/drivers/ide/pci/cy82c693.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/pci/cy82c693.c	Sat Sep 21 21:25:45 2002
@@ -429,7 +429,7 @@
 }
 
 static struct pci_device_id cy82c693_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 
diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
--- a/drivers/ide/setup-pci.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/ide/setup-pci.c	Sat Sep 21 21:25:45 2002
@@ -389,7 +389,7 @@
 	ulong flags = pci_resource_flags(dev, bar);
 	
 	/* Unconfigured ? */
-	if(pci_resource_len(dev, bar) == 0)
+	if (!flags || pci_resource_len(dev, bar) == 0)
 		return 0;
 
 	/* I/O space */		
@@ -422,10 +422,8 @@
 	unsigned long ctl = 0, base = 0;
 	ide_hwif_t *hwif;
 	
-	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE ||
-	    ((dev->class & ~(0xfa))) ||
-	    (dev->class & (port ? 4 : 1)) != 0) 
-	{    
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+	{
 	    	/*  Possibly we should fail if these checks report true */
 	    	ide_pci_check_iomem(dev, d, 2*port);
 	    	ide_pci_check_iomem(dev, d, 2*port+1);
@@ -667,6 +665,9 @@
 	
 		if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
 			continue;
+
+		/* setup proper ancestral information */
+		hwif->gendev.parent = &dev->dev;
 
 		if (hwif->channel) {
 			index.b.high = hwif->index;
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/md/md.c	Sat Sep 21 21:25:45 2002
@@ -243,43 +243,6 @@
 	return NULL;
 }
 
-static LIST_HEAD(device_names);
-
-char * partition_name(kdev_t dev)
-{
-	struct gendisk *hd;
-	static char nomem [] = "<nomem>";
-	dev_name_t *dname;
-	struct list_head *tmp;
-
-	list_for_each(tmp, &device_names) {
-		dname = list_entry(tmp, dev_name_t, list);
-		if (kdev_same(dname->dev, dev))
-			return dname->name;
-	}
-
-	dname = (dev_name_t *) kmalloc(sizeof(*dname), GFP_KERNEL);
-
-	if (!dname)
-		return nomem;
-	/*
-	 * ok, add this new device name to the list
-	 */
-	hd = get_gendisk (dev);
-	dname->name = NULL;
-	if (hd)
-		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;
-	}
-
-	dname->dev = dev;
-	list_add(&dname->list, &device_names);
-
-	return dname->name;
-}
-
 static unsigned int calc_dev_sboffset(struct block_device *bdev)
 {
 	unsigned int size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -613,7 +576,7 @@
 static void print_desc(mdp_disk_t *desc)
 {
 	printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
-		partition_name(mk_kdev(desc->major,desc->minor)),
+		partition_name(MKDEV(desc->major,desc->minor)),
 		desc->major,desc->minor,desc->raid_disk,desc->state);
 }
 
@@ -970,7 +933,7 @@
 
 	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
-		printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(to_kdev_t(newdev)));
+		printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(newdev));
 		return ERR_PTR(-ENOMEM);
 	}
 	memset(rdev, 0, sizeof(*rdev));
@@ -981,7 +944,7 @@
 	err = lock_rdev(rdev, newdev);
 	if (err) {
 		printk(KERN_ERR "md: could not lock %s.\n",
-			partition_name(to_kdev_t(newdev)));
+			partition_name(newdev));
 		goto abort_free;
 	}
 	rdev->desc_nr = -1;
@@ -1466,9 +1429,8 @@
 		mddev->state &= ~(1 << MD_SB_CLEAN);
 	md_update_sb(mddev);
 	md_recover_arrays();
-	add_gendisk(disk);
-	register_disk(disk, mk_kdev(disk->major,disk->first_minor),
-			1, &md_fops, md_size[mdidx(mddev)]<<1);
+	set_capacity(disk, md_size[mdidx(mddev)]<<1);
+	add_disk(disk);
 	disks[mdidx(mddev)] = disk;
 
 	return (0);
@@ -1754,7 +1716,7 @@
 
 	start_rdev = md_import_device(startdev, 1);
 	if (IS_ERR(start_rdev)) {
-		printk(KERN_WARNING "md: could not import %s!\n", partition_name(to_kdev_t(startdev)));
+		printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev));
 		goto abort;
 	}
 
@@ -1789,7 +1751,7 @@
 		rdev = md_import_device(dev, 1);
 		if (IS_ERR(rdev)) {
 			printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n",
-			       partition_name(to_kdev_t(dev)));
+			       partition_name(dev));
 			continue;
 		}
 		list_add(&rdev->same_set, &pending_raid_disks);
@@ -1994,7 +1956,7 @@
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to generate %s error in md%d ... \n",
-		partition_name(to_kdev_t(dev)), mdidx(mddev));
+		partition_name(dev), mdidx(mddev));
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev) {
@@ -2028,7 +1990,7 @@
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
-		partition_name(to_kdev_t(dev)), mdidx(mddev));
+		partition_name(dev), mdidx(mddev));
 
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
@@ -2057,7 +2019,7 @@
 		return -ENODEV;
 
 	printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
-		partition_name(to_kdev_t(dev)), mdidx(mddev));
+		partition_name(dev), mdidx(mddev));
 
 	if (!mddev->pers->hot_add_disk) {
 		printk(KERN_WARNING "md%d: personality does not support diskops!\n",
@@ -2232,7 +2194,7 @@
 		err = autostart_array(arg);
 		if (err) {
 			printk(KERN_WARNING "md: autostart %s failed!\n",
-			       partition_name(val_to_kdev(arg)));
+			       partition_name(arg));
 			goto abort;
 		}
 		goto done;
@@ -3231,7 +3193,7 @@
 		rdev = md_import_device(dev,1);
 		if (IS_ERR(rdev)) {
 			printk(KERN_ALERT "md: could not import %s!\n",
-				partition_name(to_kdev_t(dev)));
+				partition_name(dev));
 			continue;
 		}
 		if (rdev->faulty) {
@@ -3499,17 +3461,6 @@
 	return md_init();
 }
 
-static void free_device_names(void)
-{
-	while (!list_empty(&device_names)) {
-		dev_name_t *tmp = list_entry(device_names.next,
-					     dev_name_t, list);
-		list_del(&tmp->list);
-		kfree(tmp);
-	}
-}
-
-
 void cleanup_module(void)
 {
 	md_unregister_thread(md_recovery_thread);
@@ -3524,15 +3475,12 @@
 
 	blk_dev[MAJOR_NR].queue = NULL;
 	blk_clear(MAJOR_NR);
-	
-	free_device_names();
 }
 #endif
 
 EXPORT_SYMBOL(md_size);
 EXPORT_SYMBOL(register_md_personality);
 EXPORT_SYMBOL(unregister_md_personality);
-EXPORT_SYMBOL(partition_name);
 EXPORT_SYMBOL(md_error);
 EXPORT_SYMBOL(md_sync_acct);
 EXPORT_SYMBOL(md_done_sync);
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Sat Sep 21 21:25:47 2002
+++ b/drivers/message/i2o/i2o_block.c	Sat Sep 21 21:25:48 2002
@@ -719,11 +719,7 @@
 				struct gendisk *p = &i2o_disk[unit>>4];
 				i2ob_install_device(i2ob_dev[unit].i2odev->controller, 
 					i2ob_dev[unit].i2odev, unit);
-				add_gendisk(p);
-				register_disk(p,
-					      mk_kdev(p->major, p->first_minor),
-					      1<<p->minor_shift, p->fops,
-					      get_capacity(p));
+				add_disk(p);
 				break;
 			}
 
@@ -1465,12 +1461,7 @@
 					printk(KERN_WARNING "Could not install I2O block device\n");
 				else
 				{
-					struct gendisk *p = &i2o_disk[scan_unit>>4];
-					add_gendisk(p);
-					register_disk(p,
-						      mk_kdev(p->major, p->first_minor),
-						      1<<p->minor_shift, p->fops,
-						      get_capacity(p));
+					add_disk(&i2o_disk[scan_unit>>4]);
 					scan_unit+=16;
 					i2ob_dev_count++;
 
@@ -1558,12 +1549,7 @@
 		printk(KERN_ERR "i2o_block: Could not install new device\n");
 	else	
 	{
-		struct gendisk *p = &i2o_disk[unit>>4];
-		add_gendisk(p);
-		register_disk(p,
-			      mk_kdev(p->major, p->first_minor),
-			      1<<p->minor_shift, p->fops,
-			      get_capacity(p));
+		add_disk(&i2o_disk[unit>>4]);
 		i2ob_dev_count++;
 		i2o_device_notify_on(d, &i2o_block_handler);
 	}
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/mtd/ftl.c	Sat Sep 21 21:25:45 2002
@@ -94,12 +94,6 @@
 
 /* Funky stuff for setting up a block device */
 #define MAJOR_NR		FTL_MAJOR
-#define DEVICE_OFF(device)
-
-#define DEVICE_NR(minor)	((minor)>>5)
-#define REGION_NR(minor)	(((minor)>>3)&3)
-#define PART_NR(minor)		((minor)&7)
-#define MINOR_NR(dev,reg,part)	(((dev)<<5)+((reg)<<3)+(part))
 
 #include <linux/blk.h>
 
@@ -1258,10 +1252,8 @@
 		partition->state = FTL_FORMATTED;
 		atomic_set(&partition->open, 0);
 		myparts[device] = partition;
-		add_gendisk(disk);
-		register_disk(disk, mk_kdev(MAJOR_NR, device << 4),
-			      MAX_PART, &ftl_blk_fops,
-			      le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE);
+		set_capacity(disk, le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE);
+		add_disk(disk);
 #ifdef PCMCIA_DEBUG
 		printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n",
 		       le32_to_cpu(partition->header.FormattedSize) >> 10);
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/mtd/mtdblock.c	Sat Sep 21 21:25:45 2002
@@ -490,13 +490,7 @@
 	return 0;
 }
 
-#if LINUX_VERSION_CODE < 0x20300
-#define RQFUNC_ARG void
-#else
-#define RQFUNC_ARG request_queue_t *q
-#endif
-
-static void mtdblock_request(RQFUNC_ARG)
+static void mtdblock_request(request_queue *q)
 {
 	/* Don't do anything, except wake the thread if necessary */
 	wake_up(&thr_wq);
@@ -522,10 +516,8 @@
 		return put_user((u64)mtdblk->mtd->size, (u64 *)arg);
 		
 	case BLKFLSBUF:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
 		if(!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-#endif
 		fsync_bdev(inode->i_bdev);
 		invalidate_bdev(inode->i_bdev, 0);
 		down(&mtdblk->cache_sem);
@@ -540,16 +532,6 @@
 	}
 }
 
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations mtd_fops =
-{
-	open: mtdblock_open,
-	ioctl: mtdblock_ioctl,
-	release: mtdblock_release,
-	read: block_read,
-	write: block_write
-};
-#else
 static struct block_device_operations mtd_fops = 
 {
 	owner: THIS_MODULE,
@@ -557,7 +539,6 @@
 	release: mtdblock_release,
 	ioctl: mtdblock_ioctl
 };
-#endif
 
 #ifdef CONFIG_DEVFS_FS
 /* Notification that a new device has been added. Create the devfs entry for
diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
--- a/drivers/mtd/mtdblock_ro.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/mtd/mtdblock_ro.c	Sat Sep 21 21:25:45 2002
@@ -22,35 +22,24 @@
 #define DEVICE_NR(device) (device)
 #include <linux/blk.h>
 
-#if LINUX_VERSION_CODE < 0x20300
-#define RQFUNC_ARG void
-#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0)
-#else
 #define RQFUNC_ARG request_queue_t *q
-#endif
 
 #ifdef MTDBLOCK_DEBUG
 static int debug = MTDBLOCK_DEBUG;
 MODULE_PARM(debug, "i");
 #endif
 
-
-static int mtd_sizes[MAX_MTD_DEVICES];
-
+static struct gendisk mtd_disks[MAX_MTD_DEVICES];
+static char names names[MAX_MTD_DEVICES][11];
 
 static int mtdblock_open(struct inode *inode, struct file *file)
 {
 	struct mtd_info *mtd = NULL;
-
-	int dev;
+	int dev = minor(inode->i_rdev);
+	struct gendisk *disk = mtd_disks + dev;
 
 	DEBUG(1,"mtdblock_open\n");
-	
-	if (inode == 0)
-		return -EINVAL;
-	
-	dev = minor(inode->i_rdev);
-	
+
 	mtd = get_mtd_device(NULL, dev);
 	if (!mtd)
 		return -EINVAL;
@@ -59,7 +48,8 @@
 		return -EINVAL;
 	}
 
-	mtd_sizes[dev] = mtd->size>>9;
+	set_capacit(disk, mtd->size>>9);
+	add_disk(disk);
 
 	DEBUG(1, "ok\n");
 
@@ -83,6 +73,8 @@
 		printk(KERN_WARNING "MTD device is absent on mtd_release!\n");
 		release_return(-ENODEV);
 	}
+
+	del_gendisk(mtd_disks + dev);
 	
 	if (mtd->sync)
 		mtd->sync(mtd);
@@ -143,12 +135,10 @@
       
       /* Remove the request we are handling from the request list so nobody messes
          with it */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
       /* Now drop the lock that the ll_rw_blk functions grabbed for us
          and process the request. This is necessary due to the extreme time
          we spend processing it. */
       spin_unlock_irq(&io_request_lock);
-#endif
 
       // Handle the request
       switch (current_request->cmd)
@@ -193,9 +183,7 @@
       }
 
       // Grab the lock and re-thread the item onto the linked list
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
 	spin_lock_irq(&io_request_lock);
-#endif
 	mtdblock_end_request(current_request, res);
    }
 }
@@ -209,47 +197,25 @@
 
 	mtd = __get_mtd_device(NULL, minor(inode->i_rdev));
 
-	if (!mtd) return -EINVAL;
-
-	switch (cmd) {
-	case BLKGETSIZE:   /* Return device size */
-		return put_user((mtd->size >> 9), (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user((u64)mtd->size, (u64 *)arg);
-		
-	case BLKFLSBUF:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-		if(!capable(CAP_SYS_ADMIN))  return -EACCES;
-#endif
-		fsync_bdev(inode->i_bdev);
-		invalidate_bdev(inode->i_bdev, 0);
-		if (mtd->sync)
-			mtd->sync(mtd);
-		return 0;
+	if (!mtd || cmd != BLKFLSBUF)
+		return -EINVAL;
 
-	default:
-		return -ENOTTY;
-	}
+	if(!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	fsync_bdev(inode->i_bdev);
+	invalidate_bdev(inode->i_bdev, 0);
+	if (mtd->sync)
+		mtd->sync(mtd);
+	return 0;
 }
 
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations mtd_fops =
-{
-	open: mtdblock_open,
-	ioctl: mtdblock_ioctl,
-	release: mtdblock_release,
-	read: block_read,
-	write: block_write
-};
-#else
 static struct block_device_operations mtd_fops = 
 {
-	owner: THIS_MODULE,
-	open: mtdblock_open,
-	release: mtdblock_release,
-	ioctl: mtdblock_ioctl
+	.owner		= THIS_MODULE,
+	.open		= mtdblock_open,
+	.release	= mtdblock_release,
+	.ioctl		= mtdblock_ioctl
 };
-#endif
 
 int __init init_mtdblock(void)
 {
@@ -260,16 +226,17 @@
 		       MTD_BLOCK_MAJOR);
 		return -EAGAIN;
 	}
-	
-	/* We fill it in at open() time. */
-	for (i=0; i< MAX_MTD_DEVICES; i++) {
-		mtd_sizes[i] = 0;
-	}
-	
-	/* Allow the block size to default to BLOCK_SIZE. */
-	blk_size[MAJOR_NR] = mtd_sizes;
-	
+
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
+
+	for (i = 0; i < MAX_MTD_DEVICES; i++) {
+		struct gendisk *disk = mtd_disks + i;
+		disk->major = MAJOR_NR;
+		disk->first_minor = i;
+		sprintf(names[i], "mtdblock%d", i);
+		disk->major_name = names[i];
+		disk->fops = &mtd_fops;
+	}
 	return 0;
 }
 
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/mtd/nftlcore.c	Sat Sep 21 21:25:43 2002
@@ -41,8 +41,6 @@
 
 /* NFTL block device stuff */
 #define MAJOR_NR NFTL_MAJOR
-#define DEVICE_OFF(device)
-
 
 #include <linux/blk.h>
 #include <linux/hdreg.h>
@@ -141,10 +139,9 @@
 	gd->first_minor = firstfree << NFTL_PARTN_BITS;
 	gd->minor_shift = NFTL_PARTN_BITS;
 	gd->major_name = name;
+	set_capacity(gd, nftl->nr_sects);
 	nftl->disk = gd;
-	add_gendisk(gd);
-	register_disk(gd, mk_kdev(MAJOR_NR,firstfree<<NFTL_PARTN_BITS),
-		      1<<NFTL_PARTN_BITS, &nftl_fops, nftl->nr_sects);
+	add_disk(gd);
 }
 
 static void NFTL_unsetup(int i)
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/8139cp.c	Sat Sep 21 21:25:45 2002
@@ -22,11 +22,11 @@
 	
 		Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
 		PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
+		LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
 			
 	TODO, in rough priority order:
 	* Test Tx checksumming thoroughly
 	* dev->tx_timeout
-	* LinkChg interrupt
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Constants (module parms?) for Rx work limit
@@ -677,6 +677,8 @@
 		cp_rx(cp);
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
+	if (status & LinkChg)
+		mii_check_media(&cp->mii_if, netif_msg_link(cp));
 
 	if (status & PciErr) {
 		u16 pci_status;
@@ -1192,6 +1194,8 @@
 	if (rc)
 		goto err_out_hw;
 
+	netif_carrier_off(dev);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp));
 	netif_start_queue(dev);
 
 	return 0;
@@ -1210,6 +1214,7 @@
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
 	netif_stop_queue(dev);
+	netif_carrier_off(dev);
 
 	spin_lock_irq(&cp->lock);
 	cp_stop_hw(cp);
@@ -1649,14 +1654,27 @@
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct cp_private *cp = dev->priv;
+	struct mii_ioctl_data *mii;
 	int rc = 0;
 
+	mii = (struct mii_ioctl_data *) &rq->ifr_data;
 	if (!netif_running(dev))
 		return -EINVAL;
 
+	if (cmd != SIOCETHTOOL) 
+		mii->reg_num &= 0x1f;
+	
 	switch (cmd) {
 	case SIOCETHTOOL:
 		return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
+		
+ 	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
+		mii->phy_id = CP_INTERNAL_PHY;
+		/* Fall Through */
+
+	case SIOCGMIIREG:	/* Read the specified MII register. */
+		mii->val_out = mdio_read (dev, CP_INTERNAL_PHY, mii->reg_num);
+		break;
 
 	default:
 		rc = -EOPNOTSUPP;
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/Makefile	Sat Sep 21 21:25:45 2002
@@ -41,7 +41,7 @@
 obj-$(CONFIG_VORTEX) += 3c59x.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_PCNET32) += pcnet32.o mii.o
-obj-$(CONFIG_EEPRO100) += eepro100.o
+obj-$(CONFIG_EEPRO100) += eepro100.o mii.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o mii.o
 obj-$(CONFIG_SIS900) += sis900.o
diff -Nru a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
--- a/drivers/net/irda/actisys.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/net/irda/actisys.c	Sat Sep 21 21:25:48 2002
@@ -165,7 +165,7 @@
 	int ret = 0;
 	int i = 0;
 
-        IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed, 
+        IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __FUNCTION__, speed, 
 		   self->speed);
 
 	/* Go to a known state by reseting the dongle */
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/irda/irda-usb.c	Sat Sep 21 21:25:45 2002
@@ -156,12 +156,12 @@
 		    (!force) && (self->speed != -1)) {
 			/* No speed and xbofs change here
 			 * (we'll do it later in the write callback) */
-			IRDA_DEBUG(2, __FUNCTION__ "(), not changing speed yet\n");
+			IRDA_DEBUG(2, "%s(), not changing speed yet\n", __FUNCTION__);
 			*header = 0;
 			return;
 		}
 
-		IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed);
+		IRDA_DEBUG(2, "%s(), changing speed to %d\n", __FUNCTION__, self->new_speed);
 		self->speed = self->new_speed;
 		/* We will do ` self->new_speed = -1; ' in the completion
 		 * handler just in case the current URB fail - Jean II */
@@ -203,7 +203,7 @@
 	
 	/* Set the negotiated additional XBOFS */
 	if (self->new_xbofs != -1) {
-		IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs);
+		IRDA_DEBUG(2, "%s(), changing xbofs to %d\n", __FUNCTION__, self->new_xbofs);
 		self->xbofs = self->new_xbofs;
 		/* We will do ` self->new_xbofs = -1; ' in the completion
 		 * handler just in case the current URB fail - Jean II */
@@ -251,13 +251,13 @@
 	struct urb *urb;
 	int ret;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, xbofs=%d\n",
+	IRDA_DEBUG(2, "%s(), speed=%d, xbofs=%d\n", __FUNCTION__,
 		   self->new_speed, self->new_xbofs);
 
 	/* Grab the speed URB */
 	urb = self->speed_urb;
 	if (urb->status != 0) {
-		WARNING(__FUNCTION__ "(), URB still in use!\n");
+		WARNING("%s(), URB still in use!\n", __FUNCTION__);
 		return;
 	}
 
@@ -278,7 +278,7 @@
 
 	/* Irq disabled -> GFP_ATOMIC */
 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
-		WARNING(__FUNCTION__ "(), failed Speed URB\n");
+		WARNING("%s(), failed Speed URB\n", __FUNCTION__);
 	}
 }
 
@@ -291,7 +291,7 @@
 {
 	struct irda_usb_cb *self = urb->context;
 	
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	/* We should always have a context */
 	ASSERT(self != NULL, return;);
@@ -301,7 +301,7 @@
 	/* Check for timeout and other USB nasties */
 	if (urb->status != 0) {
 		/* I get a lot of -ECONNABORTED = -103 here - Jean II */
-		IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags);
+		IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __FUNCTION__, urb->status, urb->transfer_flags);
 
 		/* Don't do anything here, that might confuse the USB layer.
 		 * Instead, we will wait for irda_usb_net_timeout(), the
@@ -336,7 +336,7 @@
 	int res, mtt;
 	int	err = 1;	/* Failed */
 
-	IRDA_DEBUG(4, __FUNCTION__ "() on %s\n", netdev->name);
+	IRDA_DEBUG(4, "%s() on %s\n", __FUNCTION__, netdev->name);
 
 	netif_stop_queue(netdev);
 
@@ -347,7 +347,7 @@
 	 * We need to check self->present under the spinlock because
 	 * of irda_usb_disconnect() is synchronous - Jean II */
 	if (!self->present) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n");
+		IRDA_DEBUG(0, "%s(), Device is gone...\n", __FUNCTION__);
 		goto drop;
 	}
 
@@ -381,7 +381,7 @@
 	}
 
 	if (urb->status != 0) {
-		WARNING(__FUNCTION__ "(), URB still in use!\n");
+		WARNING("%s(), URB still in use!\n", __FUNCTION__);
 		goto drop;
 	}
 
@@ -390,9 +390,9 @@
 	 * Also, we don't use directly skb_cow(), because it require
 	 * headroom >= 16, which force unnecessary copies - Jean II */
 	if (skb_headroom(skb) < USB_IRDA_HEADER) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), Insuficient skb headroom.\n");
+		IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
 		if (skb_cow(skb, USB_IRDA_HEADER)) {
-			WARNING(__FUNCTION__ "(), failed skb_cow() !!!\n");
+			WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
 			goto drop;
 		}
 	}
@@ -463,7 +463,7 @@
 	
 	/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */
 	if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {
-		WARNING(__FUNCTION__ "(), failed Tx URB\n");
+		WARNING("%s(), failed Tx URB\n", __FUNCTION__);
 		self->stats.tx_errors++;
 		/* Let USB recover : We will catch that in the watchdog */
 		/*netif_start_queue(netdev);*/
@@ -495,7 +495,7 @@
 	struct sk_buff *skb = urb->context;
 	struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context;
 	
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	/* We should always have a context */
 	ASSERT(self != NULL, return;);
@@ -509,7 +509,7 @@
 	/* Check for timeout and other USB nasties */
 	if (urb->status != 0) {
 		/* I get a lot of -ECONNABORTED = -103 here - Jean II */
-		IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", urb->status, urb->transfer_flags);
+		IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __FUNCTION__, urb->status, urb->transfer_flags);
 
 		/* Don't do anything here, that might confuse the USB layer,
 		 * and we could go in recursion and blow the kernel stack...
@@ -528,7 +528,7 @@
 
 	/* If the network is closed, stop everything */
 	if ((!self->netopen) || (!self->present)) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n");
+		IRDA_DEBUG(0, "%s(), Network is gone...\n", __FUNCTION__);
 		spin_unlock_irqrestore(&self->lock, flags);
 		return;
 	}
@@ -539,7 +539,7 @@
 		    (self->new_xbofs != self->xbofs)) {
 			/* We haven't changed speed yet (because of
 			 * IUC_SPEED_BUG), so do it now - Jean II */
-			IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n");
+			IRDA_DEBUG(1, "%s(), Changing speed now...\n", __FUNCTION__);
 			irda_usb_change_speed_xbofs(self);
 		} else {
 			/* New speed and xbof is now commited in hardware */
@@ -571,7 +571,7 @@
 	struct urb *urb;
 	int	done = 0;	/* If we have made any progress */
 
-	IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
+	IRDA_DEBUG(0, "%s(), Network layer thinks we timed out!\n", __FUNCTION__);
 	ASSERT(self != NULL, return;);
 
 	/* Protect us from USB callbacks, net Tx and else. */
@@ -579,7 +579,7 @@
 
 	/* self->present *MUST* be read under spinlock */
 	if (!self->present) {
-		WARNING(__FUNCTION__ "(), device not present!\n");
+		WARNING("%s(), device not present!\n", __FUNCTION__);
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&self->lock, flags);
 		return;
@@ -702,11 +702,11 @@
 	struct irda_skb_cb *cb;
 	int ret;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	/* Check that we have an urb */
 	if (!urb) {
-		WARNING(__FUNCTION__ "(), Bug : urb == NULL\n");
+		WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__);
 		return;
 	}
 
@@ -716,7 +716,7 @@
 		if (!skb) {
 			/* If this ever happen, we are in deep s***.
 			 * Basically, the Rx path will stop... */
-			WARNING(__FUNCTION__ "(), Failed to allocate Rx skb\n");
+			WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
 			return;
 		}
 	} else  {
@@ -745,7 +745,7 @@
 	if (ret) {
 		/* If this ever happen, we are in deep s***.
 		 * Basically, the Rx path will stop... */
-		WARNING(__FUNCTION__ "(), Failed to submit Rx URB %d\n", ret);
+		WARNING("%s(), Failed to submit Rx URB %d\n", __FUNCTION__, ret);
 	}
 }
 
@@ -763,7 +763,7 @@
 	struct irda_skb_cb *cb;
 	struct sk_buff *new;
 	
-	IRDA_DEBUG(2, __FUNCTION__ "(), len=%d\n", urb->actual_length);
+	IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
 	
 	/* Find ourselves */
 	cb = (struct irda_skb_cb *) skb->cb;
@@ -773,7 +773,7 @@
 
 	/* If the network is closed or the device gone, stop everything */
 	if ((!self->netopen) || (!self->present)) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone!\n");
+		IRDA_DEBUG(0, "%s(), Network is gone!\n", __FUNCTION__);
 		/* Don't re-submit the URB : will stall the Rx path */
 		return;
 	}
@@ -786,13 +786,13 @@
 			self->stats.rx_crc_errors++;	
 			break;
 		case -ECONNRESET:		/* -104 */
-			IRDA_DEBUG(0, __FUNCTION__ "(), Connection Reset (-104), transfer_flags 0x%04X \n", urb->transfer_flags);
+			IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags);
 			/* uhci_cleanup_unlink() is going to kill the Rx
 			 * URB just after we return. No problem, at this
 			 * point the URB will be idle ;-) - Jean II */
 			break;
 		default:
-			IRDA_DEBUG(0, __FUNCTION__ "(), RX status %d,transfer_flags 0x%04X \n", urb->status, urb->transfer_flags);
+			IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);
 			break;
 		}
 		goto done;
@@ -800,7 +800,7 @@
 	
 	/* Check for empty frames */
 	if (urb->actual_length <= USB_IRDA_HEADER) {
-		WARNING(__FUNCTION__ "(), empty frame!\n");
+		WARNING("%s(), empty frame!\n", __FUNCTION__);
 		goto done;
 	}
 
@@ -905,7 +905,7 @@
  */
 static int irda_usb_net_init(struct net_device *dev)
 {
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 	
 	/* Set up to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -929,7 +929,7 @@
 	char	hwname[16];
 	int i;
 	
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	ASSERT(netdev != NULL, return -1;);
 	self = (struct irda_usb_cb *) netdev->priv;
@@ -937,7 +937,7 @@
 
 	/* Can only open the device if it's there */
 	if(!self->present) {
-		WARNING(__FUNCTION__ "(), device not present!\n");
+		WARNING("%s(), device not present!\n", __FUNCTION__);
 		return -1;
 	}
 
@@ -993,7 +993,7 @@
 	struct irda_usb_cb *self;
 	int	i;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	ASSERT(netdev != NULL, return -1;);
 	self = (struct irda_usb_cb *) netdev->priv;
@@ -1049,7 +1049,7 @@
 	self = dev->priv;
 	ASSERT(self != NULL, return -1;);
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
 
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
@@ -1107,7 +1107,7 @@
 {
 	struct irda_class_desc *desc;
 
-	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 	
 	desc = self->irda_desc;
 	
@@ -1120,7 +1120,8 @@
 	self->qos.window_size.bits     = desc->bmWindowSize;
 	self->qos.data_size.bits       = desc->bmDataSize;
 
-	IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits);
+	IRDA_DEBUG(0, "%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", 
+		__FUNCTION__, self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits);
 
 	/* Don't always trust what the dongle tell us */
 	if(self->capability & IUC_SIR_ONLY)
@@ -1164,7 +1165,7 @@
 	struct net_device *netdev;
 	int err;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	spin_lock_init(&self->lock);
 
@@ -1184,7 +1185,7 @@
 
 	/* Create a network device for us */
 	if (!(netdev = dev_alloc("irda%d", &err))) {
-		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
 		return -1;
 	}
 	self->netdev = netdev;
@@ -1204,7 +1205,7 @@
 	err = register_netdevice(netdev);
 	rtnl_unlock();
 	if (err) {
-		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
 		return -1;
 	}
 	MESSAGE("IrDA: Registered device %s\n", netdev->name);
@@ -1219,7 +1220,7 @@
  */
 static inline int irda_usb_close(struct irda_usb_cb *self)
 {
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	ASSERT(self != NULL, return -1;);
 
@@ -1301,12 +1302,13 @@
 				/* This is our interrupt endpoint */
 				self->bulk_int_ep = ep;
 			} else {
-				ERROR(__FUNCTION__ "(), Unrecognised endpoint %02X.\n", ep);
+				ERROR("%s(), Unrecognised endpoint %02X.\n", __FUNCTION__, ep);
 			}
 		}
 	}
 
-	IRDA_DEBUG(0, __FUNCTION__ "(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
+	IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n",
+		__FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
 	/* Should be 8, 16, 32 or 64 bytes */
 	ASSERT(self->bulk_out_mtu == 64, ;);
 
@@ -1368,7 +1370,7 @@
 		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 		0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500));
 	
-	IRDA_DEBUG(1, __FUNCTION__ "(), ret=%d\n", ret);
+	IRDA_DEBUG(1, "%s(), ret=%d\n", __FUNCTION__, ret);
 	if (ret < sizeof(*desc)) {
 		WARNING("usb-irda: class_descriptor read %s (%d)\n",
 			(ret<0) ? "failed" : "too short", ret);
@@ -1427,7 +1429,7 @@
 		if((irda->usbdev != NULL) &&
 		   (irda->present == 0) &&
 		   (irda->netopen == 0)) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), found a zombie instance !!!\n");
+			IRDA_DEBUG(0, "%s(), found a zombie instance !!!\n", __FUNCTION__);
 			irda_usb_disconnect(irda->usbdev, (void *) irda);
 		}
 	}
@@ -1491,10 +1493,10 @@
 			break;
 		case -EPIPE:		/* -EPIPE = -32 */
 			usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
-			IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" );
+			IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__);
 			break;
 		default:
-			IRDA_DEBUG(0, __FUNCTION__ "(), Unknown error %d\n", ret);
+			IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret);
 			return NULL;
 			break;
 	}
@@ -1503,7 +1505,7 @@
 	interface = &dev->actconfig->interface[ifnum].altsetting[0];
 	if(!irda_usb_parse_endpoints(self, interface->endpoint,
 				     interface->bNumEndpoints)) {
-		ERROR(__FUNCTION__ "(), Bogus endpoints...\n");
+		ERROR("%s(), Bogus endpoints...\n", __FUNCTION__);
 		return NULL;
 	}
 
@@ -1542,7 +1544,7 @@
 	struct irda_usb_cb *self = (struct irda_usb_cb *) ptr;
 	int i;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
 
 	/* Make sure that the Tx path is not executing. - Jean II */
 	spin_lock_irqsave(&self->lock, flags);
@@ -1583,7 +1585,7 @@
 	usb_free_urb(self->tx_urb);
 	usb_free_urb(self->speed_urb);
 
-	IRDA_DEBUG(0, __FUNCTION__ "(), USB IrDA Disconnected\n");
+	IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__);
 }
 
 /*------------------------------------------------------------------*/
@@ -1632,7 +1634,7 @@
 		irda = &irda_instance[i];
 		/* If the Device is zombie */
 		if((irda->usbdev != NULL) && (irda->present == 0)) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), disconnect zombie now !\n");
+			IRDA_DEBUG(0, "%s(), disconnect zombie now !\n", __FUNCTION__);
 			irda_usb_disconnect(irda->usbdev, (void *) irda);
 		}
 	}
diff -Nru a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
--- a/drivers/net/irda/irtty.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/irda/irtty.c	Sat Sep 21 21:25:45 2002
@@ -356,7 +356,7 @@
 
 	cflag &= ~CBAUD;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to %d\n", speed);
+	IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed);
 
 	switch (speed) {
 	case 1200:
@@ -406,7 +406,7 @@
 	__u32 speed = (__u32) task->param;
 	int ret = 0;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
+	IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies); 
 
 	self = (struct irtty_cb *) task->instance;
 	ASSERT(self != NULL, return -1;);
@@ -416,7 +416,7 @@
 
 	/* Check if busy */
 	if (self->task && self->task != task) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
 		spin_unlock_irqrestore(&self->lock, flags);
 		return MSECS_TO_JIFFIES(10);
 	} else
@@ -571,7 +571,7 @@
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
 	if (!self || !self->netdev) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
+		IRDA_DEBUG(0, "%s(), not ready yet!\n", __FUNCTION__);
 		return;
 	}
 
@@ -621,7 +621,7 @@
 {
 	struct irtty_cb *self;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	self = (struct irtty_cb *) task->instance;
 
@@ -707,7 +707,7 @@
 */
 static int irtty_receive_room(struct tty_struct *tty) 
 {
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 	return 65536;  /* We can handle an infinite amount of data. :-) */
 }
 
@@ -749,7 +749,7 @@
 		 *  Now serial buffer is almost free & we can start 
 		 *  transmission of another packet 
 		 */
-		IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
+		IRDA_DEBUG(5, "%s(), finished with frame!\n", __FUNCTION__);
 		
 		self->stats.tx_packets++;		      
 
@@ -759,7 +759,7 @@
 		spin_unlock_irqrestore(&self->lock, flags);
 
 		if (self->new_speed) {
-			IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
+			IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
 			irda_task_execute(self, irtty_change_speed, 
 					  irtty_change_speed_complete, 
 					  NULL, (void *) self->new_speed);
@@ -824,7 +824,7 @@
 	
 	/* This is probably unsafe, but currently under discussion - Jean II */
 	if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
+		IRDA_DEBUG(2, "%s(), error doing ioctl!\n", __FUNCTION__);
 	}
 	set_fs(fs);
 
@@ -850,7 +850,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
+	IRDA_DEBUG(2, "%s(), mode=%s\n", __FUNCTION__, infrared_mode[mode]);
 
 	/* Protect access to self->rx_buff - Jean II */
 	spin_lock_irqsave(&self->lock, flags);
@@ -948,7 +948,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 	
 	/* Ready to play! */
 	netif_start_queue(dev);
@@ -1015,7 +1015,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
 
-	IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
 	
 	/* Locking :
 	 * irda_device_dongle_init() can't be locked.
diff -Nru a/drivers/net/irda/ma600.c b/drivers/net/irda/ma600.c
--- a/drivers/net/irda/ma600.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/irda/ma600.c	Sat Sep 21 21:25:45 2002
@@ -48,7 +48,7 @@
 	#undef IRDA_DEBUG
 	#define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
 
-	#undef ASSERT(expr, func)
+	#undef ASSERT
 	#define ASSERT(expr, func) \
 	if(!(expr)) { \
 	        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
@@ -86,13 +86,13 @@
 
 int __init ma600_init(void)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 	return irda_device_register_dongle(&dongle);
 }
 
 void __exit ma600_cleanup(void)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 	irda_device_unregister_dongle(&dongle);
 }
 
@@ -105,7 +105,7 @@
 */
 static void ma600_open(dongle_t *self, struct qos_info *qos)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
 				|IR_57600|IR_115200;
@@ -123,7 +123,7 @@
 
 static void ma600_close(dongle_t *self)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	/* Power off dongle */
 	self->set_dtr_rts(self->dev, FALSE, FALSE);
@@ -184,12 +184,12 @@
 	__u8 byte_echo;
 	int ret = 0;
 	
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	ASSERT(task != NULL, return -1;);
 
 	if (self->speed_task && self->speed_task != task) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
 		return MSECS_TO_JIFFIES(10);
 	} else {
 		self->speed_task = task;
@@ -215,7 +215,7 @@
 		break;
 
 	case IRDA_TASK_CHILD_WAIT:
-		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+		WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
 		ret = -1;
 		break;
 
@@ -246,7 +246,7 @@
 
 		if(byte != byte_echo) {
 			/* if control byte != echo, I don't know what to do */
-			printk(KERN_WARNING __FUNCTION__ "() control byte written != read!\n");
+			printk(KERN_WARNING "%s() control byte written != read!\n", __FUNCTION__);
 			printk(KERN_WARNING "control byte = 0x%c%c\n", 
 			       hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
 			printk(KERN_WARNING "byte echo = 0x%c%c\n", 
@@ -254,7 +254,7 @@
 			       hexTbl[byte_echo & 0x0f]);
 		#ifndef NDEBUG
 		} else {
-			IRDA_DEBUG(2, __FUNCTION__ "() control byte write read OK\n");
+			IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__);
 		#endif
 		}
 
@@ -273,7 +273,7 @@
 		break;
 
 	default:
-		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
 		self->speed_task = NULL;
 		ret = -1;
@@ -298,12 +298,12 @@
 	dongle_t *self = (dongle_t *) task->instance;
 	int ret = 0;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	ASSERT(task != NULL, return -1;);
 
 	if (self->reset_task && self->reset_task != task) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
 		return MSECS_TO_JIFFIES(10);
 	} else
 		self->reset_task = task;
@@ -326,7 +326,7 @@
 		self->reset_task = NULL;
 		break;
 	default:
-		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);		
 		self->reset_task = NULL;
 		ret = -1;
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	Sat Sep 21 21:25:43 2002
+++ b/drivers/net/irda/nsc-ircc.c	Sat Sep 21 21:25:43 2002
@@ -130,7 +130,7 @@
 static int  nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
 static int  nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
 static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase);
-static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
+static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
 static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int  nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
 static int  nsc_ircc_read_dongle_id (int iobase);
@@ -921,8 +921,8 @@
 		break;
 	case 0x0A: /* same as */
 	case 0x0B: /* Reserved */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
-			   dongle_types[dongle_id]); 
+		IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
+			   __FUNCTION__, dongle_types[dongle_id]); 
 		break;
 	case 0x0C: /* same as */
 	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
@@ -930,14 +930,14 @@
 	case 0x0E: /* Supports SIR Mode only */
 		break;
 	case 0x0F: /* No dongle connected */
-		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
-			   dongle_types[dongle_id]);
+		IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n",
+			   __FUNCTION__, dongle_types[dongle_id]);
 
 		switch_bank(iobase, BANK0); 
 		outb(0x62, iobase+MCR);
 		break;
 	default: 
-		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
+		IRDA_DEBUG(0, "%s(), invalid data_rate\n", __FUNCTION__);
 	}
 	/* Restore bank register */
 	outb(bank, iobase+BSR);
@@ -948,17 +948,19 @@
  *
  *    Change the speed of the device
  *
+ * This function *must* be called with irq off and spin-lock.
  */
-static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
+static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
 {
 	struct net_device *dev = self->netdev;
 	__u8 mcr = MCR_SIR;
 	int iobase; 
 	__u8 bank;
+	__u8 ier;                  /* Interrupt enable register */
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
+	IRDA_DEBUG(2, "%s(), speed=%d\n", __FUNCTION__, speed);
 
-	ASSERT(self != NULL, return;);
+	ASSERT(self != NULL, return 0;);
 
 	iobase = self->io.fir_base;
 
@@ -989,20 +991,20 @@
 		outb(inb(iobase+4) | 0x04, iobase+4);
 	       
 		mcr = MCR_MIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, "%s(), handling baud of 576000\n", __FUNCTION__);
 		break;
 	case 1152000:
 		mcr = MCR_MIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, "%s(), handling baud of 1152000\n", __FUNCTION__);
 		break;
 	case 4000000:
 		mcr = MCR_FIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		IRDA_DEBUG(0, "%s(), handling baud of 4000000\n", __FUNCTION__);
 		break;
 	default:
 		mcr = MCR_FIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
-			   speed);
+		IRDA_DEBUG(0, "%s(), unknown baud rate of %d\n", 
+			   __FUNCTION__, speed);
 		break;
 	}
 
@@ -1033,18 +1035,21 @@
 	if (speed > 115200) {
 		/* Install FIR xmit handler */
 		dev->hard_start_xmit = nsc_ircc_hard_xmit_fir;
-		outb(IER_SFIF_IE, iobase+IER);
+		ier = IER_SFIF_IE;
 		nsc_ircc_dma_receive(self);
 	} else {
 		/* Install SIR xmit handler */
 		dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
-		outb(IER_RXHDL_IE, iobase+IER);
+		ier = IER_RXHDL_IE;
 	}
+	/* Set our current interrupt mask */
+	outb(ier, iobase+IER);
     	
 	/* Restore BSR */
 	outb(bank, iobase+BSR);
-	netif_wake_queue(dev);
-	
+
+	/* Make sure interrupt handlers keep the proper interrupt mask */
+	return(ier);
 }
 
 /*
@@ -1069,20 +1074,36 @@
 
 	netif_stop_queue(dev);
 		
+	/* Make sure tests *& speed change are atomic */
+	spin_lock_irqsave(&self->lock, flags);
+	
 	/* Check if we need to change the speed */
 	speed = irda_get_next_speed(skb);
 	if ((speed != self->io.speed) && (speed != -1)) {
-		/* Check for empty frame */
+		/* Check for empty frame. */
 		if (!skb->len) {
-			nsc_ircc_change_speed(self, speed); 
+			/* If we just sent a frame, we get called before
+			 * the last bytes get out (because of the SIR FIFO).
+			 * If this is the case, let interrupt handler change
+			 * the speed itself... Jean II */
+			if (self->io.direction == IO_RECV) {
+				nsc_ircc_change_speed(self, speed); 
+				/* TODO : For SIR->SIR, the next packet
+				 * may get corrupted - Jean II */
+				netif_wake_queue(dev);
+			} else {
+				self->new_speed = speed;
+				/* Queue will be restarted after speed change
+				 * to make sure packets gets through the
+				 * proper xmit handler - Jean II */
+			}
+			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
 	}
 
-	spin_lock_irqsave(&self->lock, flags);
-	
 	/* Save current bank */
 	bank = inb(iobase+BSR);
 	
@@ -1121,20 +1142,38 @@
 
 	netif_stop_queue(dev);
 	
+	/* Make sure tests *& speed change are atomic */
+	spin_lock_irqsave(&self->lock, flags);
+
 	/* Check if we need to change the speed */
 	speed = irda_get_next_speed(skb);
 	if ((speed != self->io.speed) && (speed != -1)) {
-		/* Check for empty frame */
+		/* Check for empty frame. */
 		if (!skb->len) {
-			nsc_ircc_change_speed(self, speed); 
+			/* If we are currently transmitting, defer to
+			 * interrupt handler. - Jean II */
+			if(self->tx_fifo.len == 0) {
+				nsc_ircc_change_speed(self, speed); 
+				netif_wake_queue(dev);
+			} else {
+				self->new_speed = speed;
+				/* Keep queue stopped :
+				 * the speed change operation may change the
+				 * xmit handler, and we want to make sure
+				 * the next packet get through the proper
+				 * Tx path, so block the Tx queue until
+				 * the speed change has been done.
+				 * Jean II */
+			}
+			spin_unlock_irqrestore(&self->lock, flags);
 			dev_kfree_skb(skb);
 			return 0;
-		} else
+		} else {
+			/* Change speed after current frame */
 			self->new_speed = speed;
+		}
 	}
 
-	spin_lock_irqsave(&self->lock, flags);
-
 	/* Save current bank */
 	bank = inb(iobase+BSR);
 
@@ -1204,8 +1243,9 @@
 		nsc_ircc_dma_xmit(self, iobase);
 	}
  out:
-	/* Not busy transmitting anymore if window is not full */
-	if (self->tx_fifo.free < MAX_TX_WINDOW)
+	/* Not busy transmitting anymore if window is not full,
+	 * and if we don't need to change speed */
+	if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0))
 		netif_wake_queue(self->netdev);
 
 	/* Restore bank register */
@@ -1265,15 +1305,15 @@
 	int actual = 0;
 	__u8 bank;
 	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	/* Save current bank */
 	bank = inb(iobase+BSR);
 
 	switch_bank(iobase, BANK0);
 	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
-		IRDA_DEBUG(4, __FUNCTION__ 
-			   "(), warning, FIFO not empty yet!\n");
+		IRDA_DEBUG(4, "%s(), warning, FIFO not empty yet!\n",
+			   __FUNCTION__);
 
 		/* FIFO may still be filled to the Tx interrupt threshold */
 		fifo_size -= 17;
@@ -1285,8 +1325,8 @@
 		outb(buf[actual++], iobase+TXD);
 	}
         
-	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-		   fifo_size, actual, len);
+	IRDA_DEBUG(4, "%s(), fifo_size %d ; %d sent of %d\n", 
+		   __FUNCTION__, fifo_size, actual, len);
 	
 	/* Restore bank */
 	outb(bank, iobase+BSR);
@@ -1307,7 +1347,7 @@
 	__u8 bank;
 	int ret = TRUE;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	iobase = self->io.fir_base;
 
@@ -1329,12 +1369,6 @@
 		self->stats.tx_packets++;
 	}
 
-	/* Check if we need to change the speed */
-	if (self->new_speed) {
-		nsc_ircc_change_speed(self, self->new_speed);
-		self->new_speed = 0;
-	}
-
 	/* Finished with this frame, so prepare for next */
 	self->tx_fifo.ptr++;
 	self->tx_fifo.len--;
@@ -1351,8 +1385,9 @@
 		self->tx_fifo.tail = self->tx_buff.head;
 	}
 
-	/* Make sure we have room for more frames */
-	if (self->tx_fifo.free < MAX_TX_WINDOW) {
+	/* Make sure we have room for more frames and
+	 * that we don't need to change speed */
+	if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) {
 		/* Not busy transmitting anymore */
 		/* Tell the network layer, that we can accept more frames */
 		netif_wake_queue(self->netdev);
@@ -1443,7 +1478,7 @@
 		len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8);
 
 		if (st_fifo->tail >= MAX_RX_WINDOW) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), window is full!\n");
+			IRDA_DEBUG(0, "%s(), window is full!\n", __FUNCTION__);
 			continue;
 		}
 			
@@ -1629,24 +1664,25 @@
 	}
 	/* Check if transmission has completed */
 	if (eir & EIR_TXEMP_EV) {
-		/* Check if we need to change the speed? */
+		/* Turn around and get ready to receive some data */
+		self->io.direction = IO_RECV;
+		self->ier = IER_RXHDL_IE;
+		/* Check if we need to change the speed?
+		 * Need to be after self->io.direction to avoid race with
+		 * nsc_ircc_hard_xmit_sir() - Jean II */
 		if (self->new_speed) {
-			IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
-			nsc_ircc_change_speed(self, self->new_speed);
+			IRDA_DEBUG(2, "%s(), Changing speed!\n", __FUNCTION__);
+			self->ier = nsc_ircc_change_speed(self,
+							  self->new_speed);
 			self->new_speed = 0;
+			netif_wake_queue(self->netdev);
 
 			/* Check if we are going to FIR */
 			if (self->io.speed > 115200) {
-				/* Should wait for status FIFO interrupt */
-				self->ier = IER_SFIF_IE;
-
 				/* No need to do anymore SIR stuff */
 				return;
 			}
 		}
-		/* Turn around and get ready to receive some data */
-		self->io.direction = IO_RECV;
-		self->ier = IER_RXHDL_IE;
 	}
 
 	/* Rx FIFO threshold or timeout */
@@ -1705,19 +1741,37 @@
 		}
 	} else if (eir & EIR_DMA_EV) {
 		/* Finished with all transmissions? */
-		if (nsc_ircc_dma_xmit_complete(self)) {		
-			/* Check if there are more frames to be transmitted */
-			if (irda_device_txqueue_empty(self->netdev)) {
-				/* Prepare for receive */
-				nsc_ircc_dma_receive(self);
-			
-				self->ier = IER_SFIF_IE;
+		if (nsc_ircc_dma_xmit_complete(self)) {
+			if(self->new_speed != 0) {
+				/* As we stop the Tx queue, the speed change
+				 * need to be done when the Tx fifo is
+				 * empty. Ask for a Tx done interrupt */
+				self->ier = IER_TXEMP_IE;
+			} else {
+				/* Check if there are more frames to be
+				 * transmitted */
+				if (irda_device_txqueue_empty(self->netdev)) {
+					/* Prepare for receive */
+					nsc_ircc_dma_receive(self);
+					self->ier = IER_SFIF_IE;
+				} else
+					WARNING("%s(), potential "
+						"Tx queue lockup !\n",
+						__FUNCTION__);
 			}
 		} else {
 			/*  Not finished yet, so interrupt on DMA again */
 			self->ier = IER_DMA_IE;
 		}
+	} else if (eir & EIR_TXEMP_EV) {
+		/* The Tx FIFO has totally drained out, so now we can change
+		 * the speed... - Jean II */
+		self->ier = nsc_ircc_change_speed(self, self->new_speed);
+		self->new_speed = 0;
+		netif_wake_queue(self->netdev);
+		/* Note : nsc_ircc_change_speed() restarted Rx fifo */
 	}
+
 	outb(bank, iobase+BSR);
 }
 
@@ -1810,7 +1864,7 @@
  */
 static int nsc_ircc_net_init(struct net_device *dev)
 {
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	/* Setup to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -1833,7 +1887,7 @@
 	char hwname[32];
 	__u8 bank;
 	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 	
 	ASSERT(dev != NULL, return -1;);
 	self = (struct nsc_ircc_cb *) dev->priv;
@@ -1897,7 +1951,7 @@
 	int iobase;
 	__u8 bank;
 
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 	
 	ASSERT(dev != NULL, return -1;);
 
@@ -1953,7 +2007,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c
--- a/drivers/net/mii.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/mii.c	Sat Sep 21 21:25:45 2002
@@ -170,6 +170,75 @@
 	return r;
 }
 
+void mii_check_link (struct mii_if_info *mii)
+{
+	if (mii_link_ok(mii))
+		netif_carrier_on(mii->dev);
+	else
+		netif_carrier_off(mii->dev);
+}
+
+unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print)
+{
+	unsigned int old_carrier, new_carrier;
+	int advertise, lpa, media, duplex;
+
+	/* if forced media, go no further */
+	if (mii->duplex_lock)
+		return 0; /* duplex did not change */
+
+	/* check current and old link status */
+	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
+	new_carrier = (unsigned int) mii_link_ok(mii);
+
+	/* if carrier state did not change, this is a "bounce",
+	 * just exit as everything is already set correctly
+	 */
+	if (old_carrier == new_carrier)
+		return 0; /* duplex did not change */
+
+	/* no carrier, nothing much to do */
+	if (!new_carrier) {
+		netif_carrier_off(mii->dev);
+		if (ok_to_print)
+			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+		return 0; /* duplex did not change */
+	}
+
+	/*
+	 * we have carrier, see who's on the other end
+	 */
+	netif_carrier_on(mii->dev);
+
+	/* get MII advertise and LPA values */
+	if (mii->advertising)
+		advertise = mii->advertising;
+	else {
+		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
+		mii->advertising = advertise;
+	}
+	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+
+	/* figure out media and duplex from advertise and LPA values */
+	media = mii_nway_result(lpa & advertise);
+	duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0;
+
+	if (ok_to_print)
+		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
+		       mii->dev->name,
+		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
+		       		"100" : "10",
+		       duplex ? "full" : "half",
+		       lpa);
+
+	if (mii->full_duplex != duplex) {
+		mii->full_duplex = duplex;
+		return 1; /* duplex changed */
+	}
+
+	return 0; /* duplex did not change */
+}
+
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
 MODULE_DESCRIPTION ("MII hardware support library");
 MODULE_LICENSE("GPL");
@@ -178,3 +247,6 @@
 EXPORT_SYMBOL(mii_nway_restart);
 EXPORT_SYMBOL(mii_ethtool_gset);
 EXPORT_SYMBOL(mii_ethtool_sset);
+EXPORT_SYMBOL(mii_check_link);
+EXPORT_SYMBOL(mii_check_media);
+
diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
--- a/drivers/net/wireless/wavelan_cs.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/wireless/wavelan_cs.c	Sat Sep 21 21:25:45 2002
@@ -56,8 +56,7 @@
  *
  */
 
-#include <linux/ethtool.h>
-#include <asm/uaccess.h>
+/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */
 #include "wavelan_cs.p.h"		/* Private header */
 
 /************************* MISC SUBROUTINES **************************/
@@ -2890,8 +2889,8 @@
 	.private	= (iw_handler *) wavelan_private_handler,
 	.private_args	= (struct iw_priv_args *) wavelan_private_args,
 };
+#endif /* WIRELESS_EXT > 12 */
 
-#else /* WIRELESS_EXT > 12 */
 /*------------------------------------------------------------------*/
 /*
  * Perform ioctl : config & info stuff
@@ -2916,8 +2915,9 @@
       ret = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
       break;
 
+#if WIRELESS_EXT <= 12
       /* --------------- WIRELESS EXTENSIONS --------------- */
-
+      /* Now done as iw_handler - Jean II */
     case SIOCGIWNAME:
       wavelan_get_name(dev, NULL, &(wrq->u), NULL);
       break;
@@ -3191,6 +3191,7 @@
       }
       break;
 #endif	/* HISTOGRAM */
+#endif /* WIRELESS_EXT <= 12 */
 
       /* ------------------- OTHER IOCTL ------------------- */
 
@@ -3203,7 +3204,6 @@
 #endif
   return ret;
 }
-#endif /* WIRELESS_EXT > 12 */
 
 /*------------------------------------------------------------------*/
 /*
@@ -5199,9 +5199,8 @@
 #ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
 #if WIRELESS_EXT > 12
   dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
-#else /* WIRELESS_EXT > 12 */
-  dev->do_ioctl = wavelan_ioctl;	/* wireless extensions */
 #endif /* WIRELESS_EXT > 12 */
+  dev->do_ioctl = wavelan_ioctl;	/* old wireless extensions */
   dev->get_wireless_stats = wavelan_get_wireless_stats;
 #endif
 
diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
--- a/drivers/net/wireless/wavelan_cs.p.h	Sat Sep 21 21:25:45 2002
+++ b/drivers/net/wireless/wavelan_cs.p.h	Sat Sep 21 21:25:45 2002
@@ -439,6 +439,7 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
+#include <linux/ethtool.h>
 
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Wireless extensions */
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	Sat Sep 21 21:25:47 2002
+++ b/drivers/pci/pci-driver.c	Sat Sep 21 21:25:47 2002
@@ -44,7 +44,7 @@
 	drv = to_pci_driver(dev->driver);
 	pci_dev = to_pci_dev(dev);
 
-	if (drv->probe) {
+	if (!pci_dev->driver && drv->probe) {
 		const struct pci_device_id *id;
 
 		id = pci_match_device(drv->id_table, pci_dev);
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/s390/block/dasd_genhd.c	Sat Sep 21 21:25:48 2002
@@ -259,10 +259,8 @@
 	struct gendisk *disk = dasd_gendisk_by_dev(device->kdev);
 	if (disk == NULL)
 		return;
-	add_gendisk(disk);
-	register_disk(disk, mk_kdev(disk->major, disk->first_minor),
-			1<<disk->minor_shift, disk->fops,
-			device->blocks << device->s2b_shift);
+	set_capacity(disk, device->blocks << device->s2b_shift);
+	add_disk(disk);
 }
 
 /*
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Sat Sep 21 21:25:48 2002
+++ b/drivers/s390/block/xpram.c	Sat Sep 21 21:25:48 2002
@@ -59,6 +59,8 @@
 
 static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
 static int xpram_sizes[XPRAM_MAX_DEVS];
+static struct gendisk xpram_disks[XPRAM_MAX_DEVS];
+static char xpram_names[XPRAM_MAX_DEV][8];
 static unsigned long xpram_pages;
 static int xpram_devs;
 static devfs_handle_t xpram_devfs_handle;
@@ -459,16 +461,24 @@
 	q = BLK_DEFAULT_QUEUE(XPRAM_MAJOR);
 	blk_queue_make_request(q,xpram_make_request);
 	blk_queue_hardsect_size(q, 4096);
-	blk_size[XPRAM_MAJOR] = xpram_sizes;
 
 	/*
 	 * Setup device structures.
 	 */
 	offset = 0;
 	for (i = 0; i < xpram_devs; i++) {
+		struct gendisk *disk = xpram_disks + i;
 		xpram_devices[i].size = xpram_sizes[i] / 4;
 		xpram_devices[i].offset = offset;
 		offset += xpram_devices[i].size;
+		disk->major = XPRAM_MAJOR;
+		disk->first_minor = i;
+		disk->minor_shift = 0;
+		disk->fops = &xpram_devops;
+		sprintf(xpram_names[i], "slram%d", i);
+		disk->major_name = xpram_names[i];
+		set_capacity(disk, xpram_sizes[i] << 1);
+		add_disk(disk);
 	}
 
 	return 0;
@@ -479,6 +489,9 @@
  */
 static void __exit xpram_exit(void)
 {
+	int i;
+	for (i = 0; i < xpram_devs; i++)
+		del_gendisk(xpram_disks + i);
 	blk_clear(XPRAM_MAJOR);
 	unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 	devfs_unregister(xpram_devfs_handle);
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/sbus/char/jsflash.c	Sat Sep 21 21:25:45 2002
@@ -36,21 +36,14 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
+#include <linux/genhd.h>
 
 /*
  * <linux/blk.h> is controlled from the outside with these definitions.
  */
 #define MAJOR_NR	JSFD_MAJOR
 
-#define DEVICE_REQUEST jsfd_do_request
-#define DEVICE_NR(device) (MINOR(device))
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-#define DEVICE_NO_RANDOM
-
 #include <linux/blk.h>
-
-
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -134,8 +127,8 @@
 
 /*
  */
-static int jsfd_sizes[JSF_MAX];
-static u64 jsfd_bytesizes[JSF_MAX];
+static struct gendisk jsfd_disk[JSF_MAX];
+static char names[JSF_MAX][6];
 
 /*
  * Let's pretend we may have several of these...
@@ -447,28 +440,6 @@
 	return error;
 }
 
-static int jsfd_ioctl(struct inode *inode, struct file *file,
-    unsigned int cmd, unsigned long arg)
-{
-	int dev;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (!inode)
-		return -EINVAL;
-	if ((dev = MINOR(inode->i_rdev)) >= JSF_MAX) return -ENODEV;
-
-	switch (cmd) {
-	case BLKGETSIZE:
-		return put_user(jsfd_bytesizes[dev] >> 9, (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user(jsfd_bytesizes[dev], (u64 *) arg);
-
-	default: ;
-	}
-	return -ENOTTY;
-}
-
 static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	return -ENXIO;
@@ -549,10 +520,9 @@
 	.owner =	THIS_MODULE,
 	.open =		jsfd_open,
 	.release =	jsfd_release,
-	.ioctl =	jsfd_ioctl,
 };
 
-int jsflash_init(void)
+static int jsflash_init(void)
 {
 	int rc;
 	struct jsflash *jsf;
@@ -640,14 +610,15 @@
 	return 0;
 }
 
-int jsfd_init(void) {
+static int jsfd_init(void)
+{
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	struct jsflash *jsf;
 	struct jsfd_part *jdp;
 	int i;
 
-	if (jsf0.base == 0) {
+	if (jsf0.base == 0)
 		return -ENXIO;
-	}
 
 	if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) {
 		printk("jsfd_init: unable to get major number %d\n",
@@ -655,20 +626,23 @@
 		return -EIO;
 	}
 
-	blk_size[JSFD_MAJOR] = jsfd_sizes;
-
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), jsfd_do_request, &lock);
 	for (i = 0; i < JSF_MAX; i++) {
+		struct gendisk *disk = jsfd_disk + i;
 		if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
 		jsf = &jsf0;	/* actually, &jsfv[i >> JSF_PART_BITS] */
 		jdp = &jsf->dv[i&JSF_PART_MASK];
 
 		jdp->refcnt = 0;
 
-		jsfd_bytesizes[i] = jdp->dsize;
-		jsfd_sizes[i] = jsfd_bytesizes[i] >> 10;
-		register_disk(NULL, MKDEV(JSFD_MAJOR, i), 1, &jsfd_fops,
-				jsfd_bytesizes[i] >> 9);
+		disk->major = JSFD_MAJOR;
+		disk->first_minor = i;
+		sprintf(names[i], "jsfd%d", i);
+		disk->major_name = names[i];
+		disk->fops = &jsfd_fops;
+		disk->minor_shift = 0;
+		set_capacity(disk, jdp->dsize >> 9);
+		add_disk(disk);
 		set_device_ro(MKDEV(JSFD_MAJOR, i), 1);
 	}
 	return 0;
@@ -686,9 +660,14 @@
 	return rc;
 }
 
-static void __exit jsflash_cleanup_module(void) {
+static void __exit jsflash_cleanup_module(void)
+{
+	int i;
 
-	/* for (all probed units) {  } */
+	for (i = 0; i < JSF_MAX; i++) {
+		if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
+		del_gendisk(jsfd_disk + i);
+	}
 	if (jsf0.busy)
 		printk("jsf0: cleaning busy unit\n");
 	jsf0.base = 0;
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/scsi/sd.c	Sat Sep 21 21:25:45 2002
@@ -1250,10 +1250,8 @@
 		if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
 			sd_init_onedisk(sdkp, k);
 			if (!sdkp->has_been_registered) {
-				add_gendisk(sd_disks[k]);
-				register_disk(sd_disks[k], MKDEV_SD(k),
-						1<<4, &sd_fops,
-						sdkp->capacity);
+				set_capacity(sd_disks[k], sdkp->capacity);
+				add_disk(sd_disks[k]);
 				sdkp->has_been_registered = 1;
 			}
 		}
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Sat Sep 21 21:25:45 2002
+++ b/drivers/scsi/sr.c	Sat Sep 21 21:25:45 2002
@@ -762,6 +762,7 @@
 		disk->minor_shift = 0;
 		disk->major_name = cd->cdi.name;
 		disk->fops = &sr_bdops;
+		disk->flags = GENHD_FL_CD;
 		cd->disk = disk;
 		cd->capacity = 0x1fffff;
 		cd->device->sector_size = 2048;/* A guess, just in case */
@@ -805,14 +806,10 @@
 				   &dev_attr_type);
 		device_create_file(&cd->cdi.cdrom_driverfs_dev,
 				   &dev_attr_kdev);
-                cd->cdi.de = devfs_register(cd->device->de, "cd",
-                                    DEVFS_FL_DEFAULT, MAJOR_NR, i,
-                                    S_IFBLK | S_IRUGO | S_IWUGO,
-                                    &sr_bdops, NULL);
+		disk->de = cd->device->de;
 		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);
+		set_capacity(disk, cd->capacity);
+		add_disk(disk);
 	}
 }
 
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	Sat Sep 21 21:25:46 2002
+++ b/drivers/scsi/sr_ioctl.c	Sat Sep 21 21:25:46 2002
@@ -545,16 +545,7 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	Scsi_CD *cd = cdi->handle;
-
-	switch (cmd) {
-	case BLKGETSIZE:
-		return put_user(cd->capacity, (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user((u64)cd->capacity << 9, (u64 *)arg);
-
-	default:
-		return scsi_ioctl(cd->device, cmd, (void *)arg);
-	}
+	return scsi_ioctl(cd->device, cmd, (void *)arg);
 }
 
 /*
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Sat Sep 21 21:25:48 2002
+++ b/fs/block_dev.c	Sat Sep 21 21:25:48 2002
@@ -843,6 +843,9 @@
 	case BLKPG:
 		ret = blk_ioctl(bdev, cmd, arg);
 		break;
+	case BLKRRPART:
+		ret = blkdev_reread_part(bdev);
+		break;
 	default:
 		if (bdev->bd_op->ioctl)
 			ret =bdev->bd_op->ioctl(inode, file, cmd, arg);
@@ -854,8 +857,6 @@
 				case BLKROSET:
 					ret = blk_ioctl(bdev,cmd,arg);
 					break;
-				case BLKRRPART:
-					ret = blkdev_reread_part(bdev);
 			}
 		}
 	}
diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c
--- a/fs/jfs/file.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/file.c	Sat Sep 21 21:25:45 2002
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include "jfs_incore.h"
+#include "jfs_dmap.h"
 #include "jfs_txnmgr.h"
 #include "jfs_xattr.h"
 #include "jfs_debug.h"
@@ -94,6 +95,47 @@
 	IWRITE_UNLOCK(ip);
 }
 
+static int jfs_open(struct inode *inode, struct file *file)
+{
+	int rc;
+
+	if ((rc = generic_file_open(inode, file)))
+		return rc;
+
+	/*
+	 * We attempt to allow only one "active" file open per aggregate
+	 * group.  Otherwise, appending to files in parallel can cause
+	 * fragmentation within the files.
+	 *
+	 * If the file is empty, it was probably just created and going
+	 * to be written to.  If it has a size, we'll hold off until the
+	 * file is actually grown.
+	 */
+	if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE &&
+	    (inode->i_size == 0)) {
+		struct jfs_inode_info *ji = JFS_IP(inode);
+		if (ji->active_ag == -1) {
+			ji->active_ag = ji->agno;
+			atomic_inc(
+			    &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]);
+		}
+	}
+
+	return 0;
+}
+static int jfs_release(struct inode *inode, struct file *file)
+{
+	struct jfs_inode_info *ji = JFS_IP(inode);
+
+	if (ji->active_ag != -1) {
+		struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
+		atomic_dec(&bmap->db_active[ji->active_ag]);
+		ji->active_ag = -1;
+	}
+
+	return 0;
+}
+
 struct inode_operations jfs_file_inode_operations = {
 	.truncate	= jfs_truncate,
 	.setxattr	= jfs_setxattr,
@@ -103,7 +145,7 @@
 };
 
 struct file_operations jfs_file_operations = {
-	.open		= generic_file_open,
+	.open		= jfs_open,
 	.llseek		= generic_file_llseek,
 	.write		= generic_file_write,
 	.read		= generic_file_read,
@@ -112,4 +154,5 @@
 	.writev		= generic_file_writev,
  	.sendfile	= generic_file_sendfile,
 	.fsync		= jfs_fsync,
+	.release	= jfs_release,
 };
diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
--- a/fs/jfs/jfs_dmap.c	Sat Sep 21 21:25:48 2002
+++ b/fs/jfs/jfs_dmap.c	Sat Sep 21 21:25:48 2002
@@ -241,6 +241,7 @@
 	bmp->db_ipbmap = ipbmap;
 	JFS_SBI(ipbmap->i_sb)->bmap = bmp;
 
+	memset(bmp->db_active, 0, sizeof(bmp->db_active));
 	DBINITMAP(bmp->db_mapsize, ipbmap, &bmp->db_DBmap);
 
 	/*
@@ -271,6 +272,7 @@
 int dbUnmount(struct inode *ipbmap, int mounterror)
 {
 	struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
+	int i;
 
 	if (!(mounterror || isReadOnly(ipbmap)))
 		dbSync(ipbmap);
@@ -280,6 +282,14 @@
 	 */
 	truncate_inode_pages(ipbmap->i_mapping, 0);
 
+	/*
+	 * Sanity Check
+	 */
+	for (i = 0; i < bmp->db_numag; i++)
+		if (atomic_read(&bmp->db_active[i]))
+			printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n",
+			       i, atomic_read(&bmp->db_active[i]));
+
 	/* free the memory for the in-memory bmap. */
 	kfree(bmp);
 
@@ -598,102 +608,77 @@
  *
  * FUNCTION:    find the preferred allocation group for new allocations.
  *
- *		we try to keep the trailing (rightmost) allocation groups
- *		free for large allocations.  we try to do this by targeting
- *		new inode allocations towards the leftmost or 'active'
- *		allocation groups while keeping the rightmost or 'inactive'
- *		allocation groups free. once the active allocation groups
- *		have dropped to a certain percentage of free space, we add
- *		the leftmost inactive allocation group to the active set.
- *
- *		within the active allocation groups, we maintain a preferred
+ *		Within the allocation groups, we maintain a preferred
  *		allocation group which consists of a group with at least
- *		average free space over the active set. it is the preferred
- *		group that we target new inode allocation towards.  the 
- *		tie-in between inode allocation and block allocation occurs
- *		as we allocate the first (data) block of an inode and specify
- *		the inode (block) as the allocation hint for this block.
+ *		average free space.  It is the preferred group that we target
+ *		new inode allocation towards.  The tie-in between inode
+ *		allocation and block allocation occurs as we allocate the
+ *		first (data) block of an inode and specify the inode (block)
+ *		as the allocation hint for this block.
+ *
+ *		We try to avoid having more than one open file growing in
+ *		an allocation group, as this will lead to fragmentation.
+ *		This differs from the old OS/2 method of trying to keep
+ *		empty ags around for large allocations.
  *
  * PARAMETERS:
  *      ipbmap	-  pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
  *      the preferred allocation group number.
- *
- * note: only called by dbAlloc();
  */
 int dbNextAG(struct inode *ipbmap)
 {
-	s64 avgfree, inactfree, actfree, rem;
-	int actags, inactags, l2agsize;
+	s64 avgfree;
+	int agpref;
+	s64 hwm = 0;
+	int i;
+	int next_best = -1;
 	struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
 
 	BMAP_LOCK(bmp);
 
-	/* determine the number of active allocation groups (i.e.
-	 * the number of allocation groups up to and including
-	 * the rightmost allocation group with blocks allocated
-	 * in it.
-	 */
-	actags = bmp->db_maxag + 1;
-	assert(actags <= bmp->db_numag);
-
-	/* get the number of inactive allocation groups (i.e. the
-	 * number of allocation group following the rightmost group
-	 * with allocation in it.
-	 */
-	inactags = bmp->db_numag - actags;
-
-	/* determine how many blocks are in the inactive allocation
-	 * groups. in doing this, we must account for the fact that
-	 * the rightmost group might be a partial group (i.e. file
-	 * system size is not a multiple of the group size).
-	 */
-	l2agsize = bmp->db_agl2size;
-	rem = bmp->db_mapsize & (bmp->db_agsize - 1);
-	inactfree = (inactags
-		     && rem) ? ((inactags - 1) << l2agsize) +
-	    rem : inactags << l2agsize;
-
-	/* now determine how many free blocks are in the active
-	 * allocation groups plus the average number of free blocks
-	 * within the active ags.
-	 */
-	actfree = bmp->db_nfree - inactfree;
-	avgfree = (u32) actfree / (u32) actags;
-
-	/* check if not all of the allocation groups are active.
-	 */
-	if (actags < bmp->db_numag) {
-		/* not all of the allocation groups are active.  determine
-		 * if we should extend the active set by 1 (i.e. add the
-		 * group following the current active set).  we do so if
-		 * the number of free blocks within the active set is less
-		 * than the allocation group set and average free within
-		 * the active set is less than 60%.  we activate a new group
-		 * by setting the allocation group preference to the new
-		 * group.
-		 */
-		if (actfree < bmp->db_agsize &&
-		    ((avgfree * 100) >> l2agsize) < 60)
-			bmp->db_agpref = actags;
-	} else {
-		/* all allocation groups are in the active set.  check if
-		 * the preferred allocation group has average free space.
-		 * if not, re-establish the preferred group as the leftmost
-		 * group with average free space.
-		 */
-		if (bmp->db_agfree[bmp->db_agpref] < avgfree) {
-			for (bmp->db_agpref = 0; bmp->db_agpref < actags;
-			     bmp->db_agpref++) {
-				if (bmp->db_agfree[bmp->db_agpref] <=
-				    avgfree)
-					break;
-			}
-			assert(bmp->db_agpref < bmp->db_numag);
+	/* determine the average number of free blocks within the ags. */
+	avgfree = (u32)bmp->db_nfree / bmp->db_numag;
+
+	/*
+	 * if the current preferred ag does not have an active allocator
+	 * and has at least average freespace, return it
+	 */
+	agpref = bmp->db_agpref;
+	if ((atomic_read(&bmp->db_active[agpref]) == 0) &&
+	    (bmp->db_agfree[agpref] >= avgfree))
+		goto found;
+
+	/* From the last preferred ag, find the next one with at least
+	 * average free space.
+	 */
+	for (i = 0 ; i < bmp->db_numag; i++, agpref++) {
+		if (agpref == bmp->db_numag)
+			agpref = 0;
+
+		if (atomic_read(&bmp->db_active[agpref]))
+			/* open file is currently growing in this ag */
+			continue;
+		if (bmp->db_agfree[agpref] >= avgfree)
+			goto found;
+		else if (bmp->db_agfree[agpref] > hwm) {
+			hwm = bmp->db_agfree[agpref];
+			next_best = agpref;
 		}
 	}
 
+	/*
+	 * If no inactive ag was found with average freespace, use the
+	 * next best
+	 */
+	if (next_best != -1)
+		agpref = next_best;
+
+	/* else agpref should be back to its original value */
+
+found:
+	bmp->db_agpref = agpref;
 	BMAP_UNLOCK(bmp);
 
 	/* return the preferred group.
@@ -701,7 +686,6 @@
 	return (bmp->db_agpref);
 }
 
-
 /*
  * NAME:	dbAlloc()
  *
@@ -750,6 +734,7 @@
 	struct dmap *dp;
 	int l2nb;
 	s64 mapSize;
+	int writers;
 
 	/* assert that nblocks is valid */
 	assert(nblocks > 0);
@@ -774,11 +759,10 @@
 	/* the hint should be within the map */
 	assert(hint < mapSize);
 
-	/* if no hint was specified or the number of blocks to be
-	 * allocated is greater than the allocation group size, try
-	 * to allocate anywhere.
+	/* if the number of blocks to be allocated is greater than the
+	 * allocation group size, try to allocate anywhere.
 	 */
-	if (hint == 0 || l2nb > bmp->db_agl2size) {
+	if (l2nb > bmp->db_agl2size) {
 		IWRITE_LOCK(ipbmap);
 
 		rc = dbAllocAny(bmp, nblocks, l2nb, results);
@@ -790,39 +774,34 @@
 		goto write_unlock;
 	}
 
+	/*
+	 * If no hint, let dbNextAG recommend an allocation group
+	 */
+	if (hint == 0)
+		goto pref_ag;
+
 	/* we would like to allocate close to the hint.  adjust the
 	 * hint to the block following the hint since the allocators
 	 * will start looking for free space starting at this point.
-	 * if the hint was the last block of the file system, try to
-	 * allocate in the same allocation group as the hint.
 	 */
 	blkno = hint + 1;
-	if (blkno >= bmp->db_mapsize) {
-		blkno--;
-		goto tryag;
-	}
+
+	if (blkno >= bmp->db_mapsize)
+		goto pref_ag;
+
+	agno = blkno >> bmp->db_agl2size;
 
 	/* check if blkno crosses over into a new allocation group.
 	 * if so, check if we should allow allocations within this
-	 * allocation group.  we try to keep the trailing (rightmost)
-	 * allocation groups of the file system free for large
-	 * allocations and may want to prevent this allocation from
-	 * spilling over into this space.
-	 */
-	if ((blkno & (bmp->db_agsize - 1)) == 0) {
-		/* check if the AG is beyond the rightmost AG with
-		 * allocations in it.  if so, call dbNextAG() to
-		 * determine if the allocation should be allowed
-		 * to proceed within this AG or should be targeted
-		 * to another AG.
-		 */
-		agno = blkno >> bmp->db_agl2size;
-		if (agno > bmp->db_maxag) {
-			agno = dbNextAG(ipbmap);
-			blkno = (s64) agno << bmp->db_agl2size;
-			goto tryag;
-		}
-	}
+	 * allocation group.
+	 */
+	if ((blkno & (bmp->db_agsize - 1)) == 0)
+		/* check if the AG is currenly being written to.
+		 * if so, call dbNextAG() to find a non-busy
+		 * AG with sufficient free space.
+		 */
+		if (atomic_read(&bmp->db_active[agno]))
+			goto pref_ag;
 
 	/* check if the allocation request size can be satisfied from a
 	 * single dmap.  if so, try to allocate from the dmap containing
@@ -844,9 +823,8 @@
 		/* first, try to satisfy the allocation request with the
 		 * blocks beginning at the hint.
 		 */
-		if ((rc =
-		     dbAllocNext(bmp, dp, blkno,
-				 (int) nblocks)) != ENOSPC) {
+		if ((rc = dbAllocNext(bmp, dp, blkno, (int) nblocks))
+		    != ENOSPC) {
 			if (rc == 0) {
 				*results = blkno;
 				DBALLOC(bmp->db_DBmap, bmp->db_mapsize,
@@ -858,12 +836,23 @@
 			goto read_unlock;
 		}
 
+		writers = atomic_read(&bmp->db_active[agno]);
+		if ((writers > 1) ||
+		    ((writers == 1) && (JFS_IP(ip)->active_ag != agno))) {
+			/*
+			 * Someone else is writing in this allocation
+			 * group.  To avoid fragmenting, try another ag
+			 */
+			release_metapage(mp);
+			IREAD_UNLOCK(ipbmap);
+			goto pref_ag;
+		}
+
 		/* next, try to satisfy the allocation request with blocks
 		 * near the hint.
 		 */
 		if ((rc =
-		     dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb,
-				 results))
+		     dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, results))
 		    != ENOSPC) {
 			if (rc == 0) {
 				DBALLOC(bmp->db_DBmap, bmp->db_mapsize,
@@ -876,10 +865,9 @@
 		}
 
 		/* try to satisfy the allocation request with blocks within
-		 * the same allocation group as the hint.
+		 * the same dmap as the hint.
 		 */
-		if ((rc =
-		     dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results))
+		if ((rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results))
 		    != ENOSPC) {
 			if (rc == 0) {
 				DBALLOC(bmp->db_DBmap, bmp->db_mapsize,
@@ -895,14 +883,30 @@
 		IREAD_UNLOCK(ipbmap);
 	}
 
-      tryag:
+	/* try to satisfy the allocation request with blocks within
+	 * the same allocation group as the hint.
+	 */
+	IWRITE_LOCK(ipbmap);
+	if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results))
+	    != ENOSPC) {
+		if (rc == 0)
+			DBALLOC(bmp->db_DBmap, bmp->db_mapsize,
+				*results, nblocks);
+		goto write_unlock;
+	}
+	IWRITE_UNLOCK(ipbmap);
+
+
+      pref_ag:
+	/*
+	 * Let dbNextAG recommend a preferred allocation group
+	 */
+	agno = dbNextAG(ipbmap);
 	IWRITE_LOCK(ipbmap);
 
-	/* determine the allocation group number of the hint and try to
-	 * allocate within this allocation group.  if that fails, try to
+	/* Try to allocate within this allocation group.  if that fails, try to
 	 * allocate anywhere in the map.
 	 */
-	agno = blkno >> bmp->db_agl2size;
 	if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) == ENOSPC)
 		rc = dbAllocAny(bmp, nblocks, l2nb, results);
 	if (rc == 0) {
@@ -2314,11 +2318,9 @@
 	 * if so, establish the new maximum allocation group number by
 	 * searching left for the first allocation group with allocation.
 	 */
-	if ((bmp->db_agfree[agno] == bmp->db_agsize
-	     && agno == bmp->db_maxag) || (agno == bmp->db_numag - 1
-					   && bmp->db_agfree[agno] ==
-					   (bmp-> db_mapsize &
-					    (BPERDMAP - 1)))) {
+	if ((bmp->db_agfree[agno] == bmp->db_agsize && agno == bmp->db_maxag) ||
+	    (agno == bmp->db_numag - 1 &&
+	     bmp->db_agfree[agno] == (bmp-> db_mapsize & (BPERDMAP - 1)))) {
 		while (bmp->db_maxag > 0) {
 			bmp->db_maxag -= 1;
 			if (bmp->db_agfree[bmp->db_maxag] !=
diff -Nru a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
--- a/fs/jfs/jfs_dmap.h	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_dmap.h	Sat Sep 21 21:25:45 2002
@@ -227,6 +227,7 @@
 	struct dbmap db_bmap;	/* on-disk aggregate map descriptor */
 	struct inode *db_ipbmap;	/* ptr to aggregate map incore inode */
 	struct semaphore db_bmaplock;	/* aggregate map lock */
+	atomic_t db_active[MAXAG];	/* count of active, open files in AG */
 	u32 *db_DBmap;
 };
 
diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_extent.c	Sat Sep 21 21:25:45 2002
@@ -514,9 +514,12 @@
 static int
 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
 {
+	struct jfs_inode_info *ji = JFS_IP(ip);
+	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
 	s64 nb, nblks, daddr, max;
-	int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
-	struct bmap *mp = JFS_SBI(ip->i_sb)->bmap;
+	int rc, nbperpage = sbi->nbperpage;
+	struct bmap *bmp = sbi->bmap;
+	int ag;
 
 	/* get the number of blocks to initially attempt to allocate.
 	 * we'll first try the number of blocks requested unless this
@@ -524,7 +527,7 @@
 	 * blocks in the map. in that case, we'll start off with the 
 	 * maximum free.
 	 */
-	max = (s64) 1 << mp->db_maxfreebud;
+	max = (s64) 1 << bmp->db_maxfreebud;
 	if (*nblocks >= max && *nblocks > nbperpage)
 		nb = nblks = (max > nbperpage) ? max : nbperpage;
 	else
@@ -548,6 +551,18 @@
 
 	*nblocks = nb;
 	*blkno = daddr;
+
+	if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) {
+		ag = BLKTOAG(daddr, sbi);
+		if (ji->active_ag == -1) {
+			atomic_inc(&bmp->db_active[ag]);
+			ji->active_ag = ag;
+		} else if (ji->active_ag != ag) {
+			atomic_dec(&bmp->db_active[ji->active_ag]);
+			atomic_inc(&bmp->db_active[ag]);
+			ji->active_ag = ag;
+		}
+	}
 
 	return (0);
 }
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_imap.c	Sat Sep 21 21:25:45 2002
@@ -429,6 +429,7 @@
 
 	/* set the ag for the inode */
 	JFS_IP(ip)->agno = BLKTOAG(agstart, sbi);
+	JFS_IP(ip)->active_ag = -1;
 
 	return (rc);
 }
@@ -1358,6 +1359,7 @@
 	DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino);
 	jfs_ip->ixpxd = iagp->inoext[extno];
 	jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
+	jfs_ip->active_ag = -1;
 }
 
 
@@ -1413,15 +1415,27 @@
 	 * moving backward on the disk.)  compute the hint within the
 	 * file system and the iag.
 	 */
+
+	/* get the ag number of this iag */
+	agno = JFS_IP(pip)->agno;
+
+	if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
+		/*
+		 * There is an open file actively growing.  We want to
+		 * allocate new inodes from a different ag to avoid
+		 * fragmentation problems.
+		 */
+		agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);
+		AG_LOCK(imap, agno);
+		goto tryag;
+	}
+
 	inum = pip->i_ino + 1;
 	ino = inum & (INOSPERIAG - 1);
 
 	/* back off the the hint if it is outside of the iag */
 	if (ino == 0)
 		inum = pip->i_ino;
-
-	/* get the ag number of this iag */
-	agno = JFS_IP(pip)->agno;
 
 	/* lock the AG inode map information */
 	AG_LOCK(imap, agno);
diff -Nru a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
--- a/fs/jfs/jfs_incore.h	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_incore.h	Sat Sep 21 21:25:45 2002
@@ -49,7 +49,7 @@
 	long	cflag;		/* commit flags		*/
 	u16	bxflag;		/* xflag of pseudo buffer?	*/
 	unchar	agno;		/* ag number			*/
-	unchar	pad;		/* pad			*/
+	signed char active_ag;	/* ag currently allocating from	*/
 	lid_t	blid;		/* lid of pseudo buffer?	*/
 	lid_t	atlhead;	/* anonymous tlock list head	*/
 	lid_t	atltail;	/* anonymous tlock list tail	*/
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_logmgr.c	Sat Sep 21 21:25:45 2002
@@ -66,6 +66,7 @@
 #include <linux/completion.h>
 #include <linux/buffer_head.h>		/* for sync_blockdev() */
 #include <linux/bio.h>
+#include <linux/suspend.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -2146,12 +2147,17 @@
 			lbmStartIO(bp);
 			spin_lock_irq(&log_redrive_lock);
 		}
-		add_wait_queue(&jfs_IO_thread_wait, &wq);
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irq(&log_redrive_lock);
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&jfs_IO_thread_wait, &wq);
+		if (current->flags & PF_FREEZE) {
+			spin_unlock_irq(&log_redrive_lock);
+			refrigerator(PF_IOTHREAD);
+		} else {
+			add_wait_queue(&jfs_IO_thread_wait, &wq);
+			set_current_state(TASK_INTERRUPTIBLE);
+			spin_unlock_irq(&log_redrive_lock);
+			schedule();
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&jfs_IO_thread_wait, &wq);
+		}
 	} while (!jfs_stop_threads);
 
 	jFYI(1,("jfsIOWait being killed!\n"));
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/jfs_txnmgr.c	Sat Sep 21 21:25:46 2002
@@ -47,6 +47,7 @@
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
+#include <linux/suspend.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -2789,8 +2790,6 @@
 	complete(&jfsIOwait);
 
 	do {
-		DECLARE_WAITQUEUE(wq, current);
-
 		LAZY_LOCK(flags);
 restart:
 		WorkDone = 0;
@@ -2825,12 +2824,19 @@
 		if (WorkDone)
 			goto restart;
 
-		add_wait_queue(&jfs_commit_thread_wait, &wq);
-		set_current_state(TASK_INTERRUPTIBLE);
-		LAZY_UNLOCK(flags);
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&jfs_commit_thread_wait, &wq);
+		if (current->flags & PF_FREEZE) {
+			LAZY_UNLOCK(flags);
+			refrigerator(PF_IOTHREAD);
+		} else {
+			DECLARE_WAITQUEUE(wq, current);
+
+			add_wait_queue(&jfs_commit_thread_wait, &wq);
+			set_current_state(TASK_INTERRUPTIBLE);
+			LAZY_UNLOCK(flags);
+			schedule();
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&jfs_commit_thread_wait, &wq);
+		}
 	} while (!jfs_stop_threads);
 
 	if (TxAnchor.unlock_queue)
@@ -2981,7 +2987,6 @@
 	complete(&jfsIOwait);
 
 	do {
-		DECLARE_WAITQUEUE(wq, current);
 		/*
 		 * write each inode on the anonymous inode list
 		 */
@@ -3030,12 +3035,20 @@
 		}
 		/* Add anon_list2 back to anon_list */
 		list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
-		add_wait_queue(&jfs_sync_thread_wait, &wq);
-		set_current_state(TASK_INTERRUPTIBLE);
-		TXN_UNLOCK();
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&jfs_sync_thread_wait, &wq);
+
+		if (current->flags & PF_FREEZE) {
+			TXN_UNLOCK();
+			refrigerator(PF_IOTHREAD);
+		} else {
+			DECLARE_WAITQUEUE(wq, current);
+
+			add_wait_queue(&jfs_sync_thread_wait, &wq);
+			set_current_state(TASK_INTERRUPTIBLE);
+			TXN_UNLOCK();
+			schedule();
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&jfs_sync_thread_wait, &wq);
+		}
 	} while (!jfs_stop_threads);
 
 	jFYI(1, ("jfs_sync being killed\n"));
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/super.c	Sat Sep 21 21:25:45 2002
@@ -406,6 +406,7 @@
 		init_rwsem(&jfs_ip->rdwrlock);
 		init_MUTEX(&jfs_ip->commit_sem);
 		jfs_ip->atlhead = 0;
+		jfs_ip->active_ag = -1;
 		inode_init_once(&jfs_ip->vfs_inode);
 	}
 }
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	Sat Sep 21 21:25:45 2002
+++ b/fs/jfs/xattr.c	Sat Sep 21 21:25:45 2002
@@ -78,6 +78,68 @@
 #define EA_NEW		0x0004
 #define EA_MALLOC	0x0008
 
+/* Namespaces */
+#define XATTR_SYSTEM_PREFIX "system."
+#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
+
+#define XATTR_USER_PREFIX "user."
+#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
+
+#define XATTR_OS2_PREFIX "os2."
+#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
+
+/*
+ * These three routines are used to recognize on-disk extended attributes
+ * that are in a recognized namespace.  If the attribute is not recognized,
+ * "os2." is prepended to the name
+ */
+static inline int is_os2_xattr(struct jfs_ea *ea)
+{
+	/*
+	 * Check for "system."
+	 */
+	if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) &&
+	    !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+		return FALSE;
+	/*
+	 * Check for "user."
+	 */
+	if ((ea->namelen >= XATTR_USER_PREFIX_LEN) &&
+	    !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+		return FALSE;
+	/*
+	 * Add any other valid namespace prefixes here
+	 */
+
+	/*
+	 * We assume it's OS/2's flat namespace
+	 */
+	return TRUE;
+}
+
+static inline int name_size(struct jfs_ea *ea)
+{
+	if (is_os2_xattr(ea))
+		return ea->namelen + XATTR_OS2_PREFIX_LEN;
+	else
+		return ea->namelen;
+}
+
+static inline int copy_name(char *buffer, struct jfs_ea *ea)
+{
+	int len = ea->namelen;
+
+	if (is_os2_xattr(ea)) {
+		memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN);
+		buffer += XATTR_OS2_PREFIX_LEN;
+		len += XATTR_OS2_PREFIX_LEN;
+	}
+	memcpy(buffer, ea->name, ea->namelen);
+	buffer[ea->namelen] = 0;
+
+	return len;
+}
+
 /* Forward references */
 static void ea_release(struct inode *inode, struct ea_buffer *ea_buf);
 
@@ -577,7 +639,8 @@
 	return rc;
 }
 
-static int can_set_xattr(struct inode *inode, const char *name)
+static int can_set_xattr(struct inode *inode, const char *name,
+			 void *value, size_t value_len)
 {
 	if (IS_RDONLY(inode))
 		return -EROFS;
@@ -585,6 +648,10 @@
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode))
 		return -EPERM;
 
+	if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&
+	   (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))
+		return -EOPNOTSUPP;
+
 	if (!S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))
 		return -EPERM;
@@ -602,13 +669,24 @@
 	int xattr_size;
 	int new_size;
 	int namelen = strlen(name);
+	char *os2name = NULL;
 	int found = 0;
 	int rc;
 	int length;
 
-	if ((rc = can_set_xattr(inode, name)))
+	if ((rc = can_set_xattr(inode, name, value, value_len)))
 		return rc;
 
+	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
+		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
+				  GFP_KERNEL);
+		if (!os2name)
+			return -ENOMEM;
+		strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
+		name = os2name;
+		namelen -= XATTR_OS2_PREFIX_LEN;
+	}
+
 	xattr_size = ea_get(inode, &ea_buf, 0);
 	if (xattr_size < 0) {
 		rc = xattr_size;
@@ -714,6 +792,9 @@
       release:
 	ea_release(inode, &ea_buf);
       out:
+	if (os2name)
+		kfree(os2name);
+
 	return rc;
 }
 
@@ -728,7 +809,7 @@
 	return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
 }
 
-static int can_get_xattr(struct inode *inode, const char *name)
+static inline int can_get_xattr(struct inode *inode, const char *name)
 {
 	return permission(inode, MAY_READ);
 }
@@ -742,12 +823,23 @@
 	int xattr_size;
 	ssize_t size;
 	int namelen = strlen(name);
+	char *os2name = NULL;
 	int rc;
 	char *value;
 
 	if ((rc = can_get_xattr(inode, name)))
 		return rc;
 
+	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
+		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
+				  GFP_KERNEL);
+		if (!os2name)
+			return -ENOMEM;
+		strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
+		name = os2name;
+		namelen -= XATTR_OS2_PREFIX_LEN;
+	}
+
 	xattr_size = ea_get(inode, &ea_buf, 0);
 	if (xattr_size < 0) {
 		size = xattr_size;
@@ -780,6 +872,8 @@
       release:
 	ea_release(inode, &ea_buf);
       out:
+	if (os2name)
+		kfree(os2name);
 
 	return size;
 }
@@ -813,7 +907,7 @@
 
 	/* compute required size of list */
 	for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea))
-		size += ea->namelen + 1;
+		size += name_size(ea) + 1;
 
 	if (!data)
 		goto release;
@@ -826,9 +920,8 @@
 	/* Copy attribute names to buffer */
 	buffer = data;
 	for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) {
-		memcpy(buffer, ea->name, ea->namelen);
-		buffer[ea->namelen] = 0;
-		buffer += ea->namelen + 1;
+		int namelen = copy_name(buffer, ea);
+		buffer += namelen + 1;
 	}
 
       release:
diff -Nru a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile
--- a/fs/ncpfs/Makefile	Sat Sep 21 21:25:48 2002
+++ b/fs/ncpfs/Makefile	Sat Sep 21 21:25:48 2002
@@ -5,7 +5,7 @@
 obj-$(CONFIG_NCP_FS) += ncpfs.o
 
 ncpfs-objs   := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \
-		ncpsign_kernel.o
+		ncpsign_kernel.o getopt.o
 ifeq ($(CONFIG_NCPFS_EXTRAS),y)
 ncpfs-objs   += symlink.o
 endif
diff -Nru a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/ncpfs/getopt.c	Sat Sep 21 21:25:48 2002
@@ -0,0 +1,75 @@
+/*
+ * getopt.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/errno.h>
+
+#include "getopt.h"
+
+/**
+ *	ncp_getopt - option parser
+ *	@caller: name of the caller, for error messages
+ *	@options: the options string
+ *	@opts: an array of &struct option entries controlling parser operations
+ *	@optopt: output; will contain the current option
+ *	@optarg: output; will contain the value (if one exists)
+ *	@flag: output; may be NULL; should point to a long for or'ing flags
+ *	@value: output; may be NULL; will be overwritten with the integer value
+ *		of the current argument.
+ *
+ *	Helper to parse options on the format used by mount ("a=b,c=d,e,f").
+ *	Returns opts->val if a matching entry in the 'opts' array is found,
+ *	0 when no more tokens are found, -1 if an error is encountered.
+ */
+int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
+	       char **optopt, char **optarg, unsigned long *value)
+{
+	char *token;
+	char *val;
+
+	do {
+		if ((token = strsep(options, ",")) == NULL)
+			return 0;
+	} while (*token == '\0');
+	if (optopt)
+		*optopt = token;
+
+	if ((val = strchr (token, '=')) != NULL) {
+		*val++ = 0;
+	}
+	*optarg = val;
+	for (; opts->name; opts++) {
+		if (!strcmp(opts->name, token)) {
+			if (!val) {
+				if (opts->has_arg & OPT_NOPARAM) {
+					return opts->val;
+				}
+				printk(KERN_INFO "%s: the %s option requires an argument\n",
+				       caller, token);
+				return -EINVAL;
+			}
+			if (opts->has_arg & OPT_INT) {
+				char* v;
+
+				*value = simple_strtoul(val, &v, 0);
+				if (!*v) {
+					return opts->val;
+				}
+				printk(KERN_INFO "%s: invalid numeric value in %s=%s\n",
+					caller, token, val);
+				return -EDOM;
+			}
+			if (opts->has_arg & OPT_STRING) {
+				return opts->val;
+			}
+			printk(KERN_INFO "%s: unexpected argument %s to the %s option\n",
+				caller, val, token);
+			return -EINVAL;
+		}
+	}
+	printk(KERN_INFO "%s: Unrecognized mount option %s\n", caller, token);
+	return -EOPNOTSUPP;
+}
diff -Nru a/fs/ncpfs/getopt.h b/fs/ncpfs/getopt.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/ncpfs/getopt.h	Sat Sep 21 21:25:48 2002
@@ -0,0 +1,16 @@
+#ifndef _LINUX_GETOPT_H
+#define _LINUX_GETOPT_H
+
+#define OPT_NOPARAM	1
+#define OPT_INT		2
+#define OPT_STRING	4
+struct ncp_option {
+	const char *name;
+	unsigned int has_arg;
+	int val;
+};
+
+extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts,
+		      char **optopt, char **optarg, unsigned long *value);
+
+#endif /* _LINUX_GETOPT_H */
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	Sat Sep 21 21:25:45 2002
+++ b/fs/ncpfs/inode.c	Sat Sep 21 21:25:45 2002
@@ -31,7 +31,10 @@
 
 #include <linux/ncp_fs.h>
 
+#include <net/sock.h>
+
 #include "ncplib_kernel.h"
+#include "getopt.h"
 
 static void ncp_delete_inode(struct inode *);
 static void ncp_put_super(struct super_block *);
@@ -283,6 +286,103 @@
 	clear_inode(inode);
 }
 
+static void ncp_stop_tasks(struct ncp_server *server) {
+	struct sock* sk = server->ncp_sock->sk;
+		
+	sk->error_report = server->error_report;
+	sk->data_ready = server->data_ready;
+	sk->write_space = server->write_space;
+	del_timer_sync(&server->timeout_tm);
+	flush_scheduled_tasks();
+}
+
+static const struct ncp_option ncp_opts[] = {
+	{ "uid",	OPT_INT,	'u' },
+	{ "gid",	OPT_INT,	'g' },
+	{ "owner",	OPT_INT,	'o' },
+	{ "mode",	OPT_INT,	'm' },
+	{ "dirmode",	OPT_INT,	'd' },
+	{ "timeout",	OPT_INT,	't' },
+	{ "retry",	OPT_INT,	'r' },
+	{ "flags",	OPT_INT,	'f' },
+	{ "wdogpid",	OPT_INT,	'w' },
+	{ "ncpfd",	OPT_INT,	'n' },
+	{ "infofd",	OPT_INT,	'i' },	/* v5 */
+	{ "version",	OPT_INT,	'v' },
+	{ NULL,		0,		0 } };
+
+static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
+	int optval;
+	char *optarg;
+	unsigned long optint;
+	int version = 0;
+
+	data->flags = 0;
+	data->int_flags = 0;
+	data->mounted_uid = 0;
+	data->wdog_pid = -1;
+	data->ncp_fd = ~0;
+	data->time_out = 10;
+	data->retry_count = 20;
+	data->uid = 0;
+	data->gid = 0;
+	data->file_mode = 0600;
+	data->dir_mode = 0700;
+	data->info_fd = -1;
+	data->mounted_vol[0] = 0;
+	
+	while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
+		if (optval < 0)
+			return optval;
+		switch (optval) {
+			case 'u':
+				data->uid = optint;
+				break;
+			case 'g':
+				data->gid = optint;
+				break;
+			case 'o':
+				data->mounted_uid = optint;
+				break;
+			case 'm':
+				data->file_mode = optint;
+				break;
+			case 'd':
+				data->dir_mode = optint;
+				break;
+			case 't':
+				data->time_out = optint;
+				break;
+			case 'r':
+				data->retry_count = optint;
+				break;
+			case 'f':
+				data->flags = optint;
+				break;
+			case 'w':
+				data->wdog_pid = optint;
+				break;
+			case 'n':
+				data->ncp_fd = optint;
+				break;
+			case 'i':
+				data->info_fd = optint;
+				break;
+			case 'v':
+				if (optint < NCP_MOUNT_VERSION_V4) {
+					return -ECHRNG;
+				}
+				if (optint > NCP_MOUNT_VERSION_V5) {
+					return -ECHRNG;
+				}
+				version = optint;
+				break;
+			
+		}
+	}
+	return 0;
+}
+
 static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 {
 	struct ncp_mount_data_kernel data;
@@ -323,6 +423,7 @@
 				data.gid = md->gid;
 				data.file_mode = md->file_mode;
 				data.dir_mode = md->dir_mode;
+				data.info_fd = -1;
 				memcpy(data.mounted_vol, md->mounted_vol,
 					NCP_VOLNAME_LEN+1);
 			}
@@ -342,12 +443,18 @@
 				data.gid = md->gid;
 				data.file_mode = md->file_mode;
 				data.dir_mode = md->dir_mode;
+				data.info_fd = -1;
 				data.mounted_vol[0] = 0;
 			}
 			break;
 		default:
 			error = -ECHRNG;
-			goto out;
+			if (*(__u32*)raw_data == cpu_to_be32(0x76657273)) {
+				error = ncp_parse_options(&data, raw_data);
+			}
+			if (error)
+				goto out;
+			break;
 	}
 	error = -EBADF;
 	ncp_filp = fget(data.ncp_fd);
@@ -376,6 +483,28 @@
 	memset(server, 0, sizeof(*server));
 
 	server->ncp_filp = ncp_filp;
+	server->ncp_sock = sock;
+	
+	if (data.info_fd != -1) {
+		struct socket *info_sock;
+
+		error = -EBADF;
+		server->info_filp = fget(data.info_fd);
+		if (!server->info_filp)
+			goto out_fput;
+		error = -ENOTSOCK;
+		sock_inode = server->info_filp->f_dentry->d_inode;
+		if (!S_ISSOCK(sock_inode->i_mode))
+			goto out_fput2;
+		info_sock = SOCKET_I(sock_inode);
+		if (!info_sock)
+			goto out_fput2;
+		error = -EBADFD;
+		if (info_sock->type != SOCK_STREAM)
+			goto out_fput2;
+		server->info_sock = info_sock;
+	}
+
 /*	server->lock = 0;	*/
 	init_MUTEX(&server->sem);
 	server->packet = NULL;
@@ -413,6 +542,16 @@
 
 	server->dentry_ttl = 0;	/* no caching */
 
+	INIT_LIST_HEAD(&server->tx.requests);
+	init_MUTEX(&server->rcv.creq_sem);
+	server->tx.creq = NULL;
+	server->rcv.creq = NULL;
+	server->data_ready = sock->sk->data_ready;
+	server->write_space = sock->sk->write_space;
+	server->error_report = sock->sk->error_report;
+	sock->sk->user_data = server;
+
+	init_timer(&server->timeout_tm);
 #undef NCP_PACKET_SIZE
 #define NCP_PACKET_SIZE 131072
 	error = -ENOMEM;
@@ -421,6 +560,22 @@
 	if (server->packet == NULL)
 		goto out_nls;
 
+	sock->sk->data_ready = ncp_tcp_data_ready;
+	sock->sk->error_report = ncp_tcp_error_report;
+	if (sock->type == SOCK_STREAM) {
+		server->rcv.ptr = (unsigned char*)&server->rcv.buf;
+		server->rcv.len = 10;
+		server->rcv.state = 0;
+		INIT_TQUEUE(&server->rcv.tq, ncp_tcp_rcv_proc, server);
+		INIT_TQUEUE(&server->tx.tq, ncp_tcp_tx_proc, server);
+		sock->sk->write_space = ncp_tcp_write_space;
+	} else {
+		INIT_TQUEUE(&server->rcv.tq, ncpdgram_rcv_proc, server);
+		INIT_TQUEUE(&server->timeout_tq, ncpdgram_timeout_proc, server);
+		server->timeout_tm.data = (unsigned long)server;
+		server->timeout_tm.function = ncpdgram_timeout_call;
+	}
+
 	ncp_lock_server(server);
 	error = ncp_connect(server);
 	ncp_unlock_server(server);
@@ -495,12 +650,16 @@
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
 out_packet:
+	ncp_stop_tasks(server);
 	vfree(server->packet);
 out_nls:
 #ifdef CONFIG_NCPFS_NLS
 	unload_nls(server->nls_io);
 	unload_nls(server->nls_vol);
 #endif
+out_fput2:
+	if (server->info_filp)
+		fput(server->info_filp);
 out_fput:
 	/* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
 	 * 
@@ -522,6 +681,8 @@
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
 
+	ncp_stop_tasks(server);
+
 #ifdef CONFIG_NCPFS_NLS
 	/* unload the NLS charsets */
 	if (server->nls_vol)
@@ -536,6 +697,8 @@
 	}
 #endif /* CONFIG_NCPFS_NLS */
 
+	if (server->info_filp)
+		fput(server->info_filp);
 	fput(server->ncp_filp);
 	kill_proc(server->m.wdog_pid, SIGTERM, 1);
 
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	Sat Sep 21 21:25:43 2002
+++ b/fs/ncpfs/ioctl.c	Sat Sep 21 21:25:43 2002
@@ -424,7 +424,7 @@
 			if (user.object_name_len) {
 				newname = ncp_kmalloc(user.object_name_len, GFP_USER);
 				if (!newname) return -ENOMEM;
-				if (copy_from_user(newname, user.object_name, sizeof(user))) {
+				if (copy_from_user(newname, user.object_name, user.object_name_len)) {
 					ncp_kfree_s(newname, user.object_name_len);
 					return -EFAULT;
 				}
diff -Nru a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
--- a/fs/ncpfs/ncplib_kernel.c	Sat Sep 21 21:25:45 2002
+++ b/fs/ncpfs/ncplib_kernel.c	Sat Sep 21 21:25:45 2002
@@ -341,6 +341,7 @@
 	target->nameLen = *name_len;
 	memcpy(target->entryName, name_len + 1, *name_len);
 	target->entryName[*name_len] = '\0';
+	target->volNumber = le32_to_cpu(target->volNumber);
 	return;
 }
 
@@ -475,7 +476,7 @@
 	}
 
 	result = NW_NS_DOS;
-	no_namespaces = ncp_reply_word(server, 0);
+	no_namespaces = le16_to_cpu(ncp_reply_word(server, 0));
 	namespace = ncp_reply_data(server, 2);
 
 	while (no_namespaces > 0) {
diff -Nru a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
--- a/fs/ncpfs/ncpsign_kernel.c	Sat Sep 21 21:25:45 2002
+++ b/fs/ncpfs/ncpsign_kernel.c	Sat Sep 21 21:25:45 2002
@@ -93,19 +93,35 @@
 
 /* Make a signature for the current packet and add it at the end of the */
 /* packet. */
-void sign_packet(struct ncp_server *server, int *size) {
- char data[64];
+void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) {
+	unsigned char data[64];
 
- memset(data,0,64);
- memcpy(data,server->sign_root,8);
- PUT_LE32(data+8,(*size));
- memcpy(data+12,server->packet+sizeof(struct ncp_request_header)-1,
-  min_t(unsigned int,(*size)-sizeof(struct ncp_request_header)+1,52));
+	memcpy(data, server->sign_root, 8);
+	*(__u32*)(data + 8) = totalsize;
+	if (size < 52) {
+		memcpy(data + 12, packet, size);
+		memset(data + 12 + size, 0, 52 - size);
+	} else {
+		memcpy(data + 12, packet, 52);
+	}
+	nwsign(server->sign_last, data, server->sign_last);
+	memcpy(sign_buff, server->sign_last, 8);
+}
 
- nwsign(server->sign_last,data,server->sign_last);
+int sign_verify_reply(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, const void *sign_buff) {
+	unsigned char data[64];
+	unsigned char hash[16];
 
- memcpy(server->packet+(*size),server->sign_last,8);
- (*size)+=8;
+	memcpy(data, server->sign_root, 8);
+	*(__u32*)(data + 8) = totalsize;
+	if (size < 52) {
+		memcpy(data + 12, packet, size);
+		memset(data + 12 + size, 0, 52 - size);
+	} else {
+		memcpy(data + 12, packet, 52);
+	}
+	nwsign(server->sign_last, data, hash);
+	return memcmp(sign_buff, hash, 8);
 }
 
 #endif	/* CONFIG_NCPFS_PACKET_SIGNING */
diff -Nru a/fs/ncpfs/ncpsign_kernel.h b/fs/ncpfs/ncpsign_kernel.h
--- a/fs/ncpfs/ncpsign_kernel.h	Sat Sep 21 21:25:48 2002
+++ b/fs/ncpfs/ncpsign_kernel.h	Sat Sep 21 21:25:48 2002
@@ -10,6 +10,19 @@
 
 #include <linux/ncp_fs.h>
 
-void sign_packet(struct ncp_server *server, int *size);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff);
+int sign_verify_reply(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, const void *sign_buff);
+#endif
+
+static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) {
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+	if (server->sign_active) {
+		__sign_packet(server, data, size, totalsize, sign_buff);
+		return 8;
+	}
+#endif
+	return 0;
+}
 
 #endif
diff -Nru a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
--- a/fs/ncpfs/sock.c	Sat Sep 21 21:25:45 2002
+++ b/fs/ncpfs/sock.c	Sat Sep 21 21:25:45 2002
@@ -29,18 +29,13 @@
 
 #include <linux/ncp_fs.h>
 
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
 #include "ncpsign_kernel.h"
-#endif
 
 static int _recv(struct socket *sock, unsigned char *ubuf, int size,
 		 unsigned flags)
 {
 	struct iovec iov;
 	struct msghdr msg;
-	struct scm_cookie scm;
-
-	memset(&scm, 0, sizeof(scm));
 
 	iov.iov_base = ubuf;
 	iov.iov_len = size;
@@ -50,15 +45,14 @@
 	msg.msg_control = NULL;
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
-	return sock->ops->recvmsg(sock, &msg, size, flags, &scm);
+
+	return sock_recvmsg(sock, &msg, size, flags);
 }
 
-static int _send(struct socket *sock, const void *buff, int len)
+static inline int _send(struct socket *sock, const void *buff, int len)
 {
 	struct iovec iov;
 	struct msghdr msg;
-	struct scm_cookie scm;
-	int err;
 
 	iov.iov_base = (void *) buff;
 	iov.iov_len = len;
@@ -70,353 +64,661 @@
 	msg.msg_iovlen = 1;
 	msg.msg_flags = 0;
 
-	err = scm_send(sock, &msg, &scm);
-	if (err < 0) {
-		return err;
-	}
-	err = sock->ops->sendmsg(sock, &msg, len, &scm);
-	scm_destroy(&scm);
-	return err;
+	return sock_sendmsg(sock, &msg, len);
 }
 
-static int do_ncp_rpc_call(struct ncp_server *server, int size,
-		struct ncp_reply_header* reply_buf, int max_reply_size)
-{
-	struct file *file;
-	struct socket *sock;
+struct ncp_request_reply {
+	struct list_head req;
+	wait_queue_head_t wq;
+	struct ncp_reply_header* reply_buf;
+	size_t datalen;
 	int result;
-	char *start = server->packet;
-	poll_table wait_table;
-	int init_timeout, max_timeout;
-	int timeout;
-	int retrans;
-	int major_timeout_seen;
-	int acknowledge_seen;
-	int n;
+	enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status;
+	struct iovec* tx_ciov;
+	size_t tx_totallen;
+	size_t tx_iovlen;
+	struct iovec tx_iov[3];
+	u_int16_t tx_type;
+	u_int32_t sign[6];
+};
 
-	/* We have to check the result, so store the complete header */
-	struct ncp_request_header request =
-	*((struct ncp_request_header *) (server->packet));
+void ncp_tcp_data_ready(struct sock *sk, int len) {
+	struct ncp_server *server = sk->user_data;
+
+	server->data_ready(sk, len);
+	schedule_task(&server->rcv.tq);
+}
+
+void ncp_tcp_error_report(struct sock *sk) {
+	struct ncp_server *server = sk->user_data;
+	
+	server->error_report(sk);
+	schedule_task(&server->rcv.tq);
+}
+
+void ncp_tcp_write_space(struct sock *sk) {
+	struct ncp_server *server = sk->user_data;
+	
+	/* We do not need any locking: we first set tx.creq, and then we do sendmsg,
+	   not vice versa... */
+	server->write_space(sk);
+	if (server->tx.creq) {
+		schedule_task(&server->tx.tq);
+	}
+}
+
+void ncpdgram_timeout_call(unsigned long v) {
+	struct ncp_server *server = (void*)v;
+	
+	schedule_task(&server->timeout_tq);
+}
+
+static inline void ncp_finish_request(struct ncp_request_reply *req, int result) {
+	req->result = result;
+	req->status = RQ_DONE;
+	wake_up_all(&req->wq);
+}
+
+static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err) {
+	struct ncp_request_reply *req;
+
+	ncp_invalidate_conn(server);
+	del_timer(&server->timeout_tm);
+	while (!list_empty(&server->tx.requests)) {
+		req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
+		
+		list_del_init(&req->req);
+		if (req == aborted) {
+			ncp_finish_request(req, err);
+		} else {
+			ncp_finish_request(req, -EIO);
+		}
+	}
+	req = server->rcv.creq;
+	if (req) {
+		server->rcv.creq = NULL;
+		if (req == aborted) {
+			ncp_finish_request(req, err);
+		} else {
+			ncp_finish_request(req, -EIO);
+		}
+		server->rcv.ptr = NULL;
+		server->rcv.state = 0;
+	}
+	req = server->tx.creq;
+	if (req) {
+		server->tx.creq = NULL;
+		if (req == aborted) {
+			ncp_finish_request(req, err);
+		} else {
+			ncp_finish_request(req, -EIO);
+		}
+	}
+}
+
+static inline int get_conn_number(struct ncp_reply_header *rp) {
+	return rp->conn_low | (rp->conn_high << 8);
+}
+
+static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
+	/* If req is done, we got signal, but we also received answer... */
+	switch (req->status) {
+		case RQ_IDLE:
+		case RQ_DONE:
+			break;
+		case RQ_QUEUED:
+			list_del_init(&req->req);
+			ncp_finish_request(req, err);
+			break;
+		case RQ_INPROGRESS:
+			__abort_ncp_connection(server, req, err);
+			break;
+	}
+}
+
+static inline void ncp_abort_request(struct ncp_server *server, struct ncp_request_reply *req, int err) {
+	down(&server->rcv.creq_sem);
+	__ncp_abort_request(server, req, err);
+	up(&server->rcv.creq_sem);
+}
+
+static inline void __ncptcp_abort(struct ncp_server *server) {
+	__abort_ncp_connection(server, NULL, 0);
+}
+
+static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) {
+	struct msghdr msg;
+	
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_control = NULL;
+	msg.msg_iov = req->tx_ciov;
+	msg.msg_iovlen = req->tx_iovlen;
+	msg.msg_flags = MSG_DONTWAIT;
+	return sock_sendmsg(sock, &msg, req->tx_totallen);
+}
+
+static void __ncptcp_try_send(struct ncp_server *server) {
+	struct ncp_request_reply *rq;
+	struct msghdr msg;
+	struct iovec* iov;
+	int result;
+
+	rq = server->tx.creq;
+	if (!rq) {
+		return;
+	}
+
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_control = NULL;
+	msg.msg_iov = rq->tx_ciov;
+	msg.msg_iovlen = rq->tx_iovlen;
+	msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT;
+	result = sock_sendmsg(server->ncp_sock, &msg, rq->tx_totallen);
+	if (result == -EAGAIN) {
+		return;
+	}
+	if (result < 0) {
+		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
+		__ncp_abort_request(server, rq, result);
+		return;
+	}
+	if (result >= rq->tx_totallen) {
+		server->rcv.creq = rq;
+		server->tx.creq = NULL;
+		return;
+	}
+	rq->tx_totallen -= result;
+	iov = rq->tx_ciov;
+	while (iov->iov_len <= result) {
+		result -= iov->iov_len;
+		iov++;
+		rq->tx_iovlen--;
+	}
+	iov->iov_len -= result;
+	rq->tx_ciov = iov;
+}
 
-	struct ncp_reply_header reply;
+static inline void ncp_init_header(struct ncp_server *server, struct ncp_request_reply *req, struct ncp_request_header *h) {
+	req->status = RQ_INPROGRESS;
+	h->conn_low = server->connection;
+	h->conn_high = server->connection >> 8;
+	h->sequence = ++server->sequence;
+}
+	
+static void ncpdgram_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
+	size_t signlen;
+	struct ncp_request_header* h;
+	
+	req->tx_ciov = req->tx_iov + 1;
+
+	h = req->tx_iov[1].iov_base;
+	ncp_init_header(server, req, h);
+	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1, 
+			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
+			cpu_to_le32(req->tx_totallen), req->sign);
+	if (signlen) {
+		req->tx_ciov[1].iov_base = req->sign;
+		req->tx_ciov[1].iov_len = signlen;
+		req->tx_iovlen += 1;
+		req->tx_totallen += signlen;
+	}
+	server->rcv.creq = req;
+	server->timeout_last = server->m.time_out;
+	server->timeout_retries = server->m.retry_count;
+	ncpdgram_send(server->ncp_sock, req);
+	mod_timer(&server->timeout_tm, jiffies + server->m.time_out);
+}
+
+#define NCP_TCP_XMIT_MAGIC	(0x446D6454)
+#define NCP_TCP_XMIT_VERSION	(1)
+#define NCP_TCP_RCVD_MAGIC	(0x744E6350)
 
-	file = server->ncp_filp;
-	sock = SOCKET_I(file->f_dentry->d_inode);
+static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
+	size_t signlen;
+	struct ncp_request_header* h;
+
+	req->tx_ciov = req->tx_iov;
+	h = req->tx_iov[1].iov_base;
+	ncp_init_header(server, req, h);
+	signlen = sign_packet(server, req->tx_iov[1].iov_base + sizeof(struct ncp_request_header) - 1,
+			req->tx_iov[1].iov_len - sizeof(struct ncp_request_header) + 1,
+			cpu_to_be32(req->tx_totallen + 24), req->sign + 4) + 16;
+
+	req->sign[0] = htonl(NCP_TCP_XMIT_MAGIC);
+	req->sign[1] = htonl(req->tx_totallen + signlen);
+	req->sign[2] = htonl(NCP_TCP_XMIT_VERSION);
+	req->sign[3] = htonl(req->datalen + 8);
+	req->tx_iov[0].iov_base = req->sign;
+	req->tx_iov[0].iov_len = signlen;
+	req->tx_iovlen += 1;
+	req->tx_totallen += signlen;
 
-	init_timeout = server->m.time_out;
-	max_timeout = NCP_MAX_RPC_TIMEOUT;
-	retrans = server->m.retry_count;
-	major_timeout_seen = 0;
-	acknowledge_seen = 0;
-
-	for (n = 0, timeout = init_timeout;; n++, timeout <<= 1) {
-		/*
-		DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
-			 htonl(server->m.serv_addr.sipx_network),
-			 server->m.serv_addr.sipx_node[0],
-			 server->m.serv_addr.sipx_node[1],
-			 server->m.serv_addr.sipx_node[2],
-			 server->m.serv_addr.sipx_node[3],
-			 server->m.serv_addr.sipx_node[4],
-			 server->m.serv_addr.sipx_node[5],
-			 ntohs(server->m.serv_addr.sipx_port));
-		*/
-		DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
-			 "seq: %d",
-			 request.type,
-			 (request.conn_high << 8) + request.conn_low,
-			 request.sequence);
-		DDPRINTK(" func: %d\n",
-			 request.function);
+	server->tx.creq = req;
+	__ncptcp_try_send(server);
+}
 
-		result = _send(sock, (void *) start, size);
+static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) {
+	if (server->ncp_sock->type == SOCK_STREAM)
+		ncptcp_start_request(server, req);
+	else
+		ncpdgram_start_request(server, req);
+}
+
+static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply *req) {
+	down(&server->rcv.creq_sem);
+	if (!ncp_conn_valid(server)) {
+		up(&server->rcv.creq_sem);
+		printk(KERN_ERR "ncpfs: tcp: Server died\n");
+		return -EIO;
+	}
+	if (server->tx.creq || server->rcv.creq) {
+		req->status = RQ_QUEUED;
+		list_add_tail(&req->req, &server->tx.requests);
+		up(&server->rcv.creq_sem);
+		return 0;
+	}
+	__ncp_start_request(server, req);
+	up(&server->rcv.creq_sem);
+	return 0;
+}
+
+static void __ncp_next_request(struct ncp_server *server) {
+	struct ncp_request_reply *req;
+
+	server->rcv.creq = NULL;
+	if (list_empty(&server->tx.requests)) {
+		return;
+	}
+	req = list_entry(server->tx.requests.next, struct ncp_request_reply, req);
+	list_del_init(&req->req);
+	__ncp_start_request(server, req);
+}
+
+static void info_server(struct ncp_server *server, unsigned int id, const void * data, size_t len) {
+	if (server->info_sock) {
+		struct iovec iov[2];
+		struct msghdr msg;
+		__u32 hdr[2];
+	
+		hdr[0] = cpu_to_be32(len + 8);
+		hdr[1] = cpu_to_be32(id);
+	
+		iov[0].iov_base = hdr;
+		iov[0].iov_len = 8;
+		iov[1].iov_base = (void *) data;
+		iov[1].iov_len = len;
+
+		msg.msg_name = NULL;
+		msg.msg_namelen = 0;
+		msg.msg_control = NULL;
+		msg.msg_iov = iov;
+		msg.msg_iovlen = 2;
+		msg.msg_flags = MSG_NOSIGNAL;
+
+		sock_sendmsg(server->info_sock, &msg, len + 8);
+	}
+}
+
+static void __ncpdgram_rcv_proc(void *s) {
+	struct ncp_server *server = s;
+	struct socket* sock;
+	
+	sock = server->ncp_sock;
+	
+	while (1) {
+		struct ncp_reply_header reply;
+		int result;
+
+		result = _recv(sock, (void*)&reply, sizeof(reply), MSG_PEEK | MSG_DONTWAIT);
 		if (result < 0) {
-			printk(KERN_ERR "ncp_rpc_call: send error = %d\n", result);
-			return result;
+			break;
 		}
-	      re_select:
-		poll_initwait(&wait_table);
-		/* mb() is not necessary because ->poll() will serialize
-		   instructions adding the wait_table waitqueues in the
-		   waitqueue-head before going to calculate the mask-retval. */
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) {
-			int timed_out;
-			if (timeout > max_timeout) {
-				/* JEJB/JSP 2/7/94
-				 * This is useful to see if the system is
-				 * hanging */
-				if (acknowledge_seen == 0) {
-					printk(KERN_WARNING "NCP max timeout\n");
+		if (result >= sizeof(reply)) {
+			struct ncp_request_reply *req;
+	
+			if (reply.type == NCP_WATCHDOG) {
+				unsigned char buf[10];
+
+				if (server->connection != get_conn_number(&reply)) {
+					goto drop;
 				}
-				timeout = max_timeout;
-			}
-			timed_out = !schedule_timeout(timeout);
-			poll_freewait(&wait_table);
-			current->state = TASK_RUNNING;
-			if (signal_pending(current)) {
-				result = -ERESTARTSYS;
-				break;
-			}
-			if(wait_table.error) {
-				result = wait_table.error;
-				break;
-			}
-			if (timed_out) {
-				if (n < retrans)
+				result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT);
+				if (result < 0) {
+					DPRINTK("recv failed with %d\n", result);
+					continue;
+				}
+				if (result < 10) {
+					DPRINTK("too short (%u) watchdog packet\n", result);
 					continue;
-				if (server->m.flags & NCP_MOUNT_SOFT) {
-					printk(KERN_WARNING "NCP server not responding\n");
-					result = -EIO;
-					break;
 				}
-				n = 0;
-				timeout = init_timeout;
-				if (init_timeout < max_timeout)
-					init_timeout <<= 1;
-				if (!major_timeout_seen) {
-					printk(KERN_WARNING "NCP server not responding\n");
+				if (buf[9] != '?') {
+					DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]);
+					continue;
 				}
-				major_timeout_seen = 1;
+				buf[9] = 'Y';
+				_send(sock, buf, sizeof(buf));
 				continue;
 			}
-		} else {
-			poll_freewait(&wait_table);
+			if (reply.type != NCP_POSITIVE_ACK && reply.type != NCP_REPLY) {
+				result = _recv(sock, server->unexpected_packet.data, sizeof(server->unexpected_packet.data), MSG_DONTWAIT);
+				if (result < 0) {
+					continue;
+				}
+				info_server(server, 0, server->unexpected_packet.data, result);
+				continue;
+			}
+			down(&server->rcv.creq_sem);		
+			req = server->rcv.creq;
+			if (req && (req->tx_type == NCP_ALLOC_SLOT_REQUEST || (server->sequence == reply.sequence && 
+					server->connection == get_conn_number(&reply)))) {
+				if (reply.type == NCP_POSITIVE_ACK) {
+					server->timeout_retries = server->m.retry_count;
+					server->timeout_last = NCP_MAX_RPC_TIMEOUT;
+					mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT);
+				} else if (reply.type == NCP_REPLY) {
+					result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+					if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
+						if (result < 8 + 8) {
+							result = -EIO;
+						} else {
+							unsigned int hdrl;
+							
+							result -= 8;
+							hdrl = sock->sk->family == AF_INET ? 8 : 6;
+							if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) {
+								printk(KERN_INFO "ncpfs: Signature violation\n");
+								result = -EIO;
+							}
+						}
+					}
+#endif
+					del_timer(&server->timeout_tm);
+				     	server->rcv.creq = NULL;
+					ncp_finish_request(req, result);
+					__ncp_next_request(server);
+					up(&server->rcv.creq_sem);
+					continue;
+				}
+			}
+			up(&server->rcv.creq_sem);
 		}
-		current->state = TASK_RUNNING;
+drop:;		
+		_recv(sock, (void*)&reply, sizeof(reply), MSG_DONTWAIT);
+	}
+}
 
-		/* Get the header from the next packet using a peek, so keep it
-		 * on the recv queue.  If it is wrong, it will be some reply
-		 * we don't now need, so discard it */
-		result = _recv(sock, (void *) &reply, sizeof(reply),
-			       MSG_PEEK | MSG_DONTWAIT);
-		if (result < 0) {
-			if (result == -EAGAIN) {
-				DDPRINTK("ncp_rpc_call: bad select ready\n");
-				goto re_select;
-			}
-			if (result == -ECONNREFUSED) {
-				DPRINTK("ncp_rpc_call: server playing coy\n");
-				goto re_select;
+void ncpdgram_rcv_proc(void *s) {
+	mm_segment_t fs;
+	struct ncp_server *server = s;
+	
+	fs = get_fs();
+	set_fs(get_ds());
+	__ncpdgram_rcv_proc(server);
+	set_fs(fs);
+}
+
+static void __ncpdgram_timeout_proc(struct ncp_server *server) {
+	/* If timer is pending, we are processing another request... */
+	if (!timer_pending(&server->timeout_tm)) {
+		struct ncp_request_reply* req;
+		
+		req = server->rcv.creq;
+		if (req) {
+			int timeout;
+			
+			if (server->m.flags & NCP_MOUNT_SOFT) {
+				if (server->timeout_retries-- == 0) {
+					__ncp_abort_request(server, req, -ETIMEDOUT);
+					return;
+				}
 			}
-			if (result != -ERESTARTSYS) {
-				printk(KERN_ERR "ncp_rpc_call: recv error = %d\n",
-				       -result);
+			/* Ignore errors */
+			ncpdgram_send(server->ncp_sock, req);
+			timeout = server->timeout_last << 1;
+			if (timeout > NCP_MAX_RPC_TIMEOUT) {
+				timeout = NCP_MAX_RPC_TIMEOUT;
 			}
-			break;
+			server->timeout_last = timeout;
+			mod_timer(&server->timeout_tm, jiffies + timeout);
 		}
-		if ((result == sizeof(reply))
-		    && (reply.type == NCP_POSITIVE_ACK)) {
-			/* Throw away the packet */
-			DPRINTK("ncp_rpc_call: got positive acknowledge\n");
-			_recv(sock, (void *) &reply, sizeof(reply),
-			      MSG_DONTWAIT);
-			n = 0;
-			timeout = max_timeout;
-			acknowledge_seen = 1;
-			goto re_select;
-		}
-		DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
-			 "seq: %d\n",
-			 reply.type,
-			 (reply.conn_high << 8) + reply.conn_low,
-			 reply.task,
-			 reply.sequence);
-
-		if ((result >= sizeof(reply))
-		    && (reply.type == NCP_REPLY)
-		    && ((request.type == NCP_ALLOC_SLOT_REQUEST)
-			|| ((reply.sequence == request.sequence)
-			    && (reply.conn_low == request.conn_low)
-/* seem to get wrong task from NW311 && (reply.task      == request.task) */
-			    && (reply.conn_high == request.conn_high)))) {
-			if (major_timeout_seen)
-				printk(KERN_NOTICE "NCP server OK\n");
-			break;
-		}
-		/* JEJB/JSP 2/7/94
-		 * we have xid mismatch, so discard the packet and start
-		 * again.  What a hack! but I can't call recvfrom with
-		 * a null buffer yet. */
-		_recv(sock, (void *) &reply, sizeof(reply), MSG_DONTWAIT);
-
-		DPRINTK("ncp_rpc_call: reply mismatch\n");
-		goto re_select;
-	}
-	/* 
-	 * we have the correct reply, so read into the correct place and
-	 * return it
-	 */
-	result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT);
-	if (result < 0) {
-		printk(KERN_WARNING "NCP: notice message: result=%d\n", result);
-	} else if (result < sizeof(struct ncp_reply_header)) {
-		printk(KERN_ERR "NCP: just caught a too small read memory size..., "
-		       "email to NET channel\n");
-		printk(KERN_ERR "NCP: result=%d\n", result);
-		result = -EIO;
 	}
+}
 
-	return result;
+void ncpdgram_timeout_proc(void *s) {
+	mm_segment_t fs;
+	struct ncp_server *server = s;
+	
+	fs = get_fs();
+	set_fs(get_ds());
+	down(&server->rcv.creq_sem);
+	__ncpdgram_timeout_proc(server);
+	up(&server->rcv.creq_sem);
+	set_fs(fs);
+}
+
+static inline void ncp_init_req(struct ncp_request_reply* req) {
+	init_waitqueue_head(&req->wq);
+	req->status = RQ_IDLE;
 }
 
 static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) {
-	poll_table wait_table;
-	struct file *file;
-	struct socket *sock;
-	int init_timeout;
-	size_t dataread;
-	int result = 0;
-	
-	file = server->ncp_filp;
-	sock = SOCKET_I(file->f_dentry->d_inode);
-	
-	dataread = 0;
-
-	init_timeout = server->m.time_out * 20;
-	
-	/* hard-mounted volumes have no timeout, except connection close... */
-	if (!(server->m.flags & NCP_MOUNT_SOFT))
-		init_timeout = 0x7FFF0000;
-
-	while (len) {
-		poll_initwait(&wait_table);
-		/* mb() is not necessary because ->poll() will serialize
-		   instructions adding the wait_table waitqueues in the
-		   waitqueue-head before going to calculate the mask-retval. */
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) {
-			init_timeout = schedule_timeout(init_timeout);
-			poll_freewait(&wait_table);
-			current->state = TASK_RUNNING;
-			if (signal_pending(current)) {
-				return -ERESTARTSYS;
-			}
-			if (!init_timeout) {
-				return -EIO;
-			}
-			if(wait_table.error) {
-				return wait_table.error;
-			}
-		} else {
-			poll_freewait(&wait_table);
+	int result;
+	
+	if (buffer) {
+		result = _recv(server->ncp_sock, buffer, len, MSG_DONTWAIT);
+	} else {
+		static unsigned char dummy[1024];
+			
+		if (len > sizeof(dummy)) {
+			len = sizeof(dummy);
 		}
-		current->state = TASK_RUNNING;
+		result = _recv(server->ncp_sock, dummy, len, MSG_DONTWAIT);
+	}
+	if (result < 0) {
+		return result;
+	}
+	if (result > len) {
+		printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %u)\n", result, len);
+		return -EIO;			
+	}
+	return result;
+}	
 
-		result = _recv(sock, buffer, len, MSG_DONTWAIT);
-		if (result < 0) {
+static int __ncptcp_rcv_proc(struct ncp_server *server) {
+	/* We have to check the result, so store the complete header */
+	while (1) {
+		int result;
+		struct ncp_request_reply *req;
+		int datalen;
+		int type;
+
+		while (server->rcv.len) {
+			result = do_tcp_rcv(server, server->rcv.ptr, server->rcv.len);
 			if (result == -EAGAIN) {
-				DDPRINTK("ncpfs: tcp: bad select ready\n");
-				continue;
+				return 0;
 			}
-			return result;
-		}
-		if (result == 0) {
-			printk(KERN_ERR "ncpfs: tcp: EOF on socket\n");
-			return -EIO;
+			if (result <= 0) {
+				req = server->rcv.creq;
+				if (req) {
+					__ncp_abort_request(server, req, -EIO);
+				} else {
+					__ncptcp_abort(server);
+				}
+				if (result < 0) {
+					printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result);
+				} else {
+					DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n");
+				}
+				return -EIO;
+			}
+			if (server->rcv.ptr) {
+				server->rcv.ptr += result;
+			}
+			server->rcv.len -= result;
 		}
-		if (result > len) {
-			printk(KERN_ERR "ncpfs: tcp: bug in recvmsg\n");
-			return -EIO;			
+		switch (server->rcv.state) {
+			case 0:
+				if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) {
+					printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic));
+					__ncptcp_abort(server);
+					return -EIO;
+				}
+				datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF;
+				if (datalen < 10) {
+					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
+					__ncptcp_abort(server);
+					return -EIO;
+				}
+#ifdef CONFIG_NCPFS_PACKET_SIGNING				
+				if (server->sign_active) {
+					if (datalen < 18) {
+						printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
+						__ncptcp_abort(server);
+						return -EIO;
+					}
+					server->rcv.buf.len = datalen - 8;
+					server->rcv.ptr = (unsigned char*)&server->rcv.buf.p1;
+					server->rcv.len = 8;
+					server->rcv.state = 4;
+					break;
+				}
+#endif				
+				type = ntohs(server->rcv.buf.type);
+cont:;				
+				if (type != NCP_REPLY) {
+					if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
+						*(__u16*)(server->unexpected_packet.data) = htons(type);
+						server->unexpected_packet.len = datalen - 8;
+
+						server->rcv.state = 5;
+						server->rcv.ptr = server->unexpected_packet.data + 2;
+						server->rcv.len = datalen - 10;
+						break;
+					}					
+					DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type);
+skipdata2:;
+					server->rcv.state = 2;
+skipdata:;
+					server->rcv.ptr = NULL;
+					server->rcv.len = datalen - 10;
+					break;
+				}
+				req = server->rcv.creq;
+				if (!req) {
+					DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n");
+					goto skipdata2;
+				}
+				if (datalen > req->datalen + 8) {
+					printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %d)\n", datalen, req->datalen + 8);
+					server->rcv.state = 3;
+					goto skipdata;
+				}
+				req->datalen = datalen - 8;
+				req->reply_buf->type = NCP_REPLY;
+				server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2;
+				server->rcv.len = datalen - 10;
+				server->rcv.state = 1;
+				break;
+#ifdef CONFIG_NCPFS_PACKET_SIGNING				
+			case 4:
+				datalen = server->rcv.buf.len;
+				type = ntohs(server->rcv.buf.type2);
+				goto cont;
+#endif
+			case 1:
+				req = server->rcv.creq;
+				if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) {
+					if (req->reply_buf->sequence != server->sequence) {
+						printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
+						__ncp_abort_request(server, req, -EIO);
+						return -EIO;
+					}
+					if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) {
+						printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
+						__ncp_abort_request(server, req, -EIO);
+						return -EIO;
+					}
+				}
+#ifdef CONFIG_NCPFS_PACKET_SIGNING				
+				if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) {
+					if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) {
+						printk(KERN_ERR "ncpfs: tcp: Signature violation\n");
+						__ncp_abort_request(server, req, -EIO);
+						return -EIO;
+					}
+				}
+#endif				
+				ncp_finish_request(req, req->datalen);
+			nextreq:;
+				__ncp_next_request(server);
+			case 2:
+			next:;
+				server->rcv.ptr = (unsigned char*)&server->rcv.buf;
+				server->rcv.len = 10;
+				server->rcv.state = 0;
+				break;
+			case 3:
+				ncp_finish_request(server->rcv.creq, -EIO);
+				goto nextreq;
+			case 5:
+				info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len);
+				goto next;
 		}
-		dataread += result;
-		buffer += result;
-		len -= result;
 	}
-	return 0;
-}	
+}
 
-#define NCP_TCP_XMIT_MAGIC	(0x446D6454)
-#define NCP_TCP_XMIT_VERSION	(1)
-#define NCP_TCP_RCVD_MAGIC	(0x744E6350)
+void ncp_tcp_rcv_proc(void *s) {
+	mm_segment_t fs;
+	struct ncp_server *server = s;
+
+	fs = get_fs();
+	set_fs(get_ds());
+	down(&server->rcv.creq_sem);
+	__ncptcp_rcv_proc(server);
+	up(&server->rcv.creq_sem);
+	set_fs(fs);
+	return;
+}
 
-static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
+void ncp_tcp_tx_proc(void *s) {
+	mm_segment_t fs;
+	struct ncp_server *server = s;
+	
+	fs = get_fs();
+	set_fs(get_ds());
+	down(&server->rcv.creq_sem);
+	__ncptcp_try_send(server);
+	up(&server->rcv.creq_sem);
+	set_fs(fs);
+	return;
+}
+
+static int do_ncp_rpc_call(struct ncp_server *server, int size,
 		struct ncp_reply_header* reply_buf, int max_reply_size)
 {
-	struct file *file;
-	struct socket *sock;
 	int result;
-	struct iovec iov[2];
-	struct msghdr msg;
-	struct scm_cookie scm;
-	__u32 ncptcp_rcvd_hdr[2];
-	__u32 ncptcp_xmit_hdr[4];
-	int   datalen;
+	struct ncp_request_reply req;
 
-	/* We have to check the result, so store the complete header */
-	struct ncp_request_header request =
-	*((struct ncp_request_header *) (server->packet));
+	ncp_init_req(&req);
+	req.reply_buf = reply_buf;
+	req.datalen = max_reply_size;
+	req.tx_iov[1].iov_base = (void *) server->packet;
+	req.tx_iov[1].iov_len = size;
+	req.tx_iovlen = 1;
+	req.tx_totallen = size;
+	req.tx_type = *(u_int16_t*)server->packet;
 
-	file = server->ncp_filp;
-	sock = SOCKET_I(file->f_dentry->d_inode);
-	
-	ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC);
-	ncptcp_xmit_hdr[1] = htonl(size + 16);
-	ncptcp_xmit_hdr[2] = htonl(NCP_TCP_XMIT_VERSION);
-	ncptcp_xmit_hdr[3] = htonl(max_reply_size + 8);
-
-	DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
-		 "seq: %d",
-		 request.type,
-		 (request.conn_high << 8) + request.conn_low,
-		 request.sequence);
-	DDPRINTK(" func: %d\n",
-		 request.function);
-
-	iov[1].iov_base = (void *) server->packet;
-	iov[1].iov_len = size;
-	iov[0].iov_base = ncptcp_xmit_hdr;
-	iov[0].iov_len = 16;
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_control = NULL;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 2;
-	msg.msg_flags = MSG_NOSIGNAL;
-
-	result = scm_send(sock, &msg, &scm);
-	if (result < 0) {
-		return result;
-	}
-	result = sock->ops->sendmsg(sock, &msg, size + 16, &scm);
-	scm_destroy(&scm);
+	result = ncp_add_request(server, &req);
 	if (result < 0) {
-		printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result);
 		return result;
 	}
-rstrcv:
-	result = do_tcp_rcv(server, ncptcp_rcvd_hdr, 8);
-	if (result)
-		return result;
-	if (ncptcp_rcvd_hdr[0] != htonl(NCP_TCP_RCVD_MAGIC)) {
-		printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(ncptcp_rcvd_hdr[0]));
-		return -EIO;
-	}
-	datalen = ntohl(ncptcp_rcvd_hdr[1]);
-	if (datalen < 8 + sizeof(*reply_buf) || datalen > max_reply_size + 8) {
-		printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen);
-		return -EIO;
+	if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) {
+		ncp_abort_request(server, &req, -EIO);
 	}
-	datalen -= 8;
-	result = do_tcp_rcv(server, reply_buf, datalen);
-	if (result)
-		return result;
-	if (reply_buf->type != NCP_REPLY) {
-		DDPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", reply_buf->type);
-		goto rstrcv;
-	}
-	if (request.type == NCP_ALLOC_SLOT_REQUEST)
-		return datalen;
-	if (reply_buf->sequence != request.sequence) {
-		printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n");
-		return -EIO;
-	}
-	if ((reply_buf->conn_low != request.conn_low) ||
-	    (reply_buf->conn_high != request.conn_high)) {
-		printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n");
-		return -EIO;
-	}
-	return datalen;
+	return req.result;
 }
 
 /*
@@ -426,8 +728,6 @@
 static int ncp_do_request(struct ncp_server *server, int size,
 		void* reply, int max_reply_size)
 {
-	struct file *file;
-	struct socket *sock;
 	int result;
 
 	if (server->lock == 0) {
@@ -435,21 +735,10 @@
 		return -EIO;
 	}
 	if (!ncp_conn_valid(server)) {
+		printk(KERN_ERR "ncpfs: Connection invalid!\n");
 		return -EIO;
 	}
-#ifdef CONFIG_NCPFS_PACKET_SIGNING
-	if (server->sign_active)
 	{
-		sign_packet(server, &size);
-	}
-#endif /* CONFIG_NCPFS_PACKET_SIGNING */
-	file = server->ncp_filp;
-	sock = SOCKET_I(file->f_dentry->d_inode);
-	/* N.B. this isn't needed ... check socket type? */
-	if (!sock) {
-		printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n");
-		result = -EBADF;
-	} else {
 		mm_segment_t fs;
 		sigset_t old_set;
 		unsigned long mask, flags;
@@ -478,10 +767,7 @@
 		fs = get_fs();
 		set_fs(get_ds());
 
-		if (sock->type == SOCK_STREAM)
-			result = do_ncp_tcp_rpc_call(server, size, reply, max_reply_size);
-		else
-			result = do_ncp_rpc_call(server, size, reply, max_reply_size);
+		result = do_ncp_rpc_call(server, size, reply, max_reply_size);
 
 		set_fs(fs);
 
@@ -510,20 +796,13 @@
 {
 	struct ncp_request_header *h;
 	struct ncp_reply_header* reply = rpl;
-	int request_size = server->current_size
-			 - sizeof(struct ncp_request_header);
 	int result;
 
 	h = (struct ncp_request_header *) (server->packet);
 	if (server->has_subfunction != 0) {
-		*(__u16 *) & (h->data[0]) = htons(request_size - 2);
+		*(__u16 *) & (h->data[0]) = htons(server->current_size - sizeof(*h) - 2);
 	}
 	h->type = NCP_REQUEST;
-
-	server->sequence += 1;
-	h->sequence = server->sequence;
-	h->conn_low = (server->connection) & 0xff;
-	h->conn_high = ((server->connection) & 0xff00) >> 8;
 	/*
 	 * The server shouldn't know or care what task is making a
 	 * request, so we always use the same task number.
@@ -531,7 +810,7 @@
 	h->task = 2; /* (current->pid) & 0xff; */
 	h->function = function;
 
-	result = ncp_do_request(server, request_size + sizeof(*h), reply, size);
+	result = ncp_do_request(server, server->current_size, reply, size);
 	if (result < 0) {
 		DPRINTK("ncp_request_error: %d\n", result);
 		goto out;
@@ -554,20 +833,17 @@
 	struct ncp_request_header *h;
 	int result;
 
+	server->connection = 0xFFFF;
+	server->sequence = 255;
+
 	h = (struct ncp_request_header *) (server->packet);
 	h->type = NCP_ALLOC_SLOT_REQUEST;
-
-	server->sequence = 0;
-	h->sequence	= server->sequence;
-	h->conn_low	= 0xff;
-	h->conn_high	= 0xff;
 	h->task		= 2; /* see above */
 	h->function	= 0;
 
 	result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size);
 	if (result < 0)
 		goto out;
-	server->sequence = 0;
 	server->connection = h->conn_low + (h->conn_high * 256);
 	result = 0;
 out:
@@ -580,11 +856,6 @@
 
 	h = (struct ncp_request_header *) (server->packet);
 	h->type = NCP_DEALLOC_SLOT_REQUEST;
-
-	server->sequence += 1;
-	h->sequence	= server->sequence;
-	h->conn_low	= (server->connection) & 0xff;
-	h->conn_high	= ((server->connection) & 0xff00) >> 8;
 	h->task		= 2; /* see above */
 	h->function	= 0;
 
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Sat Sep 21 21:25:45 2002
+++ b/fs/partitions/check.c	Sat Sep 21 21:25:45 2002
@@ -286,6 +286,8 @@
 
 #ifdef CONFIG_DEVFS_FS
 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
+static devfs_handle_t cdroms;
+static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
 #endif
 
 static void devfs_create_partitions(struct gendisk *dev)
@@ -333,6 +335,47 @@
 #endif
 }
 
+static void devfs_create_cdrom(struct gendisk *dev)
+{
+#ifdef CONFIG_DEVFS_FS
+	int pos = 0;
+	devfs_handle_t dir, slave;
+	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
+	char dirname[64], symlink[16];
+	char vname[23];
+
+	if (!cdroms)
+		cdroms = devfs_mk_dir (NULL, "cdroms", NULL);
+
+	dev->number = devfs_alloc_unique_number(&cdrom_numspace);
+	sprintf(vname, "cdroms/cdrom%d", dev->number);
+	if (dev->de) {
+		int pos;
+		devfs_handle_t slave;
+		char rname[64];
+
+		dev->disk_de = devfs_register(dev->de, "cd", DEVFS_FL_DEFAULT,
+				     dev->major, dev->first_minor,
+				     S_IFBLK | S_IRUGO | S_IWUGO,
+				     dev->fops, NULL);
+
+		pos = devfs_generate_path(dev->disk_de, rname+3, sizeof(rname)-3);
+		if (pos >= 0) {
+			strncpy(rname + pos, "../", 3);
+			devfs_mk_symlink(devfs_handle, vname,
+					 DEVFS_FL_DEFAULT,
+					 rname + pos, &slave, NULL);
+			devfs_auto_unregister(dev->de, slave);
+		}
+	} else {
+		dev->disk_de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
+				    dev->major, dev->first_minor,
+				    S_IFBLK | S_IRUGO | S_IWUGO,
+				    dev->fops, NULL);
+	}
+#endif
+}
+
 static void devfs_remove_partitions(struct gendisk *dev)
 {
 #ifdef CONFIG_DEVFS_FS
@@ -343,7 +386,10 @@
 	}
 	devfs_unregister(dev->disk_de);
 	dev->disk_de = NULL;
-	devfs_dealloc_unique_number(&disc_numspace, dev->number);
+	if (dev->flags & GENHD_FL_CD)
+		devfs_dealloc_unique_number(&cdrom_numspace, dev->number);
+	else
+		devfs_dealloc_unique_number(&disc_numspace, dev->number);
 #endif
 }
 
@@ -367,6 +413,9 @@
 
 	set_capacity(disk, size);
 
+	if (disk->flags & GENHD_FL_CD)
+		devfs_create_cdrom(disk);
+
 	/* No minors to use for partitions */
 	if (!disk->minor_shift)
 		return;
@@ -503,4 +552,48 @@
 		kfree(disk->part);
 		disk->part = NULL;
 	}
+}
+
+struct dev_name {
+	struct list_head list;
+	dev_t dev;
+	char namebuf[64];
+	char *name;
+};
+
+static LIST_HEAD(device_names);
+
+char *partition_name(dev_t dev)
+{
+	struct gendisk *hd;
+	static char nomem [] = "<nomem>";
+	struct dev_name *dname;
+	struct list_head *tmp;
+
+	list_for_each(tmp, &device_names) {
+		dname = list_entry(tmp, struct dev_name, list);
+		if (dname->dev == dev)
+			return dname->name;
+	}
+
+	dname = kmalloc(sizeof(*dname), GFP_KERNEL);
+
+	if (!dname)
+		return nomem;
+	/*
+	 * ok, add this new device name to the list
+	 */
+	hd = get_gendisk(to_kdev_t(dev));
+	dname->name = NULL;
+	if (hd)
+		dname->name = disk_name(hd, MINOR(dev)-hd->first_minor, dname->namebuf);
+	if (!dname->name) {
+		sprintf(dname->namebuf, "[dev %s]", kdevname(to_kdev_t(dev)));
+		dname->name = dname->namebuf;
+	}
+
+	dname->dev = dev;
+	list_add(&dname->list, &device_names);
+
+	return dname->name;
 }
diff -Nru a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
--- a/fs/udf/lowlevel.c	Sat Sep 21 21:25:46 2002
+++ b/fs/udf/lowlevel.c	Sat Sep 21 21:25:46 2002
@@ -78,13 +78,10 @@
 
 	if (ret) /* Hard Disk */
 	{
-		ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock);
-
-		if (!ret && lblock != 0x7FFFFFFF)
-			lblock = ((512 * lblock) / sb->s_blocksize);
+		lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
 	}
 
-	if (!ret && lblock)
+	if (lblock)
 		return lblock - 1;
 	else
 		return 0;
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/hardirq.h	Sat Sep 21 21:25:45 2002
@@ -83,6 +83,7 @@
 #define hardirq_trylock()	(!in_interrupt())
 #define hardirq_endlock()	do { } while (0)
 
+#define in_atomic()		(preempt_count() != 0)
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
 #if CONFIG_PREEMPT
diff -Nru a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
--- a/include/asm-ia64/ide.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/ide.h	Sat Sep 21 21:25:45 2002
@@ -90,20 +90,6 @@
 #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))
-
-/*
- * The following are not needed for the non-m68k ports
- */
-#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 /* __ASM_IA64_IDE_H */
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	Sat Sep 21 21:25:43 2002
+++ b/include/asm-ia64/machvec.h	Sat Sep 21 21:25:43 2002
@@ -86,12 +86,10 @@
 #  define platform_setup	ia64_mv.setup
 #  define platform_cpu_init	ia64_mv.cpu_init
 #  define platform_irq_init	ia64_mv.irq_init
-#  define platform_map_nr	ia64_mv.map_nr
 #  define platform_mca_init	ia64_mv.mca_init
 #  define platform_mca_handler	ia64_mv.mca_handler
 #  define platform_cmci_handler	ia64_mv.cmci_handler
 #  define platform_log_print	ia64_mv.log_print
-#  define platform_pci_fixup	ia64_mv.pci_fixup
 #  define platform_send_ipi	ia64_mv.send_ipi
 #  define platform_global_tlb_purge	ia64_mv.global_tlb_purge
 #  define platform_pci_dma_init		ia64_mv.dma_init
@@ -159,8 +157,6 @@
 	platform_setup,				\
 	platform_cpu_init,			\
 	platform_irq_init,			\
-	platform_pci_fixup,			\
-	platform_map_nr,			\
 	platform_mca_init,			\
 	platform_mca_handler,			\
 	platform_cmci_handler,			\
@@ -236,9 +232,6 @@
 #endif
 #ifndef platform_log_print
 # define platform_log_print	((ia64_mv_log_print_t *) machvec_noop)
-#endif
-#ifndef platform_pci_fixup
-# define platform_pci_fixup	((ia64_mv_pci_fixup_t *) machvec_noop)
 #endif
 #ifndef platform_send_ipi
 # define platform_send_ipi	ia64_send_ipi	/* default to architected version */
diff -Nru a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h
--- a/include/asm-ia64/machvec_dig.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/machvec_dig.h	Sat Sep 21 21:25:45 2002
@@ -16,7 +16,5 @@
 #define platform_name		"dig"
 #define platform_setup		dig_setup
 #define platform_irq_init	dig_irq_init
-#define platform_pci_fixup	iosapic_pci_fixup
-#define platform_map_nr		map_nr_dense
 
 #endif /* _ASM_IA64_MACHVEC_DIG_h */
diff -Nru a/include/asm-ia64/machvec_hpsim.h b/include/asm-ia64/machvec_hpsim.h
--- a/include/asm-ia64/machvec_hpsim.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/machvec_hpsim.h	Sat Sep 21 21:25:45 2002
@@ -15,6 +15,5 @@
 #define platform_name		"hpsim"
 #define platform_setup		hpsim_setup
 #define platform_irq_init	hpsim_irq_init
-#define platform_map_nr		map_nr_dense
 
 #endif /* _ASM_IA64_MACHVEC_HPSIM_h */
diff -Nru a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
--- a/include/asm-ia64/machvec_hpzx1.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/machvec_hpzx1.h	Sat Sep 21 21:25:45 2002
@@ -22,8 +22,6 @@
  */
 #define platform_name			"hpzx1"
 #define platform_setup			dig_setup
-#define platform_pci_fixup		hpzx1_pci_fixup
-#define platform_map_nr			map_nr_dense
 #define platform_pci_dma_init		((ia64_mv_pci_dma_init *) machvec_noop)
 #define platform_pci_alloc_consistent	sba_alloc_consistent
 #define platform_pci_free_consistent	sba_free_consistent
diff -Nru a/include/asm-ia64/machvec_sn1.h b/include/asm-ia64/machvec_sn1.h
--- a/include/asm-ia64/machvec_sn1.h	Sat Sep 21 21:25:46 2002
+++ b/include/asm-ia64/machvec_sn1.h	Sat Sep 21 21:25:46 2002
@@ -68,10 +68,8 @@
 #define platform_setup		sn1_setup
 #define platform_cpu_init	sn_cpu_init
 #define platform_irq_init	sn1_irq_init
-#define platform_map_nr		sn1_map_nr
 #define platform_send_ipi	sn1_send_IPI
 #define platform_global_tlb_purge       sn1_global_tlb_purge
-#define platform_pci_fixup	sn1_pci_fixup
 #define platform_inb		sn1_inb
 #define platform_inw		sn1_inw
 #define platform_inl		sn1_inl
diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
--- a/include/asm-ia64/machvec_sn2.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/machvec_sn2.h	Sat Sep 21 21:25:45 2002
@@ -73,10 +73,8 @@
 #define platform_setup		sn1_setup
 #define platform_cpu_init	sn_cpu_init
 #define platform_irq_init	sn1_irq_init
-#define platform_map_nr		sn2_map_nr
 #define platform_send_ipi	sn2_send_IPI
 #define platform_global_tlb_purge       sn2_global_tlb_purge
-#define platform_pci_fixup	sn1_pci_fixup
 #ifdef Colin /* We are using the same is Generic IA64 calls defined in io.h */
 #define platform_inb		sn1_inb
 #define platform_inw		sn1_inw
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/mmu_context.h	Sat Sep 21 21:25:45 2002
@@ -110,6 +110,10 @@
 	rr2 = rr0 + 2*rid_incr;
 	rr3 = rr0 + 3*rid_incr;
 	rr4 = rr0 + 4*rid_incr;
+#ifdef  CONFIG_HUGETLB_PAGE
+	rr4 = (rr4 & (~(0xfcUL))) | (HPAGE_SHIFT << 2);
+#endif
+
 	ia64_set_rr(0x0000000000000000, rr0);
 	ia64_set_rr(0x2000000000000000, rr1);
 	ia64_set_rr(0x4000000000000000, rr2);
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
--- a/include/asm-ia64/page.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/page.h	Sat Sep 21 21:25:45 2002
@@ -30,6 +30,32 @@
 #define PAGE_MASK		(~(PAGE_SIZE - 1))
 #define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+#ifdef CONFIG_HUGETLB_PAGE
+
+# if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB)
+#  define HPAGE_SHIFT	32
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB)
+#  define HPAGE_SHIFT	28
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
+#  define HPAGE_SHIFT	26
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_16MB)
+#  define HPAGE_SHIFT	24
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#  define HPAGE_SHIFT	22
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
+#  define HPAGE_SHIFT	20
+# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256KB)
+#  define HPAGE_SHIFT	18
+# else
+#  error Unsupported IA-64 HugeTLB Page Size!
+# endif
+
+# define REGION_HPAGE	(4UL)	/* note: this is hardcoded in mmu_context.h:reload_context()!*/
+# define REGION_SHIFT	61
+# define HPAGE_SIZE	(__IA64_UL_CONST(1) << HPAGE_SHIFT)
+# define HPAGE_MASK	(~(HPAGE_SIZE - 1))
+#endif /* CONFIG_HUGETLB_PAGE */
+
 #ifdef __ASSEMBLY__
 # define __pa(x)		((x) - PAGE_OFFSET)
 # define __va(x)		((x) + PAGE_OFFSET)
@@ -86,6 +112,12 @@
 
 #define REGION_SIZE		REGION_NUMBER(1)
 #define REGION_KERNEL		7
+
+#ifdef CONFIG_HUGETLB_PAGE
+# define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
+				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
+# define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#endif
 
 #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
 # define ia64_abort()	__builtin_trap()
diff -Nru a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
--- a/include/asm-ia64/pal.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/pal.h	Sat Sep 21 21:25:45 2002
@@ -78,6 +78,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/fpu.h>
 
 /*
  * Data types needed to pass information into PAL procedures and
@@ -649,12 +650,43 @@
 extern struct ia64_pal_retval ia64_pal_call_stacked (u64, u64, u64, u64);
 extern struct ia64_pal_retval ia64_pal_call_phys_static (u64, u64, u64, u64);
 extern struct ia64_pal_retval ia64_pal_call_phys_stacked (u64, u64, u64, u64);
+extern void ia64_save_scratch_fpregs (struct ia64_fpreg *);
+extern void ia64_load_scratch_fpregs (struct ia64_fpreg *);
 
-#define PAL_CALL(iprv,a0,a1,a2,a3)		iprv = ia64_pal_call_static(a0, a1, a2, a3, 0)
-#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3)	iprv = ia64_pal_call_static(a0, a1, a2, a3, 1)
-#define PAL_CALL_STK(iprv,a0,a1,a2,a3)		iprv = ia64_pal_call_stacked(a0, a1, a2, a3)
-#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3)		iprv = ia64_pal_call_phys_static(a0, a1, a2, a3)
-#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3)	iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3)
+#define PAL_CALL(iprv,a0,a1,a2,a3) do {			\
+	struct ia64_fpreg fr[6];			\
+	ia64_save_scratch_fpregs(fr);			\
+	iprv = ia64_pal_call_static(a0, a1, a2, a3, 0);	\
+	ia64_load_scratch_fpregs(fr);			\
+} while (0)
+
+#define PAL_CALL_IC_OFF(iprv,a0,a1,a2,a3) do {		\
+	struct ia64_fpreg fr[6];			\
+	ia64_save_scratch_fpregs(fr);			\
+	iprv = ia64_pal_call_static(a0, a1, a2, a3, 1);	\
+	ia64_load_scratch_fpregs(fr);			\
+} while (0)
+
+#define PAL_CALL_STK(iprv,a0,a1,a2,a3) do {		\
+	struct ia64_fpreg fr[6];			\
+	ia64_save_scratch_fpregs(fr);			\
+	iprv = ia64_pal_call_stacked(a0, a1, a2, a3);	\
+	ia64_load_scratch_fpregs(fr);			\
+} while (0)
+
+#define PAL_CALL_PHYS(iprv,a0,a1,a2,a3) do {			\
+	struct ia64_fpreg fr[6];				\
+	ia64_save_scratch_fpregs(fr);				\
+	iprv = ia64_pal_call_phys_static(a0, a1, a2, a3);	\
+	ia64_load_scratch_fpregs(fr);				\
+} while (0)
+
+#define PAL_CALL_PHYS_STK(iprv,a0,a1,a2,a3) do {		\
+	struct ia64_fpreg fr[6];				\
+	ia64_save_scratch_fpregs(fr);				\
+	iprv = ia64_pal_call_phys_stacked(a0, a1, a2, a3);	\
+	ia64_load_scratch_fpregs(fr);				\
+} while (0)
 
 typedef int (*ia64_pal_handler) (u64, ...);
 extern ia64_pal_handler ia64_pal;
diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
--- a/include/asm-ia64/perfmon.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/perfmon.h	Sat Sep 21 21:25:45 2002
@@ -45,6 +45,7 @@
  * PMC flags
  */
 #define PFM_REGFL_OVFL_NOTIFY	0x1	/* send notification on overflow */
+#define PFM_REGFL_RANDOM	0x2	/* randomize sampling periods    */
 
 /*
  * PMD/PMC/IBR/DBR return flags (ignored on input)
@@ -86,8 +87,10 @@
 	unsigned long	reg_short_reset;/* reset after counter overflow (small) */
 
 	unsigned long	reg_reset_pmds[4]; /* which other counters to reset on overflow */
+	unsigned long	reg_random_seed;   /* seed value when randomization is used */
+	unsigned long	reg_random_mask;   /* bitmask used to limit random value */
 
-	unsigned long   reserved[16];	/* for future use */
+	unsigned long   reserved[14];	/* for future use */
 } pfarg_reg_t;
 
 typedef struct {
@@ -132,28 +135,28 @@
 #define PFM_VERSION_MINOR(x)	((x) & 0xffff)
 
 /*
- * Entry header in the sampling buffer.
- * The header is directly followed with the PMDS saved in increasing index 
- * order: PMD4, PMD5, .... How many PMDs are present is determined by the 
- * user program during context creation.
+ * Entry header in the sampling buffer.  The header is directly followed
+ * with the PMDs saved in increasing index order: PMD4, PMD5, .... How
+ * many PMDs are present is determined by the user program during
+ * context creation.
  *
- * XXX: in this version of the entry, only up to 64 registers can be recorded
- * This should be enough for quite some time. Always check sampling format
- * before parsing entries!
+ * XXX: in this version of the entry, only up to 64 registers can be
+ * recorded. This should be enough for quite some time. Always check
+ * sampling format before parsing entries!
  *
- * Inn the case where multiple counters have overflowed at the same time, the 
- * rate field indicate the initial value of the first PMD, based on the index.
- * For instance, if PMD2 and PMD5 have ovewrflowed for this entry, the rate field
- * will show the initial value of PMD2.
+ * In the case where multiple counters overflow at the same time, the
+ * last_reset_value member indicates the initial value of the PMD with
+ * the smallest index.  For instance, if PMD2 and PMD5 have overflowed,
+ * the last_reset_value member contains the initial value of PMD2.
  */
 typedef struct {
-	int		pid;		/* identification of process */
-	int		cpu;		/* which cpu was used */
-	unsigned long	rate;		/* initial value of overflowed counter */
-	unsigned long	stamp;		/* timestamp */
-	unsigned long	ip;		/* where did the overflow interrupt happened */
-	unsigned long	regs;		/* bitmask of which registers overflowed */
-	unsigned long   period;		/* sampling period used by overflowed counter (smallest pmd index) */
+	int		pid;			/* identification of process */
+	int		cpu;			/* which cpu was used */
+	unsigned long	last_reset_value;	/* initial value of counter that overflowed */
+	unsigned long	stamp;			/* timestamp */
+	unsigned long	ip;			/* where did the overflow interrupt happened */
+	unsigned long	regs;			/* bitmask of which registers overflowed */
+	unsigned long   period;			/* unused */
 } perfmon_smpl_entry_t;
 
 extern int perfmonctl(pid_t pid, int cmd, void *arg, int narg);
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/processor.h	Sat Sep 21 21:25:45 2002
@@ -236,7 +236,15 @@
 	__u64 ssd;			/* IA32 stack selector descriptor */
 	__u64 old_k1;			/* old value of ar.k1 */
 	__u64 old_iob;			/* old IOBase value */
-# define INIT_THREAD_IA32	0, 0, 0x17800000037fULL, 0, 0, 0, 0, 0, 0,
+# define INIT_THREAD_IA32	.eflag =	0,			\
+				.fsr =		0,			\
+				.fcr =		0x17800000037fULL,	\
+				.fir =		0,			\
+				.fdr =		0,			\
+				.csd =		0,			\
+				.ssd =		0,			\
+				.old_k1 =	0,			\
+				.old_iob =	0,
 #else
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
@@ -248,7 +256,13 @@
 	atomic_t pfm_notifiers_check;	/* when >0, will cleanup ctx_notify_task in tasklist */
 	atomic_t pfm_owners_check;	/* when >0, will cleanup ctx_owner in tasklist */
 	void *pfm_smpl_buf_list;	/* list of sampling buffers to vfree */
-# define INIT_THREAD_PM		{0, }, {0, }, 0, NULL, {0}, {0}, NULL,
+# define INIT_THREAD_PM		.pmc =			{0, },	\
+				.pmd =			{0, },	\
+				.pfm_ovfl_block_reset =	0,	\
+				.pfm_context =		NULL,	\
+				.pfm_notifiers_check =	{ 0 },	\
+				.pfm_owners_check =	{ 0 },	\
+				.pfm_smpl_buf_list =	NULL,
 #else
 # define INIT_THREAD_PM
 #endif
@@ -258,16 +272,17 @@
 };
 
 #define INIT_THREAD {				\
-	flags:		0,			\
-	ksp:		0,			\
-	map_base:	DEFAULT_MAP_BASE,	\
-	task_size:	DEFAULT_TASK_SIZE,	\
-	siginfo:	0,			\
+	.flags =	0,			\
+	.ksp =		0,			\
+	.map_base =	DEFAULT_MAP_BASE,	\
+	.task_size =	DEFAULT_TASK_SIZE,	\
+	.siginfo =	0,			\
+	.last_fph_cpu =  0,			\
 	INIT_THREAD_IA32			\
 	INIT_THREAD_PM				\
-	dbr:		{0, },			\
-	ibr:		{0, },			\
-	fph:		{{{{0}}}, }		\
+	.dbr =		{0, },			\
+	.ibr =		{0, },			\
+	.fph =		{{{{0}}}, }		\
 }
 
 #define start_thread(regs,new_ip,new_sp) do {							\
diff -Nru a/include/asm-ia64/rse.h b/include/asm-ia64/rse.h
--- a/include/asm-ia64/rse.h	Sat Sep 21 21:25:48 2002
+++ b/include/asm-ia64/rse.h	Sat Sep 21 21:25:48 2002
@@ -37,9 +37,9 @@
 }
 
 /*
- * Calcuate the number of registers in the dirty partition starting at
- * BSPSTORE with a size of DIRTY bytes.  This isn't simply DIRTY
- * divided by eight because the 64th slot is used to store ar.rnat.
+ * Calculate the number of registers in the dirty partition starting at BSPSTORE and
+ * ending at BSP.  This isn't simply (BSP-BSPSTORE)/8 because every 64th slot stores
+ * ar.rnat.
  */
 static __inline__ unsigned long
 ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	Sat Sep 21 21:25:48 2002
+++ b/include/asm-ia64/sal.h	Sat Sep 21 21:25:48 2002
@@ -38,9 +38,12 @@
 
 # define SAL_CALL(result,args...) do {			\
 	unsigned long flags;				\
+	struct ia64_fpreg fr[6];                        \
+	ia64_save_scratch_fpregs(fr);                   \
 	spin_lock_irqsave(&sal_lock, flags);		\
 	__SAL_CALL(result,args);			\
 	spin_unlock_irqrestore(&sal_lock, flags);	\
+	ia64_load_scratch_fpregs(fr);                   \
 } while (0)
 
 #define SAL_SET_VECTORS			0x01000000
diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
--- a/include/asm-ia64/siginfo.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/siginfo.h	Sat Sep 21 21:25:45 2002
@@ -66,6 +66,7 @@
 			long _band;	/* POLL_IN, POLL_OUT, POLL_MSG (XPG requires a "long") */
 			int _fd;
 		} _sigpoll;
+
 		/* SIGPROF */
 		struct {
 			pid_t _pid;		/* which child */
diff -Nru a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h
--- a/include/asm-ia64/signal.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/signal.h	Sat Sep 21 21:25:45 2002
@@ -166,7 +166,6 @@
 
 #  include <asm/sigcontext.h>
 
-#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 #define HAVE_ARCH_SYS_PAUSE
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
--- a/include/asm-ia64/spinlock.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/spinlock.h	Sat Sep 21 21:25:45 2002
@@ -108,7 +108,8 @@
 } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_is_locked(x)	(*(volatile int *) (x) != 0)
 
 #define _raw_read_lock(rw)							\
 do {										\
diff -Nru a/include/asm-ia64/suspend.h b/include/asm-ia64/suspend.h
--- a/include/asm-ia64/suspend.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/suspend.h	Sat Sep 21 21:25:45 2002
@@ -0,0 +1 @@
+/* dummy (must be non-empty to prevent prejudicial removal...) */
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/system.h	Sat Sep 21 21:25:45 2002
@@ -148,8 +148,8 @@
 			      "cmp.ne p6,p7=%1,r0;;"				\
 			      "(p6) ssm psr.i;"					\
 			      "(p7) rsm psr.i;;"				\
-			      "srlz.d"						\
-			      : "=&r" (old_psr) : "r"((psr) & IA64_PSR_I)	\
+			      "(p6) srlz.d"					\
+			      : "=r" (old_psr) : "r"((psr) & IA64_PSR_I)	\
 			      : "p6", "p7", "memory");				\
 	if ((old_psr & IA64_PSR_I) && !(psr & IA64_PSR_I)) {			\
 		__asm__ ("mov %0=ip" : "=r"(ip));				\
@@ -174,6 +174,13 @@
 #define local_irq_enable()	__asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory")
 #define local_save_flags(flags)	__asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory")
 
+#define irqs_disabled()				\
+({						\
+	unsigned long flags;			\
+	local_save_flags(flags);		\
+	(flags & IA64_PSR_I) == 0;		\
+})
+
 /*
  * Force an unresolved reference if someone tries to use
  * ia64_fetch_and_add() with a bad value.
@@ -367,14 +374,14 @@
 extern void ia64_save_extra (struct task_struct *task);
 extern void ia64_load_extra (struct task_struct *task);
 
-#if defined(CONFIG_SMP) && defined(CONFIG_PERFMON)
+#ifdef CONFIG_PERFMON
   DECLARE_PER_CPU(int, pfm_syst_wide);
 # define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_wide) != 0)
 #else
 # define PERFMON_IS_SYSWIDE() (0)
 #endif
 
-#define __switch_to(prev,next,last) do {							\
+#define __switch_to(prev,next,last) do {						\
 	if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
 	    || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE())		\
 		ia64_save_extra(prev);							\
diff -Nru a/include/asm-ia64/timex.h b/include/asm-ia64/timex.h
--- a/include/asm-ia64/timex.h	Sat Sep 21 21:25:48 2002
+++ b/include/asm-ia64/timex.h	Sat Sep 21 21:25:48 2002
@@ -3,14 +3,18 @@
 
 /*
  * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 /*
  * 2001/01/18 davidm	Removed CLOCK_TICK_RATE.  It makes no sense on IA-64.
  *			Also removed cacheflush_time as it's entirely unused.
  */
 
+#include <asm/processor.h>
+
 typedef unsigned long cycles_t;
+
+#define CLOCK_TICK_RATE		100000000
 
 static inline cycles_t
 get_cycles (void)
diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
--- a/include/asm-ia64/tlb.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/tlb.h	Sat Sep 21 21:25:45 2002
@@ -81,7 +81,7 @@
 		 */
 		flush_tlb_mm(tlb->mm);
 	} else if (unlikely (end - start >= 1024*1024*1024*1024UL
-		      || REGION_NUMBER(start) != REGION_NUMBER(end - 1)))
+			     || REGION_NUMBER(start) != REGION_NUMBER(end - 1)))
 	{
 		/*
 		 * If we flush more than a tera-byte or across regions, we're probably
@@ -198,5 +198,9 @@
 
 #define tlb_start_vma(tlb, vma)			do { } while (0)
 #define tlb_end_vma(tlb, vma)			do { } while (0)
+
+#define tlb_remove_tlb_entry(tlb, ptep, addr)	__tlb_remove_tlb_entry(tlb, ptep, addr)
+#define pte_free_tlb(tlb, ptep)			__pte_free_tlb(tlb, ptep)
+#define pmd_free_tlb(tlb, ptep)			__pmd_free_tlb(tlb, ptep)
 
 #endif /* _ASM_IA64_TLB_H */
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Sat Sep 21 21:25:45 2002
+++ b/include/asm-ia64/unistd.h	Sat Sep 21 21:25:45 2002
@@ -225,7 +225,7 @@
 #define __NR_security			1233
 #define __NR_alloc_hugepages		1234
 #define __NR_free_hugepages		1235
-/* 1236 currently unused */
+#define __NR_exit_group			1236
 /* 1237 currently unused */
 #define __NR_io_setup			1238
 #define __NR_io_destroy			1239
diff -Nru a/include/linux/blkpg.h b/include/linux/blkpg.h
--- a/include/linux/blkpg.h	Sat Sep 21 21:25:45 2002
+++ b/include/linux/blkpg.h	Sat Sep 21 21:25:45 2002
@@ -56,7 +56,7 @@
 
 #ifdef __KERNEL__
 
-extern char * partition_name(kdev_t dev);
+extern char * partition_name(dev_t dev);
 extern int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg);
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h
--- a/include/linux/cdrom.h	Sat Sep 21 21:25:43 2002
+++ b/include/linux/cdrom.h	Sat Sep 21 21:25:43 2002
@@ -730,9 +730,7 @@
 	struct cdrom_device_ops  *ops;  /* link to device_ops */
 	struct cdrom_device_info *next; /* next device_info for this major */
 	void *handle;		        /* driver-dependent data */
-	devfs_handle_t de;		/* real driver should create this  */
 	struct device cdrom_driverfs_dev; /* driverfs implementation */
-	int number;			/* generic driver updates this  */
 /* specifications */
         kdev_t dev;	                /* device number */
 	int mask;                       /* mask of capability: disables them */
@@ -786,18 +784,6 @@
 
 extern int register_cdrom(struct cdrom_device_info *cdi);
 extern int unregister_cdrom(struct cdrom_device_info *cdi);
-
-static inline void devfs_plain_cdrom(struct cdrom_device_info *cdi,
-				struct block_device_operations *ops)
-{
-	char vname[23];
-
-	sprintf (vname, "cdroms/cdrom%d", cdi->number);
-	cdi->de = devfs_register (NULL, vname, DEVFS_FL_DEFAULT,
-				    major(cdi->dev), minor(cdi->dev),
-				    S_IFBLK | S_IRUGO | S_IWUGO,
-				    ops, NULL);
-}
 
 typedef struct {
     int data;
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Sat Sep 21 21:25:45 2002
+++ b/include/linux/genhd.h	Sat Sep 21 21:25:45 2002
@@ -68,6 +68,7 @@
 #define GENHD_FL_REMOVABLE  1
 #define GENHD_FL_DRIVERFS  2
 #define GENHD_FL_DEVFS	4
+#define GENHD_FL_CD	8
 
 struct gendisk {
 	int major;			/* major number of driver */
@@ -80,6 +81,7 @@
 	struct gendisk *next;
 	struct block_device_operations *fops;
 	sector_t capacity;
+	struct list_head list;
 
 	int flags;
 	int number;			/* devfs crap */
@@ -90,7 +92,7 @@
 };
 
 /* drivers/block/genhd.c */
-extern void add_gendisk(struct gendisk *gp);
+extern void add_disk(struct gendisk *disk);
 extern void del_gendisk(struct gendisk *gp);
 extern void unlink_gendisk(struct gendisk *gp);
 extern struct gendisk *get_gendisk(kdev_t dev);
@@ -258,6 +260,9 @@
 
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
 extern void update_partition(struct gendisk *disk, int part);
+
+/* will go away */
+extern void blk_set_probe(int major, struct gendisk *(p)(int));
 
 static inline unsigned int disk_index (kdev_t dev)
 {
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Sat Sep 21 21:25:45 2002
+++ b/include/linux/ide.h	Sat Sep 21 21:25:45 2002
@@ -1072,6 +1072,8 @@
 	unsigned	highmem    : 1;	/* can do full 32-bit dma */
 	unsigned	no_dsc     : 1;	/* 0 default, 1 dsc_overlap disabled */
 
+	struct device	gendev;
+
 	void		*hwif_data;	/* extra hwif data */
 } ide_hwif_t;
 
@@ -1758,5 +1760,7 @@
 extern spinlock_t ide_lock;
 
 #define local_irq_set(flags)	do { local_save_flags((flags)); local_irq_enable(); } while (0)
+
+extern struct bus_type ide_bus_type;
 
 #endif /* _IDE_H */
diff -Nru a/include/linux/mii.h b/include/linux/mii.h
--- a/include/linux/mii.h	Sat Sep 21 21:25:43 2002
+++ b/include/linux/mii.h	Sat Sep 21 21:25:43 2002
@@ -118,10 +118,12 @@
 
 struct ethtool_cmd;
 
-int mii_link_ok (struct mii_if_info *mii);
-int mii_nway_restart (struct mii_if_info *mii);
-int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
-int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_link_ok (struct mii_if_info *mii);
+extern int mii_nway_restart (struct mii_if_info *mii);
+extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern void mii_check_link (struct mii_if_info *mii);
+extern unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print);
 
 
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h
--- a/include/linux/nbd.h	Sat Sep 21 21:25:48 2002
+++ b/include/linux/nbd.h	Sat Sep 21 21:25:48 2002
@@ -79,6 +79,7 @@
 	spinlock_t queue_lock;
 	struct list_head queue_head;	/* Requests are added here...			*/
 	struct semaphore tx_lock;
+	struct gendisk disk;
 };
 #endif
 
diff -Nru a/include/linux/ncp.h b/include/linux/ncp.h
--- a/include/linux/ncp.h	Sat Sep 21 21:25:43 2002
+++ b/include/linux/ncp.h	Sat Sep 21 21:25:43 2002
@@ -30,6 +30,7 @@
 };
 
 #define NCP_REPLY                (0x3333)
+#define NCP_WATCHDOG		 (0x3E3E)
 #define NCP_POSITIVE_ACK         (0x9999)
 
 struct ncp_reply_header {
diff -Nru a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
--- a/include/linux/ncp_fs_sb.h	Sat Sep 21 21:25:43 2002
+++ b/include/linux/ncp_fs_sb.h	Sat Sep 21 21:25:43 2002
@@ -13,6 +13,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/tqueue.h>
+
 #define NCP_DEFAULT_OPTIONS 0		/* 2 for packet signatures */
 
 struct ncp_server {
@@ -24,6 +26,9 @@
 	__u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
 
 	struct file *ncp_filp;	/* File pointer to ncp socket */
+	struct socket *ncp_sock;/* ncp socket */
+	struct file *info_filp;
+	struct socket *info_sock;
 
 	u8 sequence;
 	u8 task;
@@ -79,7 +84,53 @@
 
 	/* miscellaneous */
 	unsigned int flags;
+
+	spinlock_t requests_lock;	/* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */
+
+	void (*data_ready)(struct sock* sk, int len);
+	void (*error_report)(struct sock* sk);
+	void (*write_space)(struct sock* sk);	/* STREAM mode only */
+	struct {
+		struct tq_struct tq;		/* STREAM/DGRAM: data/error ready */
+		struct ncp_request_reply* creq;	/* STREAM/DGRAM: awaiting reply from this request */
+		struct semaphore creq_sem;	/* DGRAM only: lock accesses to rcv.creq */
+
+		unsigned int state;		/* STREAM only: receiver state */
+		struct {
+			__u32 magic __attribute__((packed));
+			__u32 len __attribute__((packed));
+			__u16 type __attribute__((packed));
+			__u16 p1 __attribute__((packed));
+			__u16 p2 __attribute__((packed));
+			__u16 p3 __attribute__((packed));
+			__u16 type2 __attribute__((packed));
+		} buf;				/* STREAM only: temporary buffer */
+		unsigned char* ptr;		/* STREAM only: pointer to data */
+		size_t len;			/* STREAM only: length of data to receive */
+	} rcv;
+	struct {
+		struct list_head requests;	/* STREAM only: queued requests */
+		struct tq_struct tq;		/* STREAM only: transmitter ready */
+		struct ncp_request_reply* creq;	/* STREAM only: currently transmitted entry */
+	} tx;
+	struct timer_list timeout_tm;		/* DGRAM only: timeout timer */
+	struct tq_struct timeout_tq;		/* DGRAM only: associated queue, we run timers from process context */
+	int timeout_last;			/* DGRAM only: current timeout length */
+	int timeout_retries;			/* DGRAM only: retries left */
+	struct {
+		size_t len;
+		__u8 data[128];
+	} unexpected_packet;
 };
+
+extern void ncp_tcp_rcv_proc(void *server);
+extern void ncp_tcp_tx_proc(void *server);
+extern void ncpdgram_rcv_proc(void *server);
+extern void ncpdgram_timeout_proc(void *server);
+extern void ncpdgram_timeout_call(unsigned long server);
+extern void ncp_tcp_data_ready(struct sock* sk, int len);
+extern void ncp_tcp_write_space(struct sock* sk);
+extern void ncp_tcp_error_report(struct sock* sk);
 
 #define NCP_FLAG_UTF8	1
 
diff -Nru a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h
--- a/include/linux/ncp_mount.h	Sat Sep 21 21:25:48 2002
+++ b/include/linux/ncp_mount.h	Sat Sep 21 21:25:48 2002
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <linux/ncp.h>
 
-#define NCP_MOUNT_VERSION 3
+#define NCP_MOUNT_VERSION 3	/* Binary */
 
 /* Values for flags */
 #define NCP_MOUNT_SOFT		0x0001
@@ -41,7 +41,7 @@
 	__kernel_mode_t dir_mode;
 };
 
-#define NCP_MOUNT_VERSION_V4	(4)
+#define NCP_MOUNT_VERSION_V4	(4)	/* Binary or text */
 
 struct ncp_mount_data_v4 {
 	int version;
@@ -66,6 +66,8 @@
 	unsigned long dir_mode;
 };
 
+#define NCP_MOUNT_VERSION_V5	(5)	/* Text only */
+
 #ifdef __KERNEL__
 
 struct ncp_mount_data_kernel {
@@ -83,6 +85,7 @@
 	__kernel_gid32_t gid;
 	__kernel_mode_t  file_mode;
 	__kernel_mode_t  dir_mode;
+	int		 info_fd;
 };
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	Sat Sep 21 21:25:45 2002
+++ b/include/linux/raid/md.h	Sat Sep 21 21:25:45 2002
@@ -62,10 +62,9 @@
 
 extern int md_size[MAX_MD_DEVS];
 
-extern char * partition_name (kdev_t dev);
 extern inline char * bdev_partition_name (struct block_device *bdev)
 {
-	return partition_name(bdev ? to_kdev_t(bdev->bd_dev) : NODEV);
+	return partition_name(bdev ? bdev->bd_dev : 0);
 }
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
--- a/include/linux/raid/md_k.h	Sat Sep 21 21:25:45 2002
+++ b/include/linux/raid/md_k.h	Sat Sep 21 21:25:45 2002
@@ -299,16 +299,6 @@
 
 #define THREAD_WAKEUP  0
 
-#define MAX_DISKNAME_LEN 64
-
-typedef struct dev_name_s {
-	struct list_head list;
-	kdev_t dev;
-	char namebuf [MAX_DISKNAME_LEN];
-	char *name;
-} dev_name_t;
-
-
 #define __wait_event_lock_irq(wq, condition, lock) 			\
 do {									\
 	wait_queue_t __wait;						\
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sat Sep 21 21:25:43 2002
+++ b/kernel/ksyms.c	Sat Sep 21 21:25:43 2002
@@ -576,7 +576,7 @@
 EXPORT_SYMBOL(fasync_helper);
 EXPORT_SYMBOL(kill_fasync);
 
-EXPORT_SYMBOL(disk_name);	/* for md.c */
+EXPORT_SYMBOL(partition_name);
 
 /* binfmt_aout */
 EXPORT_SYMBOL(get_write_access);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Sat Sep 21 21:25:48 2002
+++ b/kernel/sched.c	Sat Sep 21 21:25:48 2002
@@ -940,8 +940,17 @@
 	struct list_head *queue;
 	int idx;
 
-	if (unlikely(in_atomic()))
-		BUG();
+	/*
+	 * Test if we are atomic.  Since do_exit() needs to call into
+	 * schedule() atomically, we ignore that path for now.
+	 * Otherwise, whine if we are scheduling when we should not be.
+	 */
+	if (likely(current->state != TASK_ZOMBIE)) {
+		if (unlikely(in_atomic())) {
+			printk(KERN_ERR "bad: scheduling while atomic!\n");
+			dump_stack();
+		}
+	}
 
 #if CONFIG_DEBUG_HIGHMEM
 	check_highmem_ptes();
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Sat Sep 21 21:25:45 2002
+++ b/kernel/sys.c	Sat Sep 21 21:25:45 2002
@@ -412,9 +412,10 @@
 
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
-		if(!software_suspend_enabled)
+		if (!software_suspend_enabled) {
+			unlock_kernel();
 			return -EAGAIN;
-		
+		}		
 		software_suspend();
 		do_exit(0);
 		break;
diff -Nru a/mm/numa.c b/mm/numa.c
--- a/mm/numa.c	Sat Sep 21 21:25:48 2002
+++ b/mm/numa.c	Sat Sep 21 21:25:48 2002
@@ -27,6 +27,7 @@
 {
 	unsigned long size;
 
+	pgdat = &contig_page_data;
 	contig_page_data.node_id = 0;
 	contig_page_data.node_start_pfn = node_start_pfn;
 	calculate_totalpages (&contig_page_data, zones_size, zholes_size);
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/af_irda.c	Sat Sep 21 21:25:45 2002
@@ -509,7 +509,7 @@
 	notify_t notify;
 
 	if (self->lsap) {
-		WARNING(__FUNCTION__ "(), busy!\n");
+		WARNING("%s(), busy!\n", __FUNCTION__);
 		return -EBUSY;
 	}
 
@@ -521,7 +521,7 @@
 
 	self->lsap = irlmp_open_lsap(LSAP_CONNLESS, &notify, pid);
 	if (self->lsap == NULL) {
-		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate LSAP!\n");
+		IRDA_DEBUG( 0, "%s(), Unable to allocate LSAP!\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -542,12 +542,12 @@
  */
 static int irda_find_lsap_sel(struct irda_sock *self, char *name)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "(%p, %s)\n", self, name);
+	IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name);
 
 	ASSERT(self != NULL, return -1;);
 
 	if (self->iriap) {
-		WARNING("%s: busy with a previous query\n", __FUNCTION__);
+		WARNING("%s(): busy with a previous query\n", __FUNCTION__);
 		return -EBUSY;
 	}
 
@@ -582,8 +582,8 @@
 	/* Get the remote TSAP selector */
 	switch (self->ias_result->type) {
 	case IAS_INTEGER:
-		IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n",
-			   self->ias_result->t.integer);
+		IRDA_DEBUG(4, "%s() int=%d\n",
+			   __FUNCTION__, self->ias_result->t.integer);
 
 		if (self->ias_result->t.integer != -1)
 			self->dtsap_sel = self->ias_result->t.integer;
@@ -592,7 +592,7 @@
 		break;
 	default:
 		self->dtsap_sel = 0;
-		IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n");
+		IRDA_DEBUG(0, "%s(), bad type!\n", __FUNCTION__);
 		break;
 	}
 	if (self->ias_result)
@@ -630,7 +630,7 @@
 	__u32	daddr = DEV_ADDR_ANY;	/* Address we found the service on */
 	__u8	dtsap_sel = 0x0;	/* TSAP associated with it */
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
+	IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name);
 
 	ASSERT(self != NULL, return -1;);
 
@@ -652,8 +652,8 @@
 		/* Try the address in the log */
 		self->daddr = discoveries[i].daddr;
 		self->saddr = 0x0;
-		IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n",
-			   self->daddr);
+		IRDA_DEBUG(1, "%s(), trying daddr = %08x\n",
+			   __FUNCTION__, self->daddr);
 
 		/* Query remote LM-IAS for this service */
 		err = irda_find_lsap_sel(self, name);
@@ -661,9 +661,8 @@
 		case 0:
 			/* We found the requested service */
 			if(daddr != DEV_ADDR_ANY) {
-				IRDA_DEBUG(1, __FUNCTION__
-					   "(), discovered service ''%s'' in two different devices !!!\n",
-					   name);
+				IRDA_DEBUG(1, "%s(), discovered service ''%s'' in two different devices !!!\n",
+					   __FUNCTION__, name);
 				self->daddr = DEV_ADDR_ANY;
 				kfree(discoveries);
 				return(-ENOTUNIQ);
@@ -677,8 +676,7 @@
 			break;
 		default:
 			/* Something bad did happen :-( */
-			IRDA_DEBUG(0, __FUNCTION__
-				   "(), unexpected IAS query failure\n");
+			IRDA_DEBUG(0, "%s(), unexpected IAS query failure\n", __FUNCTION__);
 			self->daddr = DEV_ADDR_ANY;
 			kfree(discoveries);
 			return(-EHOSTUNREACH);
@@ -690,9 +688,8 @@
 
 	/* Check out what we found */
 	if(daddr == DEV_ADDR_ANY) {
-		IRDA_DEBUG(1, __FUNCTION__
-			   "(), cannot discover service ''%s'' in any device !!!\n",
-			   name);
+		IRDA_DEBUG(1, "%s(), cannot discover service ''%s'' in any device !!!\n",
+			   __FUNCTION__, name);
 		self->daddr = DEV_ADDR_ANY;
 		return(-EADDRNOTAVAIL);
 	}
@@ -702,9 +699,8 @@
 	self->saddr = 0x0;
 	self->dtsap_sel = dtsap_sel;
 
-	IRDA_DEBUG(1, __FUNCTION__
-		   "(), discovered requested service ''%s'' at address %08x\n",
-		   name, self->daddr);
+	IRDA_DEBUG(1, "%s(), discovered requested service ''%s'' at address %08x\n",
+		   __FUNCTION__, name, self->daddr);
 
 	return 0;
 }
@@ -735,8 +731,8 @@
 		saddr.sir_addr = self->saddr;
 	}
 
-	IRDA_DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
-	IRDA_DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
+	IRDA_DEBUG(1, "%s(), tsap_sel = %#x\n", __FUNCTION__, saddr.sir_lsap_sel);
+	IRDA_DEBUG(1, "%s(), addr = %08x\n", __FUNCTION__, saddr.sir_addr);
 
 	/* uaddr_len come to us uninitialised */
 	*uaddr_len = sizeof (struct sockaddr_irda);
@@ -755,7 +751,7 @@
 {
 	struct sock *sk = sock->sk;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) &&
 	    (sk->type != SOCK_DGRAM))
@@ -786,7 +782,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self);
+	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
 
 	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
@@ -796,8 +792,7 @@
 	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA)) {
 		self->pid = addr->sir_lsap_sel;
 		if (self->pid & 0x80) {
-			IRDA_DEBUG(0, __FUNCTION__
-				   "(), extension in PID not supp!\n");
+			IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __FUNCTION__);
 			return -EOPNOTSUPP;
 		}
 		err = irda_open_lsap(self, self->pid);
@@ -842,7 +837,7 @@
 	struct sk_buff *skb;
 	int err;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
 	ASSERT(self != NULL, return -1;);
 
@@ -918,7 +913,7 @@
 	/* Now attach up the new socket */
 	new->tsap = irttp_dup(self->tsap, new);
 	if (!new->tsap) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
 		return -1;
 	}
 
@@ -977,7 +972,7 @@
 	struct irda_sock *self = irda_sk(sk);
 	int err;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(%p)\n", self);
+	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
 
 	/* Don't allow connect for Ultra sockets */
 	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA))
@@ -1007,19 +1002,18 @@
 		/* Try to find one suitable */
 		err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
 		if (err) {
-			IRDA_DEBUG(0, __FUNCTION__
-				   "(), auto-connect failed!\n");
+			IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __FUNCTION__);
 			return err;
 		}
 	} else {
 		/* Use the one provided by the user */
 		self->daddr = addr->sir_addr;
-		IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+		IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
 
 		/* Query remote LM-IAS */
 		err = irda_find_lsap_sel(self, addr->sir_name);
 		if (err) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+			IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
 			return err;
 		}
 	}
@@ -1037,7 +1031,7 @@
 				    self->saddr, self->daddr, NULL,
 				    self->max_sdu_size_rx, NULL);
 	if (err) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
 		return err;
 	}
 
diff -Nru a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
--- a/net/irda/ircomm/ircomm_core.c	Sat Sep 21 21:25:43 2002
+++ b/net/irda/ircomm/ircomm_core.c	Sat Sep 21 21:25:43 2002
@@ -63,7 +63,7 @@
 {
 	ircomm = hashbin_new(HB_LOCK); 
 	if (ircomm == NULL) {
-		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 	
diff -Nru a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
--- a/net/irda/ircomm/ircomm_lmp.c	Sat Sep 21 21:25:43 2002
+++ b/net/irda/ircomm/ircomm_lmp.c	Sat Sep 21 21:25:43 2002
@@ -228,7 +228,7 @@
         }
 	ret = irlmp_data_request(self->lsap, skb);
 	if (ret) {
-		ERROR(__FUNCTION__ "(), failed\n");
+		ERROR("%s(), failed\n", __FUNCTION__);
 		dev_kfree_skb(skb);
 	}
 
diff -Nru a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
--- a/net/irda/ircomm/ircomm_param.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/ircomm/ircomm_param.c	Sat Sep 21 21:25:45 2002
@@ -154,7 +154,7 @@
 	count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
 				  &ircomm_param_info);
 	if (count < 0) {
-		WARNING(__FUNCTION__ "(), no room for parameter!\n");
+		WARNING("%s(), no room for parameter!\n", __FUNCTION__);
 		spin_unlock_irqrestore(&self->spinlock, flags);
 		return -1;
 	}
diff -Nru a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
--- a/net/irda/ircomm/ircomm_ttp.c	Sat Sep 21 21:25:48 2002
+++ b/net/irda/ircomm/ircomm_ttp.c	Sat Sep 21 21:25:48 2002
@@ -146,7 +146,7 @@
 
 	ret = irttp_data_request(self->tsap, skb);
 	if (ret) {
-		ERROR(__FUNCTION__ "(), failed\n");
+		ERROR("%s(), failed\n", __FUNCTION__);
 		dev_kfree_skb(skb);
 	}
 
@@ -192,7 +192,7 @@
 	ASSERT(qos != NULL, return;);
 
 	if (max_sdu_size != TTP_SAR_DISABLE) {
-		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
 		dev_kfree_skb(skb);
 		return;
 	}
@@ -229,7 +229,7 @@
 	ASSERT(qos != NULL, return;);
 
 	if (max_sdu_size != TTP_SAR_DISABLE) {
-		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
 		dev_kfree_skb(skb);
 		return;
 	}
diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
--- a/net/irda/ircomm/ircomm_tty.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/ircomm/ircomm_tty.c	Sat Sep 21 21:25:45 2002
@@ -92,7 +92,7 @@
 {	
 	ircomm_tty = hashbin_new(HB_LOCK); 
 	if (ircomm_tty == NULL) {
-		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -135,7 +135,7 @@
 	driver.read_proc       = ircomm_tty_read_proc;
 #endif /* CONFIG_PROC_FS */
 	if (tty_register_driver(&driver)) {
-		ERROR(__FUNCTION__ "Couldn't register serial driver\n");
+		ERROR("%s(): Couldn't register serial driver\n", __FUNCTION__);
 		return -1;
 	}
 	return 0;
@@ -168,7 +168,7 @@
 
 	ret = tty_unregister_driver(&driver);
         if (ret) {
-                ERROR(__FUNCTION__ "(), failed to unregister driver\n");
+                ERROR("%s(), failed to unregister driver\n", __FUNCTION__);
 		return;
 	}
 
@@ -223,7 +223,7 @@
 	/* Connect IrCOMM link with remote device */
 	ret = ircomm_tty_attach_cable(self);
 	if (ret < 0) {
-		ERROR(__FUNCTION__ "(), error attaching cable!\n");
+		ERROR("%s(), error attaching cable!\n", __FUNCTION__);
 		return ret;
 	}
 
@@ -410,7 +410,7 @@
 		/* No, so make new instance */
 		self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
 		if (self == NULL) {
-			ERROR(__FUNCTION__"(), kmalloc failed!\n");
+			ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
 			MOD_DEC_USE_COUNT;
 			return -ENOMEM;
 		}
@@ -563,9 +563,8 @@
 	}
 
 	if (--self->open_count < 0) {
-		ERROR(__FUNCTION__ 
-		      "(), bad serial port count for ttys%d: %d\n",
-		      self->line, self->open_count);
+		ERROR("%s(), bad serial port count for ttys%d: %d\n",
+		      __FUNCTION__, self->line, self->open_count);
 		self->open_count = 0;
 	}
 	if (self->open_count) {
diff -Nru a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
--- a/net/irda/ircomm/ircomm_tty_attach.c	Sat Sep 21 21:25:48 2002
+++ b/net/irda/ircomm/ircomm_tty_attach.c	Sat Sep 21 21:25:48 2002
@@ -601,8 +601,7 @@
 		self->saddr = info->saddr;
 
 		if (self->iriap) {
-			WARNING(__FUNCTION__ 
-				"(), busy with a previous query\n");
+			WARNING("%s(), busy with a previous query\n", __FUNCTION__);
 			return -EBUSY;
 		}
 
@@ -659,8 +658,7 @@
 		self->saddr = info->saddr;
 
 		if (self->iriap) {
-			WARNING(__FUNCTION__ 
-				"(), busy with a previous query\n");
+			WARNING("%s(), busy with a previous query\n", __FUNCTION__);
 			return -EBUSY;
 		}
 		
@@ -728,8 +726,7 @@
 	switch (event) {
 	case IRCOMM_TTY_GOT_PARAMETERS:
 		if (self->iriap) {
-			WARNING(__FUNCTION__ 
-				"(), busy with a previous query\n");
+			WARNING("%s(), busy with a previous query\n", __FUNCTION__);
 			return -EBUSY;
 		}
 		
diff -Nru a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
--- a/net/irda/ircomm/ircomm_tty_ioctl.c	Sat Sep 21 21:25:43 2002
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c	Sat Sep 21 21:25:43 2002
@@ -95,7 +95,7 @@
 		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
 		/* This got me. Bummer. Jean II */
 		if (self->service_type == IRCOMM_3_WIRE_RAW)
-			WARNING(__FUNCTION__ "(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n");
+			WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__);
 	} else {
 		self->flags &= ~ASYNC_CTS_FLOW;
 		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
diff -Nru a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
--- a/net/irda/irlan/irlan_client.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/irlan/irlan_client.c	Sat Sep 21 21:25:45 2002
@@ -367,7 +367,7 @@
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
 	if (!skb) {
-		ERROR( __FUNCTION__ "(), Got NULL skb!\n");
+		ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
 		return;
 	}
 	frame = skb->data;
diff -Nru a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
--- a/net/irda/irlan/irlan_client_event.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/irlan/irlan_client_event.c	Sat Sep 21 21:25:45 2002
@@ -100,8 +100,7 @@
 	switch (event) {
 	case IRLAN_DISCOVERY_INDICATION:
 		if (self->client.iriap) {
-			WARNING(__FUNCTION__ 
-				"(), busy with a previous query\n");
+			WARNING("%s(), busy with a previous query\n", __FUNCTION__);
 			return -EBUSY;
 		}
 		
diff -Nru a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
--- a/net/irda/irlan/irlan_common.c	Sat Sep 21 21:25:45 2002
+++ b/net/irda/irlan/irlan_common.c	Sat Sep 21 21:25:45 2002
@@ -424,7 +424,7 @@
 		IRDA_DEBUG(2, __FUNCTION__ "(), IrLMP connect failed\n");
 		break;
 	default:
-		ERROR(__FUNCTION__ "(), Unknown disconnect reason\n");
+		ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
 		break;
 	}
 	
