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

diff -urN linux-2.4.23-bk13/Makefile linux-2.4.23-bk14/Makefile
--- linux-2.4.23-bk13/Makefile	2003-12-19 02:52:50.000000000 -0800
+++ linux-2.4.23-bk14/Makefile	2003-12-19 02:52:53.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 23
-EXTRAVERSION = -bk13
+EXTRAVERSION = -bk14
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/chrp_setup.c linux-2.4.23-bk14/arch/ppc64/kernel/chrp_setup.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/chrp_setup.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/chrp_setup.c	2003-12-19 02:52:56.000000000 -0800
@@ -82,6 +82,7 @@
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
 extern void openpic_init_IRQ(void);
+extern void openpic_init_irq_desc(irq_desc_t *);
 extern void init_ras_IRQ(void);
 
 extern void find_and_init_phbs(void);
@@ -264,10 +265,12 @@
 	ppc_md.setup_residual = NULL;
 	ppc_md.get_cpuinfo    = chrp_get_cpuinfo;
 	if(naca->interrupt_controller == IC_OPEN_PIC) {
-		ppc_md.init_IRQ       = openpic_init_IRQ; 
+		ppc_md.init_IRQ       = openpic_init_IRQ;
+		ppc_md.init_irq_desc  = openpic_init_irq_desc;
 		ppc_md.get_irq        = openpic_get_irq;
 	} else {
 		ppc_md.init_IRQ       = xics_init_IRQ;
+		ppc_md.init_irq_desc  = xics_init_irq_desc;
 		ppc_md.get_irq        = xics_get_irq;
 	}
 	ppc_md.init_ras_IRQ = init_ras_IRQ;
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/htab.c linux-2.4.23-bk14/arch/ppc64/kernel/htab.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/htab.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/htab.c	2003-12-19 02:52:56.000000000 -0800
@@ -1179,7 +1179,7 @@
                 "mr    5, %3\n"
                 "mr    6, %4\n"
                 "mr    7, %5\n"
-                HSC    
+		HVSC
                 "mr    %0, 3\n"
                 "mr    %1, 4\n"
 		: "=r" (lpar_rc), "=r" (slot)
@@ -1200,7 +1200,7 @@
 			      "mr    5, %3\n"
 			      "mr    6, %4\n"
 			      "mr    7, %5\n"
-			      HSC    
+			      HVSC
 			      "mr    %0, 3\n"
 			      "mr    %1, 4\n"
 			      : "=r" (lpar_rc), "=r" (slot)
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/i8259.c linux-2.4.23-bk14/arch/ppc64/kernel/i8259.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/i8259.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/i8259.c	2003-12-19 02:52:56.000000000 -0800
@@ -123,7 +123,8 @@
 
 static void i8259_end_irq(unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irqdesc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+	    irqdesc(irq)->action)
 		i8259_unmask_irq(irq);
 }
 
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/iSeries_irq.c linux-2.4.23-bk14/arch/ppc64/kernel/iSeries_irq.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/iSeries_irq.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/iSeries_irq.c	2003-12-19 02:52:56.000000000 -0800
@@ -70,15 +70,24 @@
 
 void iSeries_init_irqMap(int irq);
 
+void iSeries_init_irq_desc(irq_desc_t *desc)
+{
+	if (!desc->handler)
+		desc->handler = &iSeries_IRQ_handler;
+}
+
 /*  This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c */
 void __init iSeries_init_IRQ(void)
 {
 	int i;
+	irq_desc_t *desc;
+
 	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].handler = &iSeries_IRQ_handler;
-		irq_desc[i].status = 0;
-		irq_desc[i].status |= IRQ_DISABLED;
-		irq_desc[i].depth = 1;
+		desc = real_irqdesc(i);
+		desc->handler = &iSeries_IRQ_handler;
+		desc->status = 0;
+		desc->status |= IRQ_DISABLED;
+		desc->depth = 1;
 		iSeries_init_irqMap(i);
 	}
 	/* Register PCI event handler and open an event path */
@@ -117,6 +126,7 @@
 	u32 dsa = (busNumber << 16) | (subBusNumber << 8) | deviceId;
 	struct iSeries_irqEntry* newEntry;
 	unsigned long flags;
+	irq_desc_t *desc = irqdesc(irq);
 
 	if (irq < 0 || irq >= NR_IRQS) {
 		return -1;
@@ -132,7 +142,7 @@
 	* done during buswalk, but it should not hurt anything except a 
 	* little performance to be smp safe.
 	*******************************************************************/
-	spin_lock_irqsave(&irq_desc[irq].lock, flags);
+	spin_lock_irqsave(&desc->lock, flags);
 
 	if (iSeries_irqMap[irq].valid) {
 		/* Push the new element onto the irq stack */
@@ -147,7 +157,7 @@
 		kfree(newEntry);
 		rc = -1;
     }
-	spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 	return rc;
 }
 
@@ -179,10 +189,11 @@
 	int irq;
 	unsigned long flags;
 	for (irq=0; irq < NR_IRQS; irq++) {
-		spin_lock_irqsave(&irq_desc[irq].lock, flags);
-		irq_desc[irq].handler->startup(irq);
-		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
-    	}
+		irq_desc_t *desc = irqdesc(irq);
+		spin_lock_irqsave(&desc->lock, flags);
+		desc->handler->startup(irq);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
 /*  this is not called anywhere currently */
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/iSeries_setup.c linux-2.4.23-bk14/arch/ppc64/kernel/iSeries_setup.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/iSeries_setup.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.23-bk14/arch/ppc64/kernel/iSeries_setup.c	2003-12-19 02:52:56.000000000 -0800
@@ -63,6 +63,7 @@
 extern void iSeries_pcibios_init(void);
 extern void iSeries_pcibios_fixup(void);
 extern void iSeries_pcibios_fixup_bus(int);
+extern void iSeries_init_irq_desc(irq_desc_t *desc);
 
 /* Global Variables */
 
@@ -307,6 +308,7 @@
 	ppc_md.get_cpuinfo	 	= iSeries_get_cpuinfo;
 	ppc_md.irq_cannonicalize 	= NULL;
 	ppc_md.init_IRQ		 	= iSeries_init_IRQ;
+	ppc_md.init_irq_desc            = iSeries_init_irq_desc;
 	ppc_md.init_ras_IRQ		= NULL;
 	ppc_md.get_irq		 	= iSeries_get_irq;
 	ppc_md.init		 	= NULL;
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/irq.c linux-2.4.23-bk14/arch/ppc64/kernel/irq.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/irq.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.23-bk14/arch/ppc64/kernel/irq.c	2003-12-19 02:52:56.000000000 -0800
@@ -41,6 +41,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/random.h>
+#include <linux/bootmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -56,8 +57,47 @@
 #include <asm/paca.h>
 #include <asm/perfmon.h>
 
-#include "local_irq.h"
+/*
+ * Because the name space for interrupts is so large on ppc64 systems we
+ * avoid declaring a single array of "NR_IRQ" interrupts and instead build
+ * a three level tree leading to the irq_desc_t (similar to page tables).
+ *
+ * Currently we cover 24-bit irq values:
+ *    10-bits:  the "base" dir (2-pages)
+ *     9-bits:  the "middle" dir (1-page)
+ *     5-bits:  the "bottom" page (1-page) holding 128byte irq_desc's.
+ *
+ * We pack a hw_irq_stat struct directly after the irq_desc in the otherwise
+ * wasted space of the cacheline.
+ *
+ * MAX_IRQS is the max this implementation will support.
+ * It is much larger than NR_IRQS which is bogus on this arch and often used
+ * to declare arrays.
+ *
+ * Note that all "undefined" mid table and bottom table pointers will point
+ * to dummy tables.  Therefore, we don't need to check for NULL on spurious
+ * interrupts.
+ */
+
+#define IRQ_BASE_INDEX_SIZE  10
+#define IRQ_MID_INDEX_SIZE  9
+#define IRQ_BOT_DESC_SIZE 5
+
+#define IRQ_BASE_PTRS	(1 << IRQ_BASE_INDEX_SIZE)
+#define IRQ_MID_PTRS	(1 << IRQ_MID_INDEX_SIZE)
+#define IRQ_BOT_DESCS (1 << IRQ_BOT_DESC_SIZE)
+
+#define IRQ_BASE_IDX_SHIFT (IRQ_MID_INDEX_SIZE + IRQ_BOT_DESC_SIZE)
+#define IRQ_MID_IDX_SHIFT (IRQ_BOT_DESC_SIZE)
 
+#define IRQ_MID_IDX_MASK  ((1 << IRQ_MID_INDEX_SIZE) - 1)
+#define IRQ_BOT_IDX_MASK  ((1 << IRQ_BOT_DESC_SIZE) - 1)
+
+irq_desc_t **irq_desc_base_dir[IRQ_BASE_PTRS] __page_aligned = {0};
+irq_desc_t **irq_desc_mid_null;
+irq_desc_t *irq_desc_bot_null;
+
+unsigned int _next_irq(unsigned int irq);
 atomic_t ipi_recv;
 atomic_t ipi_sent;
 void enable_irq(unsigned int irq_nr);
@@ -72,9 +112,10 @@
 
 irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
 	{ [0 ... NR_IRQS-1] = { 0, NULL, NULL, 0, SPIN_LOCK_UNLOCKED}};
-	
+
+static irq_desc_t *add_irq_desc(unsigned int irq);
+
 int ppc_spurious_interrupts = 0;
-struct irqaction *ppc_irq_action[NR_IRQS];
 unsigned long lpEvent_count = 0;
 #ifdef CONFIG_XMON
 extern void xmon(struct pt_regs *regs);
@@ -93,16 +134,200 @@
 extern void (*debugger_fault_handler)(struct pt_regs *regs);
 #endif
 
-/* nasty hack for shared irq's since we need to do kmalloc calls but
- * can't very early in the boot when we need to do a request irq.
- * this needs to be removed.
- * -- Cort
- */
 #define IRQ_KMALLOC_ENTRIES 16
 static int cache_bitmask = 0;
 static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES];
 extern int mem_init_done;
 
+/* The hw_irq_stat struct is stored directly after the irq_desc_t
+ * in the same cacheline.  We need to use care to make sure we don't
+ * overrun the size of the cacheline.
+ *
+ * Currently sizeof(irq_desc_t) is 40 bytes or less and this hw_irq_stat
+ * fills the rest of the cache line.
+ */
+struct hw_irq_stat {
+	unsigned long irqs;		/* statistic per irq */
+	unsigned long *per_cpu_stats;
+	struct proc_dir_entry *irq_dir, *smp_affinity;
+	unsigned long irq_affinity;	/* ToDo: cpu bitmask */
+};
+
+static inline struct hw_irq_stat *get_irq_stat(irq_desc_t *desc)
+{
+	/* WARNING: this assumes lock is the last field! */
+	return (struct hw_irq_stat *)(&desc->lock+1);
+}
+
+static inline unsigned long *get_irq_per_cpu(struct hw_irq_stat *hw)
+{
+	return hw->per_cpu_stats;
+}
+
+static inline irq_desc_t **get_irq_mid_table(unsigned int irq)
+{
+	/* Assume irq < MAX_IRQS so we won't index off the end. */
+	return irq_desc_base_dir[irq >> IRQ_BASE_IDX_SHIFT];
+}
+
+static inline irq_desc_t *get_irq_bot_table(unsigned int irq,
+					    irq_desc_t **mid_ptr)
+{
+	return mid_ptr[(irq >> IRQ_MID_IDX_SHIFT) & IRQ_MID_IDX_MASK];
+}
+
+/* This should be inline. */
+void *_irqdesc(unsigned int irq)
+{
+	irq_desc_t **mid_table, *bot_table, *desc;
+
+	mid_table = get_irq_mid_table(irq);
+	bot_table = get_irq_bot_table(irq, mid_table);
+
+	desc = bot_table + (irq & IRQ_BOT_IDX_MASK);
+	return desc;
+}
+
+/*
+ * This is used by the for_each_irq(i) macro to iterate quickly over
+ * all interrupts.  It optimizes by skipping over ptrs to the null tables
+ * when possible, but it may produce false positives.
+ */
+unsigned int _next_irq(unsigned int irq)
+{
+	irq_desc_t **mid_table, *bot_table;
+
+	irq++;
+	/* Easy case first...staying on the current bot_table. */
+	if (irq & IRQ_BOT_IDX_MASK)
+		return irq;
+
+	/* Now skip empty mid tables */
+	while (irq < MAX_IRQS &&
+	       (mid_table = get_irq_mid_table(irq)) == irq_desc_mid_null) {
+		/* index to the next base index (i.e. the next mid table) */
+		irq = (irq & ~(IRQ_BASE_IDX_SHIFT-1)) + IRQ_BASE_IDX_SHIFT;
+	}
+	/* And skip empty bot tables */
+	while (irq < MAX_IRQS &&
+	       (bot_table = get_irq_bot_table(irq, mid_table)) == irq_desc_bot_null) {
+		/* index to the next mid index (i.e. the next bot table) */
+		irq = (irq & ~(IRQ_MID_IDX_SHIFT-1)) + IRQ_MID_IDX_SHIFT;
+	}
+	return irq;
+}
+
+
+/* Same as irqdesc(irq) except it will "fault in" a real desc as needed
+ * rather than return the null entry.
+ * This is used by code that is actually defining the irq.
+ *
+ * NULL may be returned on memory allocation failure.  In general, init code
+ * doesn't look for this, but setup_irq does.  In this failure case the desc
+ * is left pointing at the null pages so callers of irqdesc() should
+ * always return something.
+ */
+void *_real_irqdesc(unsigned int irq)
+{
+	irq_desc_t *desc = irqdesc(irq);
+	if (((unsigned long)desc & PAGE_MASK) ==
+	    (unsigned long)irq_desc_bot_null) {
+		desc = add_irq_desc(irq);
+	}
+	return desc;
+}
+
+/* Allocate an irq middle page and init entries to null page. */
+static irq_desc_t **alloc_irq_mid_page(void)
+{
+	irq_desc_t **m, **ent;
+
+	if (mem_init_done)
+		m = (irq_desc_t **)__get_free_page(GFP_KERNEL);
+	else
+		m = (irq_desc_t **)alloc_bootmem_pages(PAGE_SIZE);
+	if (m) {
+		for (ent = m; ent < m + IRQ_MID_PTRS; ent++) {
+			*ent = irq_desc_bot_null;
+		}
+	}
+	return m;
+}
+
+/* Allocate an irq bottom page and init the entries. */
+static irq_desc_t *alloc_irq_bot_page(void)
+{
+	irq_desc_t *b, *ent;
+	if (mem_init_done)
+		b = (irq_desc_t *)get_zeroed_page(GFP_KERNEL);
+	else
+		b = (irq_desc_t *)alloc_bootmem_pages(PAGE_SIZE);
+	if (b) {
+		for (ent = b; ent < b + IRQ_BOT_DESCS; ent++) {
+			ent->lock = SPIN_LOCK_UNLOCKED;
+		}
+	}
+	return b;
+}
+
+/*
+ * The universe of interrupt numbers ranges from 0 to 2^24.
+ * Use a sparsely populated tree to map from the irq to the handler.
+ * Top level is 2 contiguous pages, covering the 10 most significant
+ * bits.  Mid level is 1 page, covering 9 bits.  Last page covering
+ * 5 bits is the irq_desc, each of which is 128B.
+ */
+static void irq_desc_init(void) {
+	irq_desc_t ***entry_p;
+
+	/*
+	 * Now initialize the tables to point though the NULL tables for
+	 * the default case of no interrupt handler (spurious).
+	 */
+	irq_desc_bot_null = alloc_irq_bot_page();
+	irq_desc_mid_null = alloc_irq_mid_page();
+	if (!irq_desc_bot_null || !irq_desc_mid_null)
+		panic("irq_desc_init: could not allocate pages\n");
+	for(entry_p = irq_desc_base_dir;
+	    entry_p < irq_desc_base_dir + IRQ_BASE_PTRS;
+	    entry_p++) {
+		*entry_p = irq_desc_mid_null;
+	}
+}
+
+/*
+ * Add a new irq desc for the given irq if needed.
+ * This breaks any ptr to the "null" middle or "bottom" irq desc page.
+ * Note that we don't ever coalesce pages as the interrupts are released.
+ * This isn't worth the effort.  We add the cpu stats info when the
+ * interrupt is actually requested.
+ *
+ * May return NULL if memory could not be allocated.
+ */
+static irq_desc_t *add_irq_desc(unsigned int irq)
+{
+	irq_desc_t **mid_table_p, *bot_table_p;
+
+	mid_table_p = get_irq_mid_table(irq);
+	if(mid_table_p == irq_desc_mid_null) {
+		/* No mid table for this IRQ - create it */
+		mid_table_p = alloc_irq_mid_page();
+		if (!mid_table_p) return NULL;
+		irq_desc_base_dir[irq >> IRQ_BASE_IDX_SHIFT] = mid_table_p;
+	}
+
+	bot_table_p = (irq_desc_t *)(*(mid_table_p + ((irq >> 5) & 0x1ff)));
+
+	if(bot_table_p == irq_desc_bot_null) {
+		/* No bot table for this IRQ - create it */
+		bot_table_p = alloc_irq_bot_page();
+		if (!bot_table_p) return NULL;
+		mid_table_p[(irq >> IRQ_MID_IDX_SHIFT) & IRQ_MID_IDX_MASK] = bot_table_p;
+	}
+
+	return bot_table_p + (irq & IRQ_BOT_IDX_MASK);
+}
+
 void *irq_kmalloc(size_t size, int pri)
 {
 	unsigned int i;
@@ -127,13 +352,44 @@
 	kfree(ptr);
 }
 
+void allocate_per_cpu_stats(struct hw_irq_stat *hwstat)
+{
+	unsigned long *p;
+
+	if (mem_init_done) {
+		p = (unsigned long *)kmalloc(sizeof(long)*NR_CPUS, GFP_KERNEL);
+		if (p) memset(p, 0, sizeof(long)*NR_CPUS);
+	} else
+		p = (unsigned long *)alloc_bootmem(sizeof(long)*NR_CPUS);
+	hwstat->per_cpu_stats = p;
+}
+
 int
 setup_irq(unsigned int irq, struct irqaction * new)
 {
 	int shared = 0;
 	unsigned long flags;
 	struct irqaction *old, **p;
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = real_irqdesc(irq);
+	struct hw_irq_stat *hwstat;
+
+	if (!desc)
+		return -ENOMEM;
+
+	ppc_md.init_irq_desc(desc);
+
+	hwstat = get_irq_stat(desc);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+	hwstat->irq_affinity = ~0;
+#else
+	hwstat->irq_affinity = 0;
+#endif
+
+	/* Now is the time to add per-cpu kstat data to the desc
+	 * since it appears we are actually going to use the irq.
+	 */
+	allocate_per_cpu_stats(hwstat);
 
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
@@ -189,11 +445,10 @@
 static int
 do_free_irq(int irq, void* dev_id)
 {
-	irq_desc_t *desc;
+	irq_desc_t *desc = irqdesc(irq);
 	struct irqaction **p;
 	unsigned long flags;
 
-	desc = irq_desc + irq;
 	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
 	for (;;) {
@@ -233,8 +488,9 @@
 	struct irqaction *action;
 	int retval;
 
-	if (irq >= NR_IRQS)
+	if (irq >= MAX_IRQS)
 		return -EINVAL;
+
 	if (!handler)
 		/* We could implement really free_irq() instead of that... */
 		return do_free_irq(irq, dev_id);
@@ -285,7 +541,7 @@
  
  void disable_irq_nosync(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irqdesc(irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -317,7 +573,7 @@
 	if (!local_irq_count(smp_processor_id())) {
 		do {
 			barrier();
-		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+		} while (irqdesc(irq)->status & IRQ_INPROGRESS);
 	}
 }
 
@@ -333,7 +589,7 @@
  
 void enable_irq(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irqdesc(irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -357,82 +613,57 @@
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-/* one would think this function has one foot in the grave */
+/* This function as implemented was a potential source of data
+ * corruption.  I pulled it for now, until it can be properly
+ * implemented. DRENG
+ */
 int get_irq_list(char *buf)
 {
-   int i, len = 0, j;
-   struct irqaction * action;
-
-   len += sprintf(buf+len, "           ");
-   for (j=0; j<smp_num_cpus; j++)
-       len += sprintf(buf+len, "CPU%d       ",j);
-   *(char *)(buf+len++) = '\n';
-
-   for (i = 0 ; i < NR_IRQS ; i++) {
-       action = irq_desc[i].action;
-       if ( !action || !action->handler )
-           continue;
-       len += sprintf(buf+len, "%3d: ", i);
-#ifdef CONFIG_SMP
-       for (j = 0; j < smp_num_cpus; j++)
-           len += sprintf(buf+len, "%10u ",
-               kstat.irqs[cpu_logical_map(j)][i]);
-#else
-       len += sprintf(buf+len, "%10u ", kstat_irqs(i));
-#endif /* CONFIG_SMP */
-if ( irq_desc[i].handler )
-len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
-else
-len += sprintf(buf+len, "  None      ");
-len += sprintf(buf+len, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
-len += sprintf(buf+len, "    %s",action->name);
-for (action=action->next; action; action = action->next) {
-len += sprintf(buf+len, ", %s", action->name);
-}
-len += sprintf(buf+len, "\n");
+	return(0);
 }
-#ifdef CONFIG_SMP
-/* should this be per processor send/receive? */
-len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n",
-atomic_read(&ipi_recv), atomic_read(&ipi_sent));
-#endif
-len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
-return len;
-}
-
-
 
 int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
+	irq_desc_t *desc;
+	struct hw_irq_stat *hwstat;
+	unsigned long *per_cpus;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
 		seq_printf(p, "CPU%d       ",j);
 	seq_putc(p, '\n');
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
-		action = irq_desc[i].action;
+	for_each_irq(i) {
+		desc = irqdesc(i);
+		spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
+
 		if (!action || !action->handler)
-			continue;
-		seq_printf(p, "%3d: ", i);		
-#ifdef CONFIG_SMP
+			goto skip;
+		seq_printf(p, "%3d: ", i);
+		hwstat = get_irq_stat(desc);
+		per_cpus = get_irq_per_cpu(hwstat);
+		if (per_cpus) {
 		for (j = 0; j < smp_num_cpus; j++)
-			seq_printf(p, "%10u ",
-				kstat.irqs[cpu_logical_map(j)][i]);
-#else		
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#endif /* CONFIG_SMP */
-		if (irq_desc[i].handler)		
-			seq_printf(p, " %s ", irq_desc[i].handler->typename );
+				seq_printf(p, "%10lu ", per_cpus[j]);
+		} else {
+			seq_printf(p, "%10lu ", hwstat->irqs);
+		}
+
+		if (irqdesc(i)->handler)
+			seq_printf(p, " %s ", irqdesc(i)->handler->typename );
 		else
 			seq_printf(p, "  None      ");
-		seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
+		seq_printf(p, "%s", (irqdesc(i)->status & IRQ_LEVEL) ? "Level " : "Edge  ");
 		seq_printf(p, "    %s",action->name);
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&desc->lock, flags);
 	}
 #ifdef CONFIG_SMP
 	/* should this be per processor send/receive? */
@@ -470,9 +701,24 @@
 	int status;
 	struct irqaction *action;
 	int cpu = smp_processor_id();
-	irq_desc_t *desc = irq_desc + irq;
+	irq_desc_t *desc = irqdesc(irq);
+	struct hw_irq_stat *hwstat;
+	unsigned long *per_cpus;
+
+	/* Statistics. */
+	hwstat = get_irq_stat(desc);	/* same cache line as desc */
+	hwstat->irqs++;
+	per_cpus = get_irq_per_cpu(hwstat); /* same cache line for < 8 cpus */
+	if (per_cpus)
+		per_cpus[cpu]++;
 
+	if(irq < NR_IRQS) {
 	kstat.irqs[cpu][irq]++;
+	} else {
+		kstat.irqs[cpu][NR_IRQS-1]++;
+	}
+
+
 	spin_lock(&desc->lock);
 	ack_irq(irq);	
 	/*
@@ -544,11 +790,11 @@
 	 * The ->end() handler has to deal with interrupts which got
 	 * disabled while the handler was running.
 	 */
-	if (irq_desc[irq].handler) {
-		if (irq_desc[irq].handler->end)
-			irq_desc[irq].handler->end(irq);
-		else if (irq_desc[irq].handler->enable)
-			irq_desc[irq].handler->enable(irq);
+	if (desc->handler) {
+		if (desc->handler->end)
+			desc->handler->end(irq);
+		else if (desc->handler->enable)
+			desc->handler->enable(irq);
 	}
 	spin_unlock(&desc->lock);
 }
@@ -638,7 +884,10 @@
 		return;
 	else
 		once++;
-	
+
+	/* Initialize the irq tree */
+	irq_desc_init();
+
 	ppc_md.init_IRQ();
 	if(ppc_md.init_ras_IRQ) ppc_md.init_ras_IRQ(); 
 }
@@ -794,6 +1043,7 @@
 #endif /* CONFIG_SMP */
 
 static struct proc_dir_entry * root_irq_dir;
+#if 0
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
 
@@ -802,15 +1052,19 @@
 #else  /* CONFIG_IRQ_ALL_CPUS */
 unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0x00000000};
 #endif /* CONFIG_IRQ_ALL_CPUS */
+#endif
 
 #define HEX_DIGITS 8
 
 static int irq_affinity_read_proc (char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
+	irq_desc_t *desc = irqdesc((long)data);
+	struct hw_irq_stat *hwstat = get_irq_stat(desc);
+
 	if (count < HEX_DIGITS+1)
 		return -EINVAL;
-	return sprintf (page, "%08x\n", irq_affinity[(int)(long)data]);
+	return sprintf(page, "%16lx\n", hwstat->irq_affinity);
 }
 
 static unsigned int parse_hex_value (const char *buffer,
@@ -853,10 +1107,13 @@
 static int irq_affinity_write_proc (struct file *file, const char *buffer,
 					unsigned long count, void *data)
 {
-	int irq = (int)(long) data, full_count = count, err;
+	unsigned int irq = (long)data;
+	irq_desc_t *desc = irqdesc(irq);
+	struct hw_irq_stat *hwstat = get_irq_stat(desc);
+	int full_count = count, err;
 	unsigned long new_value;
 
-	if (!irq_desc[irq].handler->set_affinity)
+	if (!desc->handler->set_affinity)
 		return -EIO;
 
 	err = parse_hex_value(buffer, count, &new_value);
@@ -871,10 +1128,8 @@
 	if (!(new_value & cpu_online_map))
 		return -EINVAL;
 #endif
-
-	irq_affinity[irq] = new_value;
-	irq_desc[irq].handler->set_affinity(irq, new_value);
-
+	hwstat->irq_affinity = new_value;
+	desc->handler->set_affinity(irq, new_value);
 	return full_count;
 }
 
@@ -923,25 +1178,39 @@
 {
 	struct proc_dir_entry *entry;
 	char name [MAX_NAMELEN];
+	irq_desc_t *desc;
+	struct hw_irq_stat *hwstat;
 
-	if (!root_irq_dir || (irq_desc[irq].handler == NULL))
+	desc = real_irqdesc(irq);
+	if (!root_irq_dir || !desc || !desc->handler)
+		return;
+	hwstat = get_irq_stat(desc);
+	if (hwstat->irq_dir)
 		return;
 
 	memset(name, 0, MAX_NAMELEN);
 	sprintf(name, "%d", irq);
 
 	/* create /proc/irq/1234 */
-	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+	hwstat->irq_dir = proc_mkdir(name, root_irq_dir);
+	if(hwstat->irq_dir == NULL) {
+		printk(KERN_ERR "register_irq_proc: proc_mkdir failed.\n");
+		return;
+	}
 
 	/* create /proc/irq/1234/smp_affinity */
-	entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+	entry = create_proc_entry("smp_affinity", 0600, hwstat->irq_dir);
 
-	entry->nlink = 1;
-	entry->data = (void *)(long)irq;
-	entry->read_proc = irq_affinity_read_proc;
-	entry->write_proc = irq_affinity_write_proc;
+	if(entry) {
+		entry->nlink = 1;
+		entry->data = (void *)(long)irq;
+		entry->read_proc = irq_affinity_read_proc;
+		entry->write_proc = irq_affinity_write_proc;
+	} else {
+		printk(KERN_ERR "register_irq_proc: create_proc_entry failed.\n");
+	}
 
-	smp_affinity_entry[irq] = entry;
+	hwstat->smp_affinity = entry;
 }
 
 unsigned long prof_cpu_mask = -1;
@@ -953,20 +1222,27 @@
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
+	if(root_irq_dir == NULL) {
+		printk(KERN_ERR "init_irq_proc: proc_mkdir failed.\n");
+	}
 
 	/* create /proc/irq/prof_cpu_mask */
 	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
 
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	if(entry) {
+		entry->nlink = 1;
+		entry->data = (void *)&prof_cpu_mask;
+		entry->read_proc = prof_cpu_mask_read_proc;
+		entry->write_proc = prof_cpu_mask_write_proc;
+	} else {
+		printk(KERN_ERR "init_irq_proc: create_proc_entry failed.\n");
+	}
 
 	/*
 	 * Create entries for all existing IRQs.
 	 */
-	for (i = 0; i < NR_IRQS; i++) {
-		if (irq_desc[i].handler == NULL)
+	for_each_irq(i) {
+		if (irqdesc(i)->handler == NULL)
 			continue;
 		register_irq_proc(i);
 	}
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/open_pic.c linux-2.4.23-bk14/arch/ppc64/kernel/open_pic.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/open_pic.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.23-bk14/arch/ppc64/kernel/open_pic.c	2003-12-19 02:52:56.000000000 -0800
@@ -20,7 +20,7 @@
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
-
+#include <asm/smp.h>
 #include <asm/machdep.h>
 
 #include "local_irq.h"
@@ -131,13 +131,23 @@
 
 #define GET_ISU(source)	ISU[(source) >> 4][(source) & 0xf]
 
+void
+openpic_init_irq_desc(irq_desc_t *desc)
+{
+	/* Don't mess with the handler if already set.
+	 * This leaves the setup of isa/ipi handlers undisturbed.
+	 */
+	if (!desc->handler)
+		desc->handler = &open_pic;
+}
+
 void __init openpic_init_IRQ(void)
 {
         struct device_node *np;
         int i;
         unsigned int *addrp;
         unsigned char* chrp_int_ack_special = 0;
-        unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
+	unsigned char init_senses[NR_IRQS - NUM_ISA_INTERRUPTS];
         int nmi_irq = -1;
 #if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
         struct device_node *kbd;
@@ -152,13 +162,13 @@
 			__ioremap(addrp[prom_n_addr_cells(np)-1], 1, _PAGE_NO_CACHE);
         /* hydra still sets OpenPIC_InitSenses to a static set of values */
         if (OpenPIC_InitSenses == NULL) {
-                prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
-                OpenPIC_InitSenses = init_senses;
-                OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
-        }
-        openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
-        for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
-                irq_desc[i].handler = &i8259_pic;
+		prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS);
+		OpenPIC_InitSenses = init_senses;
+		OpenPIC_NumInitSenses = NR_IRQS - NUM_ISA_INTERRUPTS;
+	}
+	openpic_init(1, NUM_ISA_INTERRUPTS, chrp_int_ack_special, nmi_irq);
+	for ( i = 0 ; i < NUM_ISA_INTERRUPTS  ; i++ )
+		real_irqdesc(i)->handler = &i8259_pic;
         i8259_init();
 }
 
@@ -343,8 +353,8 @@
 		/* Disabled, Priority 10..13 */
 		openpic_initipi(i, 10+i, openpic_vec_ipi+i);
 		/* IPIs are per-CPU */
-		irq_desc[openpic_vec_ipi+i].status |= IRQ_PER_CPU;
-		irq_desc[openpic_vec_ipi+i].handler = &open_pic_ipi;
+		real_irqdesc(openpic_vec_ipi+i)->status |= IRQ_PER_CPU;
+		real_irqdesc(openpic_vec_ipi+i)->handler = &open_pic_ipi;
 	}
 #endif
 
@@ -369,7 +379,7 @@
 		pri = (i == programmer_switch_irq)? 9: 8;
 		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
 		if (sense)
-			irq_desc[i+offset].status = IRQ_LEVEL;
+			real_irqdesc(i+offset)->status = IRQ_LEVEL;
 
 		/* Enabled, Priority 8 or 9 */
 		openpic_initirq(i, pri, i+offset, !sense, sense);
@@ -377,10 +387,6 @@
 		openpic_mapirq(i, 1<<get_hard_smp_processor_id(0));
 	}
 
-	/* Init descriptors */
-	for (i = offset; i < NumSources + offset; i++)
-		irq_desc[i].handler = &open_pic;
-
 	/* Initialize the spurious interrupt */
 	ppc64_boot_msg(0x24, "OpenPic Spurious");
 	openpic_set_spurious(openpic_vec_spurious);
@@ -755,7 +761,7 @@
 
 static void openpic_end_irq(unsigned int irq_nr)
 {
-	if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
+	if ((irqdesc(irq_nr)->status & IRQ_LEVEL) != 0)
 		openpic_eoi();
 }
 
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/open_pic.h linux-2.4.23-bk14/arch/ppc64/kernel/open_pic.h
--- linux-2.4.23-bk13/arch/ppc64/kernel/open_pic.h	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/open_pic.h	2003-12-19 02:52:56.000000000 -0800
@@ -37,9 +37,4 @@
 extern void openpic_setup_ISU(int isu_num, unsigned long addr);
 extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
 
-extern inline int openpic_to_irq(int irq)
-{
-	return irq += NUM_8259_INTERRUPTS;
-}
-/*extern int open_pic_irq_offset;*/
 #endif /* _PPC64_KERNEL_OPEN_PIC_H */
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/pSeries_hvCall.S linux-2.4.23-bk14/arch/ppc64/kernel/pSeries_hvCall.S
--- linux-2.4.23-bk13/arch/ppc64/kernel/pSeries_hvCall.S	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/pSeries_hvCall.S	2003-12-19 02:52:56.000000000 -0800
@@ -23,7 +23,7 @@
 /*
  * hcall interface to pSeries LPAR
  */
-#define HSC .long 0x44000022
+#define HVSC	.long 0x44000022
 
 /* long plpar_hcall(unsigned long opcode,	 R3 
 		 unsigned long arg1,		 R4 
@@ -45,7 +45,7 @@
         std     r9,-16(r1)
         std     r10,-24(r1)
 	
-	HSC                     /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
 
         ld      r10,-8(r1)      /* Fetch r4-r7 ret args. */
         std     r4,0(r10)
@@ -60,11 +60,85 @@
 	blr                     /* return r3 = status */
 
 
+/* long plpar_hcall_4out(unsigned long opcode,	 R3
+		 unsigned long arg1,		 R4
+		 unsigned long arg2,		 R5
+		 unsigned long arg3,		 R6
+		 unsigned long arg4,		 R7
+		 unsigned long *out1,	(r4)	 R8
+		 unsigned long *out2,	(r5)	 R9
+		 unsigned long *out3,   (r6)     R10
+		 unsigned long *out4);	(r7)	 112(R1). From Parameter save area. 
+ */
+_GLOBAL(plpar_hcall_4out)
+	mfcr	r0
+	std	r0,-8(r1)
+	ld      r14,112(r1)
+	stdu	r1,-48(r1)
+
+	std     r8,32(r1)       /* Save out ptrs. */
+	std     r9,24(r1)
+	std     r10,16(r1)
+	std     r14,8(r1)
+
+	HVSC                    /* invoke the hypervisor */
+
+	ld      r14,32(r1)      /* Fetch r4-r7 ret args. */
+	std     r4,0(r14)
+	ld      r14,24(r1)
+	std     r5,0(r14)
+	ld      r14,16(r1)
+	std     r6,0(r14)
+	ld      r14,8(r1)
+	std     r7,0(r14)
+
+	ld	r1,0(r1) 
+	ld	r0,-8(r1)
+	mtcrf	0xff,r0
+	blr                     /* return r3 = status */
+
+
 /* Simple interface with no output values (other than status) */
 _GLOBAL(plpar_hcall_norets)
 	mfcr	r0
 	std	r0,-8(r1)
-	HSC                     /* invoke the hypervisor */
+	HVSC                    /* invoke the hypervisor */
+	ld	r0,-8(r1)
+	mtcrf	0xff,r0
+	blr                     /* return r3 = status */
+
+
+/* long plpar_hcall_8arg_2ret(unsigned long opcode,		 R3
+				unsigned long arg1,		 R4
+				unsigned long arg2,		 R5
+				unsigned long arg3,		 R6
+				unsigned long arg4,		 R7
+				unsigned long arg5,		 R8
+				unsigned long arg6,		 R9
+				unsigned long arg7,		 R10
+				unsigned long arg8,		 112(R1)
+				unsigned long *out1);		 120(R1)
+
+ */
+
+	.text
+_GLOBAL(plpar_hcall_8arg_2ret)
+	mfcr	r0
+
+	ld	r11, 112(r1) /* put arg8 and out1 in R11 and R12 */
+	ld	r12, 120(r1)
+
+	std	r0,-8(r1)
+	stdu	r1,-32(r1)
+
+	std	r12,-8(r1)      /* Save out ptr */
+
+	HVSC                     /* invoke the hypervisor */
+
+	ld	r10,-8(r1)      /* Fetch r4 ret arg */
+	std	r4,0(r10)
+
+	ld	r1,0(r1)
 	ld	r0,-8(r1)
 	mtcrf	0xff,r0
 	blr                     /* return r3 = status */
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/pSeries_pci.c linux-2.4.23-bk14/arch/ppc64/kernel/pSeries_pci.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/pSeries_pci.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/pSeries_pci.c	2003-12-19 02:52:56.000000000 -0800
@@ -703,10 +703,6 @@
 		pci_read_irq_line(dev);
 		PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Dev(dev) );
 	}
-
-	if (naca->interrupt_controller == IC_PPC_XIC) {
-		xics_isa_init(); 
-	}
 }
 
 /*********************************************************************** 
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/prom.c linux-2.4.23-bk14/arch/ppc64/kernel/prom.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/prom.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/prom.c	2003-12-19 02:52:56.000000000 -0800
@@ -182,11 +182,6 @@
 
 struct device_node *allnodes = 0;
 
-#define UNDEFINED_IRQ 0xffff
-unsigned short real_irq_to_virt_map[NR_HW_IRQS];
-unsigned short virt_irq_to_real_map[NR_IRQS];
-int last_virt_irq = 2;	/* index of last virt_irq.  Skip through IPI */
-
 static unsigned long call_prom(const char *service, int nargs, int nret, ...);
 static void prom_exit(void);
 static unsigned long copy_device_tree(unsigned long);
@@ -1697,46 +1692,6 @@
 	return DOUBLEWORD_ALIGN(mem);
 }
 
-void
-virt_irq_init(void)
-{
-	int i;
-	for (i = 0; i < NR_IRQS; i++)
-		virt_irq_to_real_map[i] = UNDEFINED_IRQ;
-	for (i = 0; i < NR_HW_IRQS; i++)
-		real_irq_to_virt_map[i] = UNDEFINED_IRQ;
-}
-
-/* Create a mapping for a real_irq if it doesn't already exist.
- * Return the virtual irq as a convenience.
- */
-unsigned long
-virt_irq_create_mapping(unsigned long real_irq)
-{
-	unsigned long virq;
-	if (naca->interrupt_controller == IC_OPEN_PIC)
-		return real_irq;	/* no mapping for openpic (for now) */
-	virq = real_irq_to_virt(real_irq);
-	if (virq == UNDEFINED_IRQ) {
-		/* Assign a virtual IRQ number */
-		if (real_irq < NR_IRQS && virt_irq_to_real(real_irq) == UNDEFINED_IRQ) {
-			/* A 1-1 mapping will work. */
-			virq = real_irq;
-		} else {
-			while (last_virt_irq < NR_IRQS &&
-			       virt_irq_to_real(++last_virt_irq) != UNDEFINED_IRQ)
-				/* skip irq's in use */;
-			if (last_virt_irq >= NR_IRQS)
-				panic("Too many IRQs are required on this system.  NR_IRQS=%d\n", NR_IRQS);
-			virq = last_virt_irq;
-		}
-		virt_irq_to_real_map[virq] = real_irq;
-		real_irq_to_virt_map[real_irq] = virq;
-	}
-	return virq;
-}
-
-
 static int __init
 prom_next_node(phandle *nodep)
 {
@@ -1866,8 +1821,6 @@
 {
 	unsigned long mem = klimit;
 
-	virt_irq_init();
-
 	mem = finish_node(allnodes, mem, NULL, 0, 0);
 	dev_tree_size = mem - (unsigned long) allnodes;
 
@@ -1972,7 +1925,7 @@
 		np->n_intrs = ipsize / isize;
 		mem_start += np->n_intrs * sizeof(struct interrupt_info);
 		for (i = 0; i < np->n_intrs; ++i) {
-		    np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(*interrupts++));
+		    np->intrs[i].line = irq_offset_up(*interrupts++);
 		    np->intrs[i].sense = 1;
 		    if (isize > 1)
 		        np->intrs[i].sense = *interrupts++;
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/ras.c linux-2.4.23-bk14/arch/ppc64/kernel/ras.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/ras.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/ras.c	2003-12-19 02:52:56.000000000 -0800
@@ -73,7 +73,7 @@
 	   (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", 
 						&len))) {
 		for(i=0; i<(len / sizeof(*ireg)); i++) {
-			request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, 
+			request_irq(irq_offset_up(*(ireg)),
 				    &ras_error_interrupt, 0, 
 				    "RAS_ERROR", NULL);
 			ireg++;
@@ -84,7 +84,7 @@
 	   (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", 
 						&len))) {
 		for(i=0; i<(len / sizeof(*ireg)); i++) {
-			request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, 
+			request_irq(irq_offset_up(*(ireg)),
 				    &ras_epow_interrupt, 0, 
 				    "RAS_EPOW", NULL);
 			ireg++;
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/xics.c linux-2.4.23-bk14/arch/ppc64/kernel/xics.c
--- linux-2.4.23-bk13/arch/ppc64/kernel/xics.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/xics.c	2003-12-19 02:52:56.000000000 -0800
@@ -51,7 +51,6 @@
 };
 
 #define XICS_IPI		2
-#define XICS_IRQ_OFFSET		0x10
 #define XICS_IRQ_SPURIOUS	0
 
 /* Want a priority other than 0.  Various HW issues require this. */
@@ -136,17 +135,14 @@
 
 
 void
-xics_enable_irq(
-	u_int	virq
-	)
+xics_enable_irq(u_int virq)
 {
 	u_int		irq;
 	unsigned long	status;
 	long	        call_status;
 	unsigned int    interrupt_server = default_server;
 
-	virq -= XICS_IRQ_OFFSET;
-	irq = virt_irq_to_real(virq);
+	irq = irq_offset_down(virq);
 	if (irq == XICS_IPI)
 		return;
 
@@ -175,18 +171,14 @@
 }
 
 void
-xics_disable_irq(
-	u_int	virq
-	)
+xics_disable_irq(u_int virq)
 {
 	u_int		irq;
 	unsigned long 	status;
 	long 	        call_status;
 
-	virq -= XICS_IRQ_OFFSET;
-	irq = virt_irq_to_real(virq);
-	call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, 
-				irq);
+	irq = irq_offset_down(virq);
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
 	if( call_status != 0 ) {
 		printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n",
 		       irq, call_status);
@@ -195,16 +187,12 @@
 }
 
 void
-xics_end_irq(
-	u_int	irq
-	)
+xics_end_irq(u_int irq)
 {
 	int cpu = smp_processor_id();
 
-	ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */
-	iosync();
-	ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET))));
 	iosync();
+	ops->xirr_info_set(cpu, (0xff<<24) | irq_offset_down(irq));
 }
 
 void
@@ -212,7 +200,7 @@
 {
 	int cpu = smp_processor_id();
 
-	if( irq < XICS_IRQ_OFFSET ) {
+	if (irq < irq_offset_value()) {
 		i8259_pic.ack(irq);
 		iosync();
 		ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade_real));
@@ -239,13 +227,13 @@
 		irq = i8259_irq(cpu);
 		if(irq == -1) {
 			/* Spurious cascaded interrupt.  Still must ack xics */
-                        xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade);
+			xics_end_irq(irq_offset_up(xics_irq_8259_cascade));
 			irq = -1;
 		}
 	} else if( vec == XICS_IRQ_SPURIOUS ) {
 		irq = -1;
 	} else {
-		irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET;
+		irq = irq_offset_up(vec);
 	}
 	return irq;
 }
@@ -290,6 +278,15 @@
 }
 #endif /* CONFIG_SMP */
 
+void xics_init_irq_desc(irq_desc_t *desc)
+{
+	/* Don't mess with the handler if already set.
+	 * This leaves the setup of isa handlers undisturbed.
+	 */
+	if (!desc->handler)
+		desc->handler = &xics_pic;
+}
+
 void
 xics_init_IRQ( void )
 {
@@ -373,7 +370,7 @@
 			while (1);
 		}
 		xics_irq_8259_cascade_real = *ireg;
-		xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real);
+		xics_irq_8259_cascade = xics_irq_8259_cascade_real;
 	}
 
 	if (systemcfg->platform == PLATFORM_PSERIES) {
@@ -398,36 +395,24 @@
 	xics_8259_pic.enable = i8259_pic.enable;
 	xics_8259_pic.disable = i8259_pic.disable;
 	for (i = 0; i < 16; ++i)
-		irq_desc[i].handler = &xics_8259_pic;
-	for (; i < NR_IRQS; ++i)
-		irq_desc[i].handler = &xics_pic;
+		real_irqdesc(i)->handler = &xics_8259_pic;
 
 	ops->cppr_info(0, 0xff);
 	iosync();
 	if (xics_irq_8259_cascade != -1) {
-		if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
-				0, "8259 cascade", 0))
+		if (request_irq(irq_offset_up(xics_irq_8259_cascade),
+				no_action, 0, "8259 cascade", 0))
 			printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
 		i8259_init();
 	}
 
 #ifdef CONFIG_SMP
-	real_irq_to_virt_map[XICS_IPI] = virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
-	request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
-	irq_desc[XICS_IPI+XICS_IRQ_OFFSET].status |= IRQ_PER_CPU;
+	request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, 0, "IPI", 0);
+	real_irqdesc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU;
 #endif
 	ppc64_boot_msg(0x21, "XICS Done");
 }
 
-void xics_isa_init(void)
-{
-	return;
-	if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
-			0, "8259 cascade", 0))
-		printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
-	i8259_init();
-}
-
 /*
  * Find first logical cpu and return its physical cpu number
  */
@@ -445,21 +430,19 @@
 	return default_distrib_server;
 }
 
-void xics_set_affinity(unsigned int virq, unsigned long cpumask)
+void xics_set_affinity(unsigned int irq, unsigned long cpumask)
 {
-        irq_desc_t *desc = irq_desc + virq;
-	unsigned int irq;
+	irq_desc_t *desc = irqdesc(irq);
 	unsigned long flags;
 	long status;
 	unsigned long xics_status[2];
 	u32 newmask;
 
-	virq -= XICS_IRQ_OFFSET;
-	irq = virt_irq_to_real(virq);
+	irq = irq_offset_down(irq);
 	if (irq == XICS_IPI)
 		return;
 
-        spin_lock_irqsave(&desc->lock, flags);
+	spin_lock_irqsave(&desc->lock, flags);
 
 	status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, irq);
 
@@ -485,5 +468,5 @@
 	}
 
 out:
-        spin_unlock_irqrestore(&desc->lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
diff -urN linux-2.4.23-bk13/arch/ppc64/kernel/xics.h linux-2.4.23-bk14/arch/ppc64/kernel/xics.h
--- linux-2.4.23-bk13/arch/ppc64/kernel/xics.h	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.23-bk14/arch/ppc64/kernel/xics.h	2003-12-19 02:52:56.000000000 -0800
@@ -18,7 +18,7 @@
 extern struct hw_interrupt_type xics_8259_pic;
 
 void xics_init_IRQ(void);
+void xics_init_irq_desc(irq_desc_t *);
 int xics_get_irq(struct pt_regs *);
-void xics_isa_init(void);
 
 #endif /* _PPC_KERNEL_XICS_H */
diff -urN linux-2.4.23-bk13/drivers/char/drm/drmP.h linux-2.4.23-bk14/drivers/char/drm/drmP.h
--- linux-2.4.23-bk13/drivers/char/drm/drmP.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/drmP.h	2003-12-19 02:52:56.000000000 -0800
@@ -328,16 +328,16 @@
    if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
 
 				/* Mapping helper macros */
-#define DRM_IOREMAP(map)						\
-	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size )
+#define DRM_IOREMAP(map, dev)					\
+	(map)->handle = DRM(ioremap)((map)->offset, (map)->size, (dev) )
 
-#define DRM_IOREMAP_NOCACHE(map)					\
-	(map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size)
+#define DRM_IOREMAP_NOCACHE(map, dev)					\
+	(map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev) )
 
-#define DRM_IOREMAPFREE(map)						\
+#define DRM_IOREMAPFREE(map, dev)						\
 	do {								\
 		if ( (map)->handle && (map)->size )			\
-			DRM(ioremapfree)( (map)->handle, (map)->size );	\
+			DRM(ioremapfree)( (map)->handle, (map)->size, (dev) );	\
 	} while (0)
 
 #define DRM_FIND_MAP(_map, _o)						\
@@ -789,9 +789,9 @@
 extern unsigned long DRM(alloc_pages)(int order, int area);
 extern void	     DRM(free_pages)(unsigned long address, int order,
 				     int area);
-extern void	     *DRM(ioremap)(unsigned long offset, unsigned long size);
-extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size);
-extern void	     DRM(ioremapfree)(void *pt, unsigned long size);
+extern void	     *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void	     DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
 
 #if __REALLY_HAVE_AGP
 extern agp_memory    *DRM(alloc_agp)(int pages, u32 type);
diff -urN linux-2.4.23-bk13/drivers/char/drm/drm_bufs.h linux-2.4.23-bk14/drivers/char/drm/drm_bufs.h
--- linux-2.4.23-bk13/drivers/char/drm/drm_bufs.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/drm_bufs.h	2003-12-19 02:52:56.000000000 -0800
@@ -123,7 +123,7 @@
 					      MTRR_TYPE_WRCOMB, 1 );
 		}
 #endif
-		map->handle = DRM(ioremap)( map->offset, map->size );
+		map->handle = DRM(ioremap)( map->offset, map->size, dev );
 		break;
 
 	case _DRM_SHM:
@@ -245,7 +245,7 @@
 				DRM_DEBUG("mtrr_del = %d\n", retcode);
 			}
 #endif
-			DRM(ioremapfree)(map->handle, map->size);
+			DRM(ioremapfree)(map->handle, map->size, dev);
 			break;
 		case _DRM_SHM:
 			vfree(map->handle);
diff -urN linux-2.4.23-bk13/drivers/char/drm/drm_drv.h linux-2.4.23-bk14/drivers/char/drm/drm_drv.h
--- linux-2.4.23-bk13/drivers/char/drm/drm_drv.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/drm_drv.h	2003-12-19 02:52:56.000000000 -0800
@@ -443,7 +443,7 @@
 					DRM_DEBUG( "mtrr_del=%d\n", retcode );
 				}
 #endif
-				DRM(ioremapfree)( map->handle, map->size );
+				DRM(ioremapfree)( map->handle, map->size, dev );
 				break;
 			case _DRM_SHM:
 				vfree(map->handle);
diff -urN linux-2.4.23-bk13/drivers/char/drm/drm_memory.h linux-2.4.23-bk14/drivers/char/drm/drm_memory.h
--- linux-2.4.23-bk13/drivers/char/drm/drm_memory.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/drm_memory.h	2003-12-19 02:52:56.000000000 -0800
@@ -290,7 +290,7 @@
 	}
 }
 
-void *DRM(ioremap)(unsigned long offset, unsigned long size)
+void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	void *pt;
 
@@ -313,7 +313,7 @@
 	return pt;
 }
 
-void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size)
+void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	void *pt;
 
@@ -336,7 +336,7 @@
 	return pt;
 }
 
-void DRM(ioremapfree)(void *pt, unsigned long size)
+void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
 {
 	int alloc_count;
 	int free_count;
diff -urN linux-2.4.23-bk13/drivers/char/drm/drm_vm.h linux-2.4.23-bk14/drivers/char/drm/drm_vm.h
--- linux-2.4.23-bk13/drivers/char/drm/drm_vm.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/drm_vm.h	2003-12-19 02:52:56.000000000 -0800
@@ -206,7 +206,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				DRM(ioremapfree)(map->handle, map->size);
+				DRM(ioremapfree)(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				vfree(map->handle);
diff -urN linux-2.4.23-bk13/drivers/char/drm/gamma_dma.c linux-2.4.23-bk14/drivers/char/drm/gamma_dma.c
--- linux-2.4.23-bk13/drivers/char/drm/gamma_dma.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/gamma_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -638,7 +638,7 @@
 	} else {
 		DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
 
-		DRM_IOREMAP( dev_priv->buffers );
+		DRM_IOREMAP( dev_priv->buffers, dev );
 
 		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
 		pgt = buf->address;
@@ -668,7 +668,7 @@
 	if ( dev->dev_private ) {
 		drm_gamma_private_t *dev_priv = dev->dev_private;
 
-		DRM_IOREMAPFREE( dev_priv->buffers );
+		DRM_IOREMAPFREE( dev_priv->buffers, dev );
 
 		DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
 			   DRM_MEM_DRIVER );
diff -urN linux-2.4.23-bk13/drivers/char/drm/i810_dma.c linux-2.4.23-bk14/drivers/char/drm/i810_dma.c
--- linux-2.4.23-bk13/drivers/char/drm/i810_dma.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/i810_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -276,7 +276,7 @@
 
 	   	if(dev_priv->ring.virtual_start) {
 		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
-					 dev_priv->ring.Size);
+					 dev_priv->ring.Size, dev);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
 		   	pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -292,7 +292,7 @@
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-			DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total);
+			DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
 		}
 	}
    	return 0;
@@ -362,7 +362,7 @@
 	   	*buf_priv->in_use = I810_BUF_FREE;
 
 		buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address,
-							buf->total);
+							buf->total, dev);
 	}
 	return 0;
 }
@@ -415,7 +415,7 @@
 
    	dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
 						    init->ring_start,
-						    init->ring_size);
+						    init->ring_size, dev);
 
    	if (dev_priv->ring.virtual_start == NULL) {
 		dev->dev_private = (void *) dev_priv;
diff -urN linux-2.4.23-bk13/drivers/char/drm/i830_dma.c linux-2.4.23-bk14/drivers/char/drm/i830_dma.c
--- linux-2.4.23-bk13/drivers/char/drm/i830_dma.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/i830_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -252,7 +252,7 @@
 	   
 	   	if(dev_priv->ring.virtual_start) {
 		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
-					 dev_priv->ring.Size);
+					 dev_priv->ring.Size, dev);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
 			pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -277,7 +277,7 @@
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
 			drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-			DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total);
+			DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
 		}
 	}
    	return 0;
@@ -353,7 +353,7 @@
 	   	*buf_priv->in_use = I830_BUF_FREE;
 
 		buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, 
-							buf->total);
+							buf->total, dev);
 	}
 	return 0;
 }
@@ -407,7 +407,7 @@
 
    	dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + 
 						    init->ring_start, 
-						    init->ring_size);
+						    init->ring_size, dev);
 
    	if (dev_priv->ring.virtual_start == NULL) {
 		dev->dev_private = (void *) dev_priv;
diff -urN linux-2.4.23-bk13/drivers/char/drm/mga_dma.c linux-2.4.23-bk14/drivers/char/drm/mga_dma.c
--- linux-2.4.23-bk13/drivers/char/drm/mga_dma.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/mga_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -556,9 +556,9 @@
 		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				    init->sarea_priv_offset);
 
-	DRM_IOREMAP( dev_priv->warp );
-	DRM_IOREMAP( dev_priv->primary );
-	DRM_IOREMAP( dev_priv->buffers );
+	DRM_IOREMAP( dev_priv->warp, dev );
+	DRM_IOREMAP( dev_priv->primary, dev );
+	DRM_IOREMAP( dev_priv->buffers, dev );
 
 	if(!dev_priv->warp->handle ||
 	   !dev_priv->primary->handle ||
@@ -644,9 +644,9 @@
 	if ( dev->dev_private ) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
 
-		DRM_IOREMAPFREE( dev_priv->warp );
-		DRM_IOREMAPFREE( dev_priv->primary );
-		DRM_IOREMAPFREE( dev_priv->buffers );
+		DRM_IOREMAPFREE( dev_priv->warp, dev );
+		DRM_IOREMAPFREE( dev_priv->primary, dev );
+		DRM_IOREMAPFREE( dev_priv->buffers, dev );
 
 		if ( dev_priv->head != NULL ) {
 			mga_freelist_cleanup( dev );
diff -urN linux-2.4.23-bk13/drivers/char/drm/r128_cce.c linux-2.4.23-bk14/drivers/char/drm/r128_cce.c
--- linux-2.4.23-bk13/drivers/char/drm/r128_cce.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/r128_cce.c	2003-12-19 02:52:56.000000000 -0800
@@ -542,9 +542,9 @@
 				     init->sarea_priv_offset);
 
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cce_ring );
-		DRM_IOREMAP( dev_priv->ring_rptr );
-		DRM_IOREMAP( dev_priv->buffers );
+		DRM_IOREMAP( dev_priv->cce_ring, dev );
+		DRM_IOREMAP( dev_priv->ring_rptr, dev );
+		DRM_IOREMAP( dev_priv->buffers, dev );
 		if(!dev_priv->cce_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
 		   !dev_priv->buffers->handle) {
@@ -618,9 +618,9 @@
 #if __REALLY_HAVE_SG
 		if ( !dev_priv->is_pci ) {
 #endif
-			DRM_IOREMAPFREE( dev_priv->cce_ring );
-			DRM_IOREMAPFREE( dev_priv->ring_rptr );
-			DRM_IOREMAPFREE( dev_priv->buffers );
+			DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
+			DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
+			DRM_IOREMAPFREE( dev_priv->buffers, dev );
 #if __REALLY_HAVE_SG
 		} else {
 			if (!DRM(ati_pcigart_cleanup)( dev,
diff -urN linux-2.4.23-bk13/drivers/char/drm/radeon_cp.c linux-2.4.23-bk14/drivers/char/drm/radeon_cp.c
--- linux-2.4.23-bk13/drivers/char/drm/radeon_cp.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm/radeon_cp.c	2003-12-19 02:52:56.000000000 -0800
@@ -1145,9 +1145,9 @@
 				       init->sarea_priv_offset);
 
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cp_ring );
-		DRM_IOREMAP( dev_priv->ring_rptr );
-		DRM_IOREMAP( dev_priv->buffers );
+		DRM_IOREMAP( dev_priv->cp_ring, dev );
+		DRM_IOREMAP( dev_priv->ring_rptr, dev );
+		DRM_IOREMAP( dev_priv->buffers, dev );
 		if(!dev_priv->cp_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
 		   !dev_priv->buffers->handle) {
@@ -1266,9 +1266,9 @@
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
 		if ( !dev_priv->is_pci ) {
-			DRM_IOREMAPFREE( dev_priv->cp_ring );
-			DRM_IOREMAPFREE( dev_priv->ring_rptr );
-			DRM_IOREMAPFREE( dev_priv->buffers );
+			DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
+			DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
+			DRM_IOREMAPFREE( dev_priv->buffers, dev );
 		} else {
 #if __REALLY_HAVE_SG
 			if (!DRM(ati_pcigart_cleanup)( dev,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/bufs.c linux-2.4.23-bk14/drivers/char/drm-4.0/bufs.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/bufs.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/bufs.c	2003-12-19 02:52:56.000000000 -0800
@@ -87,7 +87,7 @@
 					     MTRR_TYPE_WRCOMB, 1);
 		}
 #endif
-		map->handle = drm_ioremap(map->offset, map->size);
+		map->handle = drm_ioremap(map->offset, map->size, dev);
 		break;
 			
 
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/drmP.h linux-2.4.23-bk14/drivers/char/drm-4.0/drmP.h
--- linux-2.4.23-bk13/drivers/char/drm-4.0/drmP.h	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/drmP.h	2003-12-19 02:52:56.000000000 -0800
@@ -679,8 +679,8 @@
 extern unsigned long drm_alloc_pages(int order, int area);
 extern void	     drm_free_pages(unsigned long address, int order,
 				    int area);
-extern void	     *drm_ioremap(unsigned long offset, unsigned long size);
-extern void	     drm_ioremapfree(void *pt, unsigned long size);
+extern void	     *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void	     drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
 
 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
 extern agp_memory    *drm_alloc_agp(int pages, u32 type);
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/ffb_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/ffb_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/ffb_drv.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/ffb_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -158,7 +158,7 @@
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 
 			case _DRM_SHM:
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/gamma_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/gamma_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/gamma_drv.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/gamma_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -258,7 +258,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/i810_dma.c linux-2.4.23-bk14/drivers/char/drm-4.0/i810_dma.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/i810_dma.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/i810_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -305,7 +305,7 @@
 	   
 	   	if(dev_priv->ring.virtual_start) {
 		   	drm_ioremapfree((void *) dev_priv->ring.virtual_start,
-					dev_priv->ring.Size);
+					dev_priv->ring.Size, dev);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
 		   	i810_free_page(dev, dev_priv->hw_status_page);
@@ -319,7 +319,7 @@
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-			drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
+			drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
 		}
 	}
    	return 0;
@@ -393,7 +393,7 @@
 	   	*buf_priv->in_use = I810_BUF_FREE;
 
 		buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
-						       buf->total);
+						       buf->total, dev);
 	}
 	return 0;
 }
@@ -430,7 +430,7 @@
 
    	dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
 						   init->ring_start, 
-						   init->ring_size);
+						   init->ring_size, dev);
 
    	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
    
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/i810_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/i810_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/i810_drv.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/i810_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -286,7 +286,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/memory.c linux-2.4.23-bk14/drivers/char/drm-4.0/memory.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/memory.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/memory.c	2003-12-19 02:52:56.000000000 -0800
@@ -296,7 +296,7 @@
 	}
 }
 
-void *drm_ioremap(unsigned long offset, unsigned long size)
+void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	void *pt;
 	
@@ -319,7 +319,7 @@
 	return pt;
 }
 
-void drm_ioremapfree(void *pt, unsigned long size)
+void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
 {
 	int alloc_count;
 	int free_count;
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/mga_dma.c linux-2.4.23-bk14/drivers/char/drm-4.0/mga_dma.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/mga_dma.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/mga_dma.c	2003-12-19 02:52:56.000000000 -0800
@@ -308,7 +308,7 @@
 	temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
 
 	dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
-					temp);
+					temp, dev);
 	if(dev_priv->ioremap == NULL) {
 		DRM_ERROR("Ioremap failed\n");
 		return -ENOMEM;
@@ -635,7 +635,7 @@
 				    dev_priv->primary_size +
 				    PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
 
-			drm_ioremapfree((void *) dev_priv->ioremap, temp);
+			drm_ioremapfree((void *) dev_priv->ioremap, temp, dev);
 		}
 	   	if(dev_priv->status_page != NULL) {
 		   	iounmap(dev_priv->status_page);
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/mga_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/mga_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/mga_drv.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/mga_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -286,7 +286,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/r128_cce.c linux-2.4.23-bk14/drivers/char/drm-4.0/r128_cce.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/r128_cce.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/r128_cce.c	2003-12-19 02:52:56.000000000 -0800
@@ -86,12 +86,12 @@
 };
 
 
-#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+#define DO_REMAP(_m, _d) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size, (_d))
 
-#define DO_REMAPFREE(_m)                                                    \
+#define DO_REMAPFREE(_m, _d)                                                   \
 	do {                                                                \
 		if ((_m)->handle && (_m)->size)                             \
-			drm_ioremapfree((_m)->handle, (_m)->size);          \
+			drm_ioremapfree((_m)->handle, (_m)->size, (_d));    \
 	} while (0)
 
 #define DO_FIND_MAP(_m, _o)                                                 \
@@ -481,12 +481,12 @@
 		(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				     init->sarea_priv_offset);
 
-	DO_REMAP( dev_priv->cce_ring );
-	DO_REMAP( dev_priv->ring_rptr );
-	DO_REMAP( dev_priv->buffers );
+	DO_REMAP( dev_priv->cce_ring, dev );
+	DO_REMAP( dev_priv->ring_rptr, dev );
+	DO_REMAP( dev_priv->buffers, dev );
 #if 0
 	if ( !dev_priv->is_pci ) {
-		DO_REMAP( dev_priv->agp_textures );
+		DO_REMAP( dev_priv->agp_textures, dev );
 	}
 #endif
 
@@ -521,12 +521,12 @@
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
-		DO_REMAPFREE( dev_priv->cce_ring );
-		DO_REMAPFREE( dev_priv->ring_rptr );
-		DO_REMAPFREE( dev_priv->buffers );
+		DO_REMAPFREE( dev_priv->cce_ring, dev );
+		DO_REMAPFREE( dev_priv->ring_rptr, dev );
+		DO_REMAPFREE( dev_priv->buffers, dev );
 #if 0
 		if ( !dev_priv->is_pci ) {
-			DO_REMAPFREE( dev_priv->agp_textures );
+			DO_REMAPFREE( dev_priv->agp_textures, dev );
 		}
 #endif
 
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/r128_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/r128_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/r128_drv.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/r128_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -296,7 +296,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/radeon_cp.c linux-2.4.23-bk14/drivers/char/drm-4.0/radeon_cp.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/radeon_cp.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/radeon_cp.c	2003-12-19 02:52:56.000000000 -0800
@@ -300,12 +300,12 @@
 };
 
 
-#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
+#define DO_IOREMAP(_m, _d) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size, (_d))
 
-#define DO_IOREMAPFREE(_m)						\
+#define DO_IOREMAPFREE(_m, _d)						\
 	do {								\
 		if ((_m)->handle && (_m)->size)				\
-			drm_ioremapfree((_m)->handle, (_m)->size);	\
+			drm_ioremapfree((_m)->handle, (_m)->size, (_d));\
 	} while (0)
 
 #define DO_FIND_MAP(_m, _o)						\
@@ -757,12 +757,12 @@
 		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				       init->sarea_priv_offset);
 
-	DO_IOREMAP( dev_priv->cp_ring );
-	DO_IOREMAP( dev_priv->ring_rptr );
-	DO_IOREMAP( dev_priv->buffers );
+	DO_IOREMAP( dev_priv->cp_ring, dev );
+	DO_IOREMAP( dev_priv->ring_rptr, dev );
+	DO_IOREMAP( dev_priv->buffers, dev );
 #if 0
 	if ( !dev_priv->is_pci ) {
-		DO_IOREMAP( dev_priv->agp_textures );
+		DO_IOREMAP( dev_priv->agp_textures, dev );
 	}
 #endif
 
@@ -828,12 +828,12 @@
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
-		DO_IOREMAPFREE( dev_priv->cp_ring );
-		DO_IOREMAPFREE( dev_priv->ring_rptr );
-		DO_IOREMAPFREE( dev_priv->buffers );
+		DO_IOREMAPFREE( dev_priv->cp_ring, dev );
+		DO_IOREMAPFREE( dev_priv->ring_rptr, dev );
+		DO_IOREMAPFREE( dev_priv->buffers, dev );
 #if 0
 		if ( !dev_priv->is_pci ) {
-			DO_IOREMAPFREE( dev_priv->agp_textures );
+			DO_IOREMAPFREE( dev_priv->agp_textures, dev );
 		}
 #endif
 
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/radeon_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/radeon_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/radeon_drv.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/radeon_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -294,7 +294,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/drm-4.0/tdfx_drv.c linux-2.4.23-bk14/drivers/char/drm-4.0/tdfx_drv.c
--- linux-2.4.23-bk13/drivers/char/drm-4.0/tdfx_drv.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/drm-4.0/tdfx_drv.c	2003-12-19 02:52:56.000000000 -0800
@@ -264,7 +264,7 @@
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
 #endif
-				drm_ioremapfree(map->handle, map->size);
+				drm_ioremapfree(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
 				drm_free_pages((unsigned long)map->handle,
diff -urN linux-2.4.23-bk13/drivers/char/efirtc.c linux-2.4.23-bk14/drivers/char/efirtc.c
--- linux-2.4.23-bk13/drivers/char/efirtc.c	2003-12-19 02:52:50.000000000 -0800
+++ linux-2.4.23-bk14/drivers/char/efirtc.c	2003-12-19 02:52:56.000000000 -0800
@@ -118,7 +118,7 @@
 static void
 convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
 {
-	memset(&wtime, 0, sizeof(struct rtc_time));
+	memset(wtime, 0, sizeof(struct rtc_time));
 	wtime->tm_sec  = eft->second;
 	wtime->tm_min  = eft->minute;
 	wtime->tm_hour = eft->hour;
diff -urN linux-2.4.23-bk13/drivers/input/keybdev.c linux-2.4.23-bk14/drivers/input/keybdev.c
--- linux-2.4.23-bk13/drivers/input/keybdev.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-bk14/drivers/input/keybdev.c	2003-12-19 02:52:57.000000000 -0800
@@ -154,16 +154,18 @@
 
 static struct input_handler keybdev_handler;
 
+static unsigned int ledstate = 0xff;
+
 void keybdev_ledfunc(unsigned int led)
 {
 	struct input_handle *handle;	
 
-	for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
+	ledstate = led;
 
+	for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
 		input_event(handle->dev, EV_LED, LED_SCROLLL, !!(led & 0x01));
 		input_event(handle->dev, EV_LED, LED_NUML,    !!(led & 0x02));
 		input_event(handle->dev, EV_LED, LED_CAPSL,   !!(led & 0x04));
-
 	}
 }
 
@@ -202,7 +204,12 @@
 	input_open_device(handle);
 
 //	printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
-	kbd_refresh_leds();
+
+	if (ledstate != 0xff) {
+		input_event(dev, EV_LED, LED_SCROLLL, !!(ledstate & 0x01));
+		input_event(dev, EV_LED, LED_NUML,    !!(ledstate & 0x02));
+		input_event(dev, EV_LED, LED_CAPSL,   !!(ledstate & 0x04));
+	}
 
 	return handle;
 }
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_aops.c linux-2.4.23-bk14/fs/xfs/linux/xfs_aops.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_aops.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_aops.c	2003-12-19 02:52:58.000000000 -0800
@@ -361,6 +361,7 @@
 	unsigned long		p_offset,
 	int			block_bits,
 	xfs_iomap_t		*iomapp,
+	int			startio,
 	int			all_bh)
 {
 	struct buffer_head	*bh = curr;
@@ -436,7 +437,7 @@
 				break;
 			nblocks += bs;
 			atomic_add(bs, &pb->pb_io_remaining);
-			convert_page(inode, page, iomapp, pb, 1, all_bh);
+			convert_page(inode, page, iomapp, pb, startio, all_bh);
 		}
 
 		if (tindex == tlast &&
@@ -446,7 +447,7 @@
 			if (page) {
 				nblocks += bs;
 				atomic_add(bs, &pb->pb_io_remaining);
-				convert_page(inode, page, iomapp, pb, 1, all_bh);
+				convert_page(inode, page, iomapp, pb, startio, all_bh);
 			}
 		}
 	}
@@ -546,7 +547,7 @@
 		if (buffer_unwritten(bh) && !bh->b_end_io) {
 			ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN);
 			map_unwritten(inode, page, head, bh,
-						offset, bbits, tmp, all_bh);
+					offset, bbits, tmp, startio, all_bh);
 		} else if (! (buffer_unwritten(bh) && buffer_locked(bh))) {
 			map_buffer_at_offset(page, bh, offset, bbits, tmp);
 			if (buffer_unwritten(bh)) {
@@ -678,8 +679,8 @@
 				if (!bh->b_end_io) {
 					err = map_unwritten(inode, page,
 							head, bh, p_offset,
-							inode->i_blkbits,
-							iomp, unmapped);
+							inode->i_blkbits, iomp,
+							startio, unmapped);
 					if (err) {
 						goto error;
 					}
@@ -796,7 +797,7 @@
 STATIC int
 linvfs_get_block_core(
 	struct inode		*inode,
-	sector_t		iblock,
+	long			iblock,
 	struct buffer_head	*bh_result,
 	int			create,
 	int			direct,
@@ -879,7 +880,7 @@
 int
 linvfs_get_block(
 	struct inode		*inode,
-	sector_t		iblock,
+	long			iblock,
 	struct buffer_head	*bh_result,
 	int			create)
 {
@@ -890,7 +891,7 @@
 STATIC int
 linvfs_get_block_sync(
 	struct inode		*inode,
-	sector_t		iblock,
+	long			iblock,
 	struct buffer_head	*bh_result,
 	int			create)
 {
@@ -901,7 +902,7 @@
 STATIC int
 linvfs_get_block_direct(
 	struct inode		*inode,
-	sector_t		iblock,
+	long			iblock,
 	struct buffer_head	*bh_result,
 	int			create)
 {
@@ -909,10 +910,10 @@
 					create, 1, BMAPI_WRITE|BMAPI_DIRECT);
 }
 
-STATIC sector_t
+STATIC int
 linvfs_bmap(
 	struct address_space	*mapping,
-	sector_t		block)
+	long			block)
 {
 	struct inode		*inode = (struct inode *)mapping->host;
 	vnode_t			*vp = LINVFS_GET_VP(inode);
@@ -1116,7 +1117,7 @@
 	int			rw,
 	struct inode		*inode,
 	struct kiobuf		*iobuf,
-	sector_t		blocknr,
+	unsigned long		blocknr,
 	int			blocksize)
 {
 	struct page		**maplist;
@@ -1138,7 +1139,7 @@
 	page_offset = iobuf->offset;
 
 	map_flags = (rw ? BMAPI_WRITE : BMAPI_READ) | BMAPI_DIRECT;
-	pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO;
+	pb_flags = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIO | PBF_DIRECTIO;
 	while (length) {
 		error = map_blocks(inode, offset, length, &iomap, map_flags);
 		if (error)
@@ -1224,21 +1225,6 @@
 }
 
 
-/* since the address_space_operations are not consitent with the type used
- * for block indexes we must cast the functions into what is expected..
- * thus the following 2 lines.
- * If running on a kernel with LBD support and hence bmap and direct_IO
- * correctly defined with sector_t params. use the second set of typedefs
- * or casts from the address space_operations
- * RMC
- */
-
-#ifndef  HAVE_SECTOR_T
-typedef int (bmap_proc)(struct address_space *, long);
-typedef int (direct_IO_proc)(int, struct inode *, struct kiobuf *,
-			     unsigned long, int);
-#endif
-
 struct address_space_operations linvfs_aops = {
 	.readpage		= linvfs_readpage,
 	.writepage		= linvfs_writepage,
@@ -1246,11 +1232,6 @@
 	.releasepage		= linvfs_release_page,
 	.prepare_write		= linvfs_prepare_write,
 	.commit_write		= generic_commit_write,
-#ifndef HAVE_SECTOR_T
-	.bmap			= (bmap_proc *)linvfs_bmap,
-	.direct_IO		= (direct_IO_proc *)linvfs_direct_IO,
-#else
 	.bmap			= linvfs_bmap,
 	.direct_IO		= linvfs_direct_IO,
-#endif
 };
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_file.c linux-2.4.23-bk14/fs/xfs/linux/xfs_file.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_file.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_file.c	2003-12-19 02:52:58.000000000 -0800
@@ -58,14 +58,6 @@
 
 static struct vm_operations_struct linvfs_file_vm_ops;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
-#define	do_down_read(x)	down_read(x)
-#define do_up_read(x)	up_read(x)
-#else
-#define	do_down_read(x)
-#define do_up_read(x)
-#endif
-
 STATIC inline ssize_t
 __linvfs_read(
 	struct file	*file,
@@ -80,9 +72,9 @@
 
 	if (unlikely(file->f_flags & O_DIRECT)) {
 		ioflags |= IO_ISDIRECT;
-		do_down_read(&inode->i_alloc_sem);
+		down_read(&inode->i_alloc_sem);
 		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, error);
-		do_up_read(&inode->i_alloc_sem);
+		up_read(&inode->i_alloc_sem);
 	} else {
 		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, error);
 	}
@@ -144,10 +136,10 @@
 	 */
 	if (unlikely(file->f_flags & O_DIRECT)) {
 		ioflags |= IO_ISDIRECT;
-		do_down_read(&inode->i_alloc_sem);
+		down_read(&inode->i_alloc_sem);
 		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, error);
 		*ppos = pos;
-		do_up_read(&inode->i_alloc_sem);
+		up_read(&inode->i_alloc_sem);
 	} else {
 		down(&inode->i_sem);
 		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, error);
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_globals.c linux-2.4.23-bk14/fs/xfs/linux/xfs_globals.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_globals.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_globals.c	2003-12-19 02:52:58.000000000 -0800
@@ -102,10 +102,8 @@
 
 xfs_param_t xfs_params = {
 			  /*	MIN	DFLT	MAX	*/
-#ifdef HAVE_REFCACHE
 	.refcache_size	= {	0,	128,	XFS_REFCACHE_SIZE_MAX },
 	.refcache_purge	= {	0,	32,	XFS_REFCACHE_SIZE_MAX },
-#endif
 	.restrict_chown	= {	0,	1,	1	},
 	.sgid_inherit	= {	0,	0,	1	},
 	.symlink_mode	= {	0,	0,	1	},
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_iops.c linux-2.4.23-bk14/fs/xfs/linux/xfs_iops.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_iops.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_iops.c	2003-12-19 02:52:58.000000000 -0800
@@ -110,7 +110,7 @@
 	vattr_t		va;
 	vnode_t		*vp = NULL, *dvp = LINVFS_GET_VP(dir);
 	xfs_acl_t	*default_acl = NULL;
-	xattr_exists_t	test_default_acl = _ACL_DEFAULT_EXISTS;
+	attrexists_t	test_default_acl = _ACL_DEFAULT_EXISTS;
 	int		error;
 
 	if (test_default_acl && test_default_acl(dvp)) {
@@ -543,61 +543,6 @@
 	block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block);
 }
 
-
-
-/*
- * Extended attributes interfaces
- */
-
-#define SYSTEM_NAME	"system."	/* VFS shared names/values */
-#define ROOT_NAME	"trusted."	/* root's own names/values */
-#define USER_NAME	"user."		/* user's own names/values */
-STATIC xattr_namespace_t xfs_namespace_array[] = {
-	{ .name= SYSTEM_NAME,	.namelen= sizeof(SYSTEM_NAME)-1,.exists= NULL },
-	{ .name= ROOT_NAME,	.namelen= sizeof(ROOT_NAME)-1,	.exists= NULL },
-	{ .name= USER_NAME,	.namelen= sizeof(USER_NAME)-1,	.exists= NULL },
-	{ .name= NULL }
-};
-xattr_namespace_t *xfs_namespaces = &xfs_namespace_array[0];
-
-#define POSIXACL_ACCESS		"posix_acl_access"
-#define POSIXACL_ACCESS_SIZE	(sizeof(POSIXACL_ACCESS)-1)
-#define POSIXACL_DEFAULT	"posix_acl_default"
-#define POSIXACL_DEFAULT_SIZE	(sizeof(POSIXACL_DEFAULT)-1)
-#define POSIXCAP		"posix_capabilities"
-#define POSIXCAP_SIZE		(sizeof(POSIXCAP)-1)
-#define POSIXMAC		"posix_mac"
-#define POSIXMAC_SIZE		(sizeof(POSIXMAC)-1)
-STATIC xattr_namespace_t sys_namespace_array[] = {
-	{ .name= POSIXACL_ACCESS,
-		.namelen= POSIXACL_ACCESS_SIZE,	 .exists= _ACL_ACCESS_EXISTS },
-	{ .name= POSIXACL_DEFAULT,
-		.namelen= POSIXACL_DEFAULT_SIZE, .exists= _ACL_DEFAULT_EXISTS },
-	{ .name= POSIXCAP,
-		.namelen= POSIXCAP_SIZE,	 .exists= _CAP_EXISTS },
-	{ .name= POSIXMAC,
-		.namelen= POSIXMAC_SIZE,	 .exists= _MAC_EXISTS },
-	{ .name= NULL }
-};
-
-/*
- * Some checks to prevent people abusing EAs to get over quota:
- * - Don't allow modifying user EAs on devices/symlinks;
- * - Don't allow modifying user EAs if sticky bit set;
- */
-STATIC int
-capable_user_xattr(
-	struct inode	*inode)
-{
-	if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
-	    !capable(CAP_SYS_ADMIN))
-		return 0;
-	if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
-	    (current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
-		return 0;
-	return 1;
-}
-
 STATIC int
 linvfs_setxattr(
 	struct dentry	*dentry,
@@ -606,59 +551,27 @@
 	size_t		size,
 	int		flags)
 {
-	struct inode	*inode = dentry->d_inode;
-	vnode_t		*vp = LINVFS_GET_VP(inode);
-	char		*p = (char *)name;
+	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
+	char		*attr = (char *)name;
+	attrnames_t	*namesp;
 	int		xflags = 0;
 	int		error;
 
-	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
-			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
-		error = -EINVAL;
-		if (flags & XATTR_CREATE)
-			 return error;
-		error = -EOPNOTSUPP;
-		p += xfs_namespaces[SYSTEM_NAMES].namelen;
-		if (strcmp(p, POSIXACL_ACCESS) == 0)
-			error = xfs_acl_vset(vp, (void *) data, size,
-						_ACL_TYPE_ACCESS);
-		else if (strcmp(p, POSIXACL_DEFAULT) == 0)
-			error = xfs_acl_vset(vp, (void *) data, size,
-						_ACL_TYPE_DEFAULT);
-		else if (strcmp(p, POSIXCAP) == 0)
-			error = xfs_cap_vset(vp, (void *) data, size);
-		if (!error)
-			error = vn_revalidate(vp);
+	namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	attr += namesp->attr_namelen;
+	error = namesp->attr_capable(vp, NULL);
+	if (error)
 		return error;
-	}
-
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
 
 	/* Convert Linux syscall to XFS internal ATTR flags */
 	if (flags & XATTR_CREATE)
 		xflags |= ATTR_CREATE;
 	if (flags & XATTR_REPLACE)
 		xflags |= ATTR_REPLACE;
-
-	if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
-			xfs_namespaces[ROOT_NAMES].namelen) == 0) {
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		xflags |= ATTR_ROOT;
-		p += xfs_namespaces[ROOT_NAMES].namelen;
-		VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error);
-		return -error;
-	}
-	if (strncmp(name, xfs_namespaces[USER_NAMES].name,
-			xfs_namespaces[USER_NAMES].namelen) == 0) {
-		if (!capable_user_xattr(inode))
-			return -EPERM;
-		p += xfs_namespaces[USER_NAMES].namelen;
-		VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error);
-		return -error;
-	}
-	return -EOPNOTSUPP;
+	xflags |= namesp->attr_flag;
+	return namesp->attr_set(vp, attr, (void *)data, size, xflags);
 }
 
 STATIC ssize_t
@@ -668,96 +581,47 @@
 	void		*data,
 	size_t		size)
 {
-	struct inode	*inode = dentry->d_inode;
-	vnode_t		*vp = LINVFS_GET_VP(inode);
-	char		*p = (char *)name;
+	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
+	char		*attr = (char *)name;
+	attrnames_t	*namesp;
 	int		xflags = 0;
 	ssize_t		error;
 
-	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
-			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
-		error = -EOPNOTSUPP;
-		p += xfs_namespaces[SYSTEM_NAMES].namelen;
-		if (strcmp(p, POSIXACL_ACCESS) == 0)
-			error = xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
-		else if (strcmp(p, POSIXACL_DEFAULT) == 0)
-			error = xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
-		else if (strcmp(p, POSIXCAP) == 0)
-			error = xfs_cap_vget(vp, data, size);
+	namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	attr += namesp->attr_namelen;
+	error = namesp->attr_capable(vp, NULL);
+	if (error)
 		return error;
-	}
 
 	/* Convert Linux syscall to XFS internal ATTR flags */
 	if (!size) {
 		xflags |= ATTR_KERNOVAL;
 		data = NULL;
 	}
-
-	if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
-			xfs_namespaces[ROOT_NAMES].namelen) == 0) {
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		xflags |= ATTR_ROOT;
-		p += xfs_namespaces[ROOT_NAMES].namelen;
-		VOP_ATTR_GET(vp, p, data, (int *)&size, xflags, NULL, error);
-		if (!error)
-			error = -size;
-		return -error;
-	}
-	if (strncmp(name, xfs_namespaces[USER_NAMES].name,
-			xfs_namespaces[USER_NAMES].namelen) == 0) {
-		p += xfs_namespaces[USER_NAMES].namelen;
-		if (!capable_user_xattr(inode))
-			return -EPERM;
-		VOP_ATTR_GET(vp, p, data, (int *)&size, xflags, NULL, error);
-		if (!error)
-			error = -size;
-		return -error;
-	}
-	return -EOPNOTSUPP;
+	xflags |= namesp->attr_flag;
+	return namesp->attr_get(vp, attr, (void *)data, size, xflags);
 }
 
-
 STATIC ssize_t
 linvfs_listxattr(
 	struct dentry		*dentry,
 	char			*data,
 	size_t			size)
 {
-	attrlist_cursor_kern_t	cursor;
-	xattr_namespace_t	*sys;
 	vnode_t			*vp = LINVFS_GET_VP(dentry->d_inode);
-	char			*k = data;
-	int			xflags = ATTR_KERNAMELS;
-	int			result = 0;
-	ssize_t			error;
+	int			error, xflags = ATTR_KERNAMELS;
+	ssize_t			result;
 
 	if (!size)
 		xflags |= ATTR_KERNOVAL;
 	if (capable(CAP_SYS_ADMIN))
 		xflags |= ATTR_KERNFULLS;
 
-	memset(&cursor, 0, sizeof(cursor));
-	VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
-	if (error > 0)
-		return -error;
-	result += -error;
-
-	k += result;		/* advance start of our buffer */
-	for (sys = &sys_namespace_array[0]; sys->name != NULL; sys++) {
-		if (sys->exists == NULL || !sys->exists(vp))
-			continue;
-		result += xfs_namespaces[SYSTEM_NAMES].namelen;
-		result += sys->namelen + 1;
-		if (size) {
-			if (result > size)
-				return -ERANGE;
-			strcpy(k, xfs_namespaces[SYSTEM_NAMES].name);
-			k += xfs_namespaces[SYSTEM_NAMES].namelen;
-			strcpy(k, sys->name);
-			k += sys->namelen + 1;
-		}
-	}
+	error = attr_generic_list(vp, data, size, xflags, &result);
+	if (error < 0)
+		return error;
 	return result;
 }
 
@@ -766,51 +630,25 @@
 	struct dentry	*dentry,
 	const char	*name)
 {
-	struct inode	*inode = dentry->d_inode;
-	vnode_t		*vp = LINVFS_GET_VP(inode);
-	char		*p = (char *)name;
+	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
+	char		*attr = (char *)name;
+	attrnames_t	*namesp;
 	int		xflags = 0;
 	int		error;
 
-	if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name,
-			xfs_namespaces[SYSTEM_NAMES].namelen) == 0) {
-		error = -EOPNOTSUPP;
-		p += xfs_namespaces[SYSTEM_NAMES].namelen;
-		if (strcmp(p, POSIXACL_ACCESS) == 0)
-			error = xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
-		else if (strcmp(p, POSIXACL_DEFAULT) == 0)
-			error = xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
-		else if (strcmp(p, POSIXCAP) == 0)
-			error = xfs_cap_vremove(vp);
+	namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	attr += namesp->attr_namelen;
+	error = namesp->attr_capable(vp, NULL);
+	if (error)
 		return error;
-	}
-
-        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		return -EPERM;
-
-	if (strncmp(name, xfs_namespaces[ROOT_NAMES].name,
-			xfs_namespaces[ROOT_NAMES].namelen) == 0) {
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		xflags |= ATTR_ROOT;
-		p += xfs_namespaces[ROOT_NAMES].namelen;
-		VOP_ATTR_REMOVE(vp, p, xflags, NULL, error);
-		return -error;
-	}
-	if (strncmp(name, xfs_namespaces[USER_NAMES].name,
-			xfs_namespaces[USER_NAMES].namelen) == 0) {
-		p += xfs_namespaces[USER_NAMES].namelen;
-		if (!capable_user_xattr(inode))
-			return -EPERM;
-		VOP_ATTR_REMOVE(vp, p, xflags, NULL, error);
-		return -error;
-	}
-	return -EOPNOTSUPP;
+	xflags |= namesp->attr_flag;
+	return namesp->attr_remove(vp, attr, xflags);
 }
 
 
-struct inode_operations linvfs_file_inode_operations =
-{
+struct inode_operations linvfs_file_inode_operations = {
 	.permission		= linvfs_permission,
 	.truncate		= linvfs_truncate,
 	.revalidate		= linvfs_revalidate,
@@ -821,8 +659,7 @@
 	.removexattr		= linvfs_removexattr,
 };
 
-struct inode_operations linvfs_dir_inode_operations =
-{
+struct inode_operations linvfs_dir_inode_operations = {
 	.create			= linvfs_create,
 	.lookup			= linvfs_lookup,
 	.link			= linvfs_link,
@@ -841,8 +678,7 @@
 	.removexattr		= linvfs_removexattr,
 };
 
-struct inode_operations linvfs_symlink_inode_operations =
-{
+struct inode_operations linvfs_symlink_inode_operations = {
 	.readlink		= linvfs_readlink,
 	.follow_link		= linvfs_follow_link,
 	.permission		= linvfs_permission,
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_iops.h linux-2.4.23-bk14/fs/xfs/linux/xfs_iops.h
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_iops.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_iops.h	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -32,30 +32,6 @@
 #ifndef __XFS_IOPS_H__
 #define __XFS_IOPS_H__
 
-/*
- * Extended system attributes.
- * So far only POSIX ACLs are supported, but this will need to
- * grow in time (capabilities, mandatory access control, etc).
- */
-#define XFS_SYSTEM_NAMESPACE	SYSTEM_POSIXACL
-
-/*
- * Define a table of the namespaces XFS supports
- */
-typedef int (*xattr_exists_t)(vnode_t *);
-
-typedef struct xattr_namespace {
-	char		*name;
-	unsigned int	namelen;
-	xattr_exists_t	exists;
-} xattr_namespace_t;
-
-#define SYSTEM_NAMES	0
-#define ROOT_NAMES	1
-#define USER_NAMES	2
-extern struct xattr_namespace *xfs_namespaces;
-
-
 extern struct inode_operations linvfs_file_inode_operations;
 extern struct inode_operations linvfs_dir_inode_operations;
 extern struct inode_operations linvfs_symlink_inode_operations;
@@ -66,7 +42,7 @@
 
 extern struct address_space_operations linvfs_aops;
 
-extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+extern int linvfs_get_block(struct inode *, long, struct buffer_head *, int);
 extern void linvfs_unwritten_done(struct buffer_head *, int);
 
 extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_linux.h linux-2.4.23-bk14/fs/xfs/linux/xfs_linux.h
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_linux.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_linux.h	2003-12-19 02:52:58.000000000 -0800
@@ -32,6 +32,34 @@
 #ifndef __XFS_LINUX__
 #define __XFS_LINUX__
 
+#include <linux/types.h>
+#include <linux/config.h>
+
+/*
+ * Some types are conditional depending on the target system.
+ * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits.
+ * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well
+ * as requiring XFS_BIG_BLKNOS to be set.
+ */
+#define XFS_BIG_BLKNOS	0
+#define XFS_BIG_INUMS	0
+
+#include <xfs_types.h>
+#include <xfs_arch.h>
+
+#include <support/kmem.h>
+#include <support/mrlock.h>
+#include <support/qsort.h>
+#include <support/spin.h>
+#include <support/sv.h>
+#include <support/ktrace.h>
+#include <support/mutex.h>
+#include <support/sema.h>
+#include <support/debug.h>
+#include <support/move.h>
+#include <support/uuid.h>
+#include <support/time.h>
+
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -55,10 +83,6 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-#ifndef HAVE_SECTOR_T
-typedef long		sector_t;	/* offset- or number- of disk blocks */
-#endif
-
 #include <linux/xfs_behavior.h>
 #include <linux/xfs_vfs.h>
 #include <linux/xfs_cred.h>
@@ -97,10 +121,7 @@
 {
 	bh->b_end_io = linvfs_unwritten_done;
 }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,17)
 BUFFER_FNS(Unwritten, unwritten)
-#endif
 
 #define xfs_refcache_size	xfs_params.refcache_size.val
 #define xfs_refcache_purge_count xfs_params.refcache_purge.val
@@ -220,18 +241,30 @@
 #define howmany(x, y)	(((x)+((y)-1))/(y))
 #define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
 
-/* dump_stack() showed up in 2.4.20, show_stack is arch-specific */
+/*
+ * Juggle IRIX device numbers - still used in ondisk structures
+ */
+#define XFS_DEV_BITSMAJOR	14
+#define XFS_DEV_BITSMINOR	18
+#define XFS_DEV_MAXMAJ		0x1ff
+#define XFS_DEV_MAXMIN		0x3ffff
+#define XFS_DEV_MAJOR(dev)	((int)(((unsigned)(dev)>>XFS_DEV_BITSMINOR) \
+				    & XFS_DEV_MAXMAJ))
+#define XFS_DEV_MINOR(dev)	((int)((dev)&XFS_DEV_MAXMIN))
+#define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \
+				    | (minor&XFS_DEV_MAXMIN)))
+
+#define XFS_DEV_TO_KDEVT(dev)	mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev))
+
+
+/* Produce a kernel stack trace */
+
 static inline void xfs_stack_trace(void)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
 	dump_stack();
-#else
-# if defined(CONFIG_X86) || defined(CONFIG_X86_64)
-	show_stack(0);
-# endif
-#endif
 }
 
+
 /* Move the kernel do_div definition off to one side */
 
 #if defined __i386__
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_lrw.c linux-2.4.23-bk14/fs/xfs/linux/xfs_lrw.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_lrw.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_lrw.c	2003-12-19 02:52:58.000000000 -0800
@@ -321,16 +321,12 @@
 		}
 	}
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
 	if (unlikely(ioflags & IO_ISDIRECT)) {
 		ret = do_generic_direct_read(file, buf, size, offset);
 		UPDATE_ATIME(file->f_dentry->d_inode);
 	} else {
 		ret = generic_file_read(file, buf, size, offset);
 	}
-#else
-	ret = generic_file_read(file, buf, size, offset);
-#endif
 
 	if (!(ioflags & IO_ISLOCKED))
 		xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -713,7 +709,6 @@
 	}
 
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
 	if ((ssize_t) size < 0) {
 		ret = -EINVAL;
 		goto error;
@@ -735,13 +730,6 @@
 					io, buf, size, *offset, ioflags);
 		ret = do_generic_file_write(file, buf, size, offset);
 	}
-#else
-retry:
-	if (ioflags & IO_ISDIRECT) {
-		xfs_inval_cached_pages(vp, io, *offset, 1, 1);
-	}
- 	ret = generic_file_write_nolock(file, buf, size, offset);
-#endif
 
 	if (unlikely(ioflags & IO_INVIS)) {
 		/* generic_file_write updates the mtime/ctime but we need
@@ -770,9 +758,7 @@
 		goto retry;
 	}
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
 error:
-#endif
 	if (ret <= 0) {
 		if (iolock)
 			xfs_rwunlock(bdp, locktype);
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_super.c linux-2.4.23-bk14/fs/xfs/linux/xfs_super.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_super.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_super.c	2003-12-19 02:52:58.000000000 -0800
@@ -116,13 +116,7 @@
 	 */
 
 #if BITS_PER_LONG == 32
-# if defined(CONFIG_LBD)
-	ASSERT(sizeof(sector_t) == 8);
-	pagefactor = PAGE_CACHE_SIZE;
-	bitshift = BITS_PER_LONG;
-# else
 	pagefactor = PAGE_CACHE_SIZE >> (PAGE_CACHE_SHIFT - blockshift);
-# endif
 #endif
 
 	return (((__uint64_t)pagefactor) << bitshift) - 1;
diff -urN linux-2.4.23-bk13/fs/xfs/linux/xfs_sysctl.c linux-2.4.23-bk14/fs/xfs/linux/xfs_sysctl.c
--- linux-2.4.23-bk13/fs/xfs/linux/xfs_sysctl.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/linux/xfs_sysctl.c	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -41,7 +41,6 @@
 
 /* Custom proc handlers */
 
-#ifdef HAVE_REFCACHE
 STATIC int
 xfs_refcache_resize_proc_handler(
 	ctl_table	*ctl,
@@ -66,7 +65,6 @@
 
 	return ret;
 }
-#endif
 
 #ifdef CONFIG_PROC_FS
 STATIC int
@@ -96,8 +94,6 @@
 #endif /* CONFIG_PROC_FS */
 
 STATIC ctl_table xfs_table[] = {
-
-#ifdef HAVE_REFCACHE
 	{XFS_REFCACHE_SIZE, "refcache_size", &xfs_params.refcache_size.val,
 	sizeof(int), 0644, NULL, &xfs_refcache_resize_proc_handler,
 	&sysctl_intvec, NULL, 
@@ -108,7 +104,6 @@
 	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
 	&sysctl_intvec, NULL, 
 	&xfs_params.refcache_purge.min, &xfs_params.refcache_size.val},
-#endif
 
 	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val,
 	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
diff -urN linux-2.4.23-bk13/fs/xfs/pagebuf/page_buf.c linux-2.4.23-bk14/fs/xfs/pagebuf/page_buf.c
--- linux-2.4.23-bk13/fs/xfs/pagebuf/page_buf.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/pagebuf/page_buf.c	2003-12-19 02:52:58.000000000 -0800
@@ -417,9 +417,6 @@
 			page_cache_release(page);
 		}
 	}
-
-	if (pb->pb_pages != pb->pb_page_array)
-		kfree(pb->pb_pages);
 }
 
 /*
@@ -458,20 +455,17 @@
 		if (pb->pb_flags & _PBF_MEM_ALLOCATED) {
 			if (pb->pb_pages) {
 				/* release the pages in the address list */
-				if (pb->pb_pages[0] &&
-				    PageSlab(pb->pb_pages[0])) {
-					/*
-					 * This came from the slab
-					 * allocator free it as such
-					 */
+				if ((pb->pb_pages[0]) &&
+				    (pb->pb_flags & _PBF_MEM_SLAB)) {
 					kfree(pb->pb_addr);
 				} else {
 					_pagebuf_freepages(pb);
 				}
-
+				if (pb->pb_pages != pb->pb_page_array)
+					kfree(pb->pb_pages);
 				pb->pb_pages = NULL;
 			}
-			pb->pb_flags &= ~_PBF_MEM_ALLOCATED;
+			pb->pb_flags &= ~(_PBF_MEM_ALLOCATED|_PBF_MEM_SLAB);
 		}
 	}
 
@@ -847,7 +841,8 @@
 				_PBF_LOCKABLE | \
 				_PBF_ALL_PAGES_MAPPED | \
 				_PBF_ADDR_ALLOCATED | \
-				_PBF_MEM_ALLOCATED;
+				_PBF_MEM_ALLOCATED | \
+				_PBF_MEM_SLAB;
 	PB_TRACE(pb, "got_lock", 0);
 	PB_STATS_INC(pb_get_locked);
 	return (pb);
@@ -927,6 +922,7 @@
 			PB_STATS_INC(pb_get_read);
 			pagebuf_iostart(pb, flags);
 		} else if (flags & PBF_ASYNC) {
+			PB_TRACE(pb, "get_read_async", (unsigned long)flags);
 			/*
 			 * Read ahead call which is already satisfied,
 			 * drop the buffer
@@ -936,12 +932,13 @@
 			pagebuf_rele(pb);
 			return NULL;
 		} else {
+			PB_TRACE(pb, "get_read_done", (unsigned long)flags);
 			/* We do not want read in the flags */
 			pb->pb_flags &= ~PBF_READ;
 		}
+	} else {
+		PB_TRACE(pb, "get_write", (unsigned long)flags);
 	}
-
-	PB_TRACE(pb, "get_done", (unsigned long)flags);
 	return (pb);
 }
 
@@ -1067,8 +1064,8 @@
 	page_buf_t		*pb;
 	size_t			tlen = 0;
 
-	if (len > 0x20000)
-		return(NULL);
+	if (unlikely(len > 0x20000))
+		return NULL;
 
 	pb = pagebuf_allocate(flags);
 	if (!pb)
@@ -1095,7 +1092,7 @@
 		return NULL;
 	}
 	/* otherwise pagebuf_free just ignores it */
-	pb->pb_flags |= _PBF_MEM_ALLOCATED;
+	pb->pb_flags |= (_PBF_MEM_ALLOCATED | _PBF_MEM_SLAB);
 	PB_CLEAR_OWNER(pb);
 	up(&pb->pb_sema);	/* Return unlocked pagebuf */
 
diff -urN linux-2.4.23-bk13/fs/xfs/pagebuf/page_buf.h linux-2.4.23-bk14/fs/xfs/pagebuf/page_buf.h
--- linux-2.4.23-bk13/fs/xfs/pagebuf/page_buf.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/pagebuf/page_buf.h	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -93,12 +93,14 @@
 	_PBF_PRIVATE_BH = (1 << 17), /* do not use public buffer heads	   */
 	_PBF_ALL_PAGES_MAPPED = (1 << 18), /* all pages in range mapped	   */
 	_PBF_ADDR_ALLOCATED = (1 << 19), /* pb_addr space was allocated	   */
-	_PBF_MEM_ALLOCATED = (1 << 20), /* pb_mem+underlying pages alloc'd */
+	_PBF_MEM_ALLOCATED = (1 << 20), /* underlying pages are allocated  */
+	_PBF_MEM_SLAB = (1 << 21), /* underlying pages are slab allocated  */
 
-	PBF_FORCEIO = (1 << 21),
-	PBF_FLUSH = (1 << 22),	/* flush disk write cache		   */
-	PBF_READ_AHEAD = (1 << 23),
-	PBF_RUN_QUEUES = (1 << 24), /* run block device task queue	   */
+	PBF_FORCEIO = (1 << 22), /* ignore any cache state		   */
+	PBF_FLUSH = (1 << 23),	/* flush disk write cache		   */
+	PBF_READ_AHEAD = (1 << 24), /* asynchronous read-ahead		   */
+	PBF_RUN_QUEUES = (1 << 25), /* run block device task queue	   */
+	PBF_DIRECTIO = (1 << 26), /* used for a direct IO mapping	   */
 
 } page_buf_flags_t;
 
@@ -338,6 +340,7 @@
 # define pagebuf_trace(pb, id, ptr, ra)	do { } while (0)
 #endif
 
+#define pagebuf_target_name(target)	bdevname((target)->pbr_kdev)
 
 /*
  * Kernel version compatibility macros
diff -urN linux-2.4.23-bk13/fs/xfs/quota/xfs_dquot.c linux-2.4.23-bk14/fs/xfs/quota/xfs_dquot.c
--- linux-2.4.23-bk13/fs/xfs/quota/xfs_dquot.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/quota/xfs_dquot.c	2003-12-19 02:52:58.000000000 -0800
@@ -1508,7 +1508,7 @@
 	 */
 	ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
 
-	dqp->q_mount = NULL;;
+	dqp->q_mount = NULL;
 	dqp->q_hash = NULL;
 	dqp->dq_flags = XFS_DQ_INACTIVE;
 	memset(&dqp->q_core, 0, sizeof(dqp->q_core));
diff -urN linux-2.4.23-bk13/fs/xfs/support/uuid.c linux-2.4.23-bk14/fs/xfs/support/uuid.c
--- linux-2.4.23-bk13/fs/xfs/support/uuid.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/support/uuid.c	2003-12-19 02:52:58.000000000 -0800
@@ -30,9 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/types.h>
-#include <xfs_types.h>
-#include <xfs_arch.h>
+#include <xfs.h>
 #include "time.h"
 #include "uuid.h"
 #include "kmem.h"
diff -urN linux-2.4.23-bk13/fs/xfs/xfs.h linux-2.4.23-bk14/fs/xfs/xfs.h
--- linux-2.4.23-bk13/fs/xfs/xfs.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs.h	2003-12-19 02:52:58.000000000 -0800
@@ -32,25 +32,6 @@
 #ifndef __XFS_H__
 #define __XFS_H__
 
-#include <linux/types.h>
-#include <linux/config.h>
-#include <xfs_types.h>
-
-#include <xfs_arch.h>
-
-#include <support/kmem.h>
-#include <support/mrlock.h>
-#include <support/qsort.h>
-#include <support/spin.h>
-#include <support/sv.h>
-#include <support/ktrace.h>
-#include <support/mutex.h>
-#include <support/sema.h>
-#include <support/debug.h>
-#include <support/move.h>
-#include <support/uuid.h>
-#include <support/time.h>
-
 #include <linux/xfs_linux.h>
 
 #include <xfs_fs.h> 
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_acl.h linux-2.4.23-bk14/fs/xfs/xfs_acl.h
--- linux-2.4.23-bk13/fs/xfs/xfs_acl.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_acl.h	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -102,6 +102,8 @@
 #define xfs_acl_vset(v,p,sz,t)	(-EOPNOTSUPP)
 #define xfs_acl_vget(v,p,sz,t)	(-EOPNOTSUPP)
 #define xfs_acl_vremove(v,t)	(-EOPNOTSUPP)
+#define xfs_acl_vhasacl_access(v)	(0)
+#define xfs_acl_vhasacl_default(v)	(0)
 #define _ACL_DECL(a)		((void)0)
 #define _ACL_ALLOC(a)		(1)	/* successfully allocate nothing */
 #define _ACL_FREE(a)		((void)0)
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_attr.c linux-2.4.23-bk14/fs/xfs/xfs_attr.c
--- linux-2.4.23-bk13/fs/xfs/xfs_attr.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_attr.c	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -63,6 +63,7 @@
 #include "xfs_quota.h"
 #include "xfs_rw.h"
 #include "xfs_trans_space.h"
+#include "xfs_acl.h"
 
 /*
  * xfs_attr.c
@@ -2357,3 +2358,307 @@
 					 (void *)a14, (void *)a15);
 }
 #endif	/* XFS_ATTR_TRACE */
+
+
+/*========================================================================
+ * System (pseudo) namespace attribute interface routines.
+ *========================================================================*/
+
+STATIC int
+posix_acl_access_set(
+	vnode_t	*vp, char *name, void *data, size_t size, int xflags)
+{
+	return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
+}
+
+STATIC int
+posix_acl_access_remove(
+	struct vnode *vp, char *name, int xflags)
+{
+	return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
+}
+
+STATIC int
+posix_acl_access_get(
+	vnode_t *vp, char *name, void *data, size_t size, int xflags)
+{
+	return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
+}
+
+STATIC int
+posix_acl_access_exists(
+	vnode_t *vp)
+{
+	return xfs_acl_vhasacl_access(vp);
+}
+
+STATIC int
+posix_acl_default_set(
+	vnode_t	*vp, char *name, void *data, size_t size, int xflags)
+{
+	return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
+}
+
+STATIC int
+posix_acl_default_get(
+	vnode_t *vp, char *name, void *data, size_t size, int xflags)
+{
+	return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
+}
+
+STATIC int
+posix_acl_default_remove(
+	struct vnode *vp, char *name, int xflags)
+{
+	return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
+}
+
+STATIC int
+posix_acl_default_exists(
+	vnode_t *vp)
+{
+	return xfs_acl_vhasacl_default(vp);
+}
+
+struct attrnames posix_acl_access = {
+	.attr_name	= "posix_acl_access",
+	.attr_namelen	= sizeof("posix_acl_access") - 1,
+	.attr_get	= posix_acl_access_get,
+	.attr_set	= posix_acl_access_set,
+	.attr_remove	= posix_acl_access_remove,
+	.attr_exists	= posix_acl_access_exists,
+};
+
+struct attrnames posix_acl_default = {
+	.attr_name	= "posix_acl_default",
+	.attr_namelen	= sizeof("posix_acl_default") - 1,
+	.attr_get	= posix_acl_default_get,
+	.attr_set	= posix_acl_default_set,
+	.attr_remove	= posix_acl_default_remove,
+	.attr_exists	= posix_acl_default_exists,
+};
+
+struct attrnames *attr_system_names[] =
+	{ &posix_acl_access, &posix_acl_default };
+
+
+/*========================================================================
+ * Namespace-prefix-style attribute name interface routines.
+ *========================================================================*/
+
+STATIC int
+attr_generic_set(
+	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+{
+	int 	error;
+
+	VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);
+	return -error;
+}
+
+STATIC int
+attr_generic_get(
+	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+{
+	int	error, asize = size;
+
+	VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error);
+	if (!error)
+		return asize;
+	return -error;
+}
+
+STATIC int
+attr_generic_remove(
+	struct vnode *vp, char *name, int xflags)
+{
+	int	error;
+
+	VOP_ATTR_REMOVE(vp, name, xflags, NULL, error);
+	return -error;
+}
+
+STATIC int
+attr_generic_listadd(
+	attrnames_t		*prefix,
+	attrnames_t		*namesp,
+	void			*data,
+	size_t			size,
+	ssize_t			*result)
+{
+	char			*p = data + *result;
+
+	*result += prefix->attr_namelen;
+	*result += namesp->attr_namelen + 1;
+	if (!size)
+		return 0;
+	if (*result > size)
+		return -ERANGE;
+	strcpy(p, prefix->attr_name);
+	p += prefix->attr_namelen;
+	strcpy(p, namesp->attr_name);
+	p += namesp->attr_namelen + 1;
+	return 0;
+}
+
+STATIC int
+attr_system_list(
+	struct vnode		*vp,
+	void			*data,
+	size_t			size,
+	ssize_t			*result)
+{
+	attrnames_t		*namesp;
+	int			i, error = 0;
+
+	for (i = 0; i < ATTR_SYSCOUNT; i++) {
+		namesp = attr_system_names[i];
+		if (!namesp->attr_exists || !namesp->attr_exists(vp))
+			continue;
+		error = attr_generic_listadd(&attr_system, namesp,
+						data, size, result);
+		if (error)
+			break;
+	}
+	return error;
+}
+
+int
+attr_generic_list(
+	struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result)
+{
+	attrlist_cursor_kern_t	cursor = { 0 };
+	int			error;
+
+	VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
+	if (error > 0)
+		return -error;
+	*result = -error;
+	return attr_system_list(vp, data, size, result);
+}
+
+attrnames_t *
+attr_lookup_namespace(
+	char			*name,
+	struct attrnames	**names,
+	int			nnames)
+{
+	int			i;
+
+	for (i = 0; i < nnames; i++)
+		if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
+			return names[i];
+	return NULL;
+}
+
+/*
+ * Some checks to prevent people abusing EAs to get over quota:
+ * - Don't allow modifying user EAs on devices/symlinks;
+ * - Don't allow modifying user EAs if sticky bit set;
+ */
+STATIC int
+attr_user_capable(
+	struct vnode	*vp,
+	cred_t		*cred)
+{
+	struct inode	*inode = LINVFS_GET_IP(vp);
+
+	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+		return -EPERM;
+	if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
+	    !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
+	    (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+	return 0;
+}
+
+STATIC int
+attr_trusted_capable(
+	struct vnode	*vp,
+	cred_t		*cred)
+{
+	struct inode	*inode = LINVFS_GET_IP(vp);
+
+	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+		return -EPERM;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
+STATIC int
+attr_system_set(
+	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+{
+	attrnames_t	*namesp;
+	int		error;
+
+	if (xflags & ATTR_CREATE)
+		return -EINVAL;
+
+	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	error = namesp->attr_set(vp, name, data, size, xflags);
+	if (!error)
+		error = vn_revalidate(vp);
+	return error;
+}
+
+STATIC int
+attr_system_get(
+	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+{
+	attrnames_t	*namesp;
+
+	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	return namesp->attr_get(vp, name, data, size, xflags);
+}
+
+STATIC int
+attr_system_remove(
+	struct vnode *vp, char *name, int xflags)
+{
+	attrnames_t	*namesp;
+
+	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
+	if (!namesp)
+		return -EOPNOTSUPP;
+	return namesp->attr_remove(vp, name, xflags);
+}
+
+struct attrnames attr_system = {
+	.attr_name	= "system.",
+	.attr_namelen	= sizeof("system.") - 1,
+	.attr_flag	= ATTR_SYSTEM,
+	.attr_get	= attr_system_get,
+	.attr_set	= attr_system_set,
+	.attr_remove	= attr_system_remove,
+	.attr_capable	= (attrcapable_t)fs_noerr,
+};
+
+struct attrnames attr_trusted = {
+	.attr_name	= "trusted.",
+	.attr_namelen	= sizeof("trusted.") - 1,
+	.attr_flag	= ATTR_ROOT,
+	.attr_get	= attr_generic_get,
+	.attr_set	= attr_generic_set,
+	.attr_remove	= attr_generic_remove,
+	.attr_capable	= attr_trusted_capable,
+};
+
+struct attrnames attr_user = {
+	.attr_name	= "user.",
+	.attr_namelen	= sizeof("user.") - 1,
+	.attr_get	= attr_generic_get,
+	.attr_set	= attr_generic_set,
+	.attr_remove	= attr_generic_remove,
+	.attr_capable	= attr_user_capable,
+};
+
+struct attrnames *attr_namespaces[] =
+	{ &attr_system, &attr_trusted, &attr_user };
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_attr.h linux-2.4.23-bk14/fs/xfs/xfs_attr.h
--- linux-2.4.23-bk13/fs/xfs/xfs_attr.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_attr.h	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000, 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -49,9 +49,46 @@
  * External interfaces
  *========================================================================*/
 
-#define ATTR_ROOT	0x0002	/* use attrs in root namespace, not user */
+struct cred;
+struct vnode;
+
+typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int);
+typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int);
+typedef int (*attrremove_t)(struct vnode *, char *, int);
+typedef int (*attrexists_t)(struct vnode *);
+typedef int (*attrcapable_t)(struct vnode *, struct cred *);
+
+typedef struct attrnames {
+	char *		attr_name;
+	unsigned int	attr_namelen;
+	unsigned int	attr_flag;
+	attrget_t	attr_get;
+	attrset_t	attr_set;
+	attrremove_t	attr_remove;
+	attrexists_t	attr_exists;
+	attrcapable_t	attr_capable;
+} attrnames_t;
+
+#define ATTR_NAMECOUNT	3
+extern struct attrnames attr_user;
+extern struct attrnames attr_system;
+extern struct attrnames attr_trusted;
+extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
+
+#define ATTR_SYSCOUNT	2
+extern struct attrnames posix_acl_access;
+extern struct attrnames posix_acl_default;
+extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+
+extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
+extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
+
+#define ATTR_DONTFOLLOW	0x0001	/* -- unused, from IRIX -- */
+#define ATTR_ROOT	0x0002	/* use attrs in root (trusted) namespace */
+#define ATTR_TRUST	0x0004	/* -- unused, from IRIX -- */
 #define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
 #define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
+#define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
 #define ATTR_KERNOTIME	0x1000	/* [kernel] don't update inode timestamps */
 #define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */
 #define ATTR_KERNAMELS	0x4000	/* [kernel] list attr names (simple list) */
@@ -126,11 +163,8 @@
  * Function prototypes for the kernel.
  *========================================================================*/
 
-struct cred;
-struct vnode;
 struct xfs_inode;
 struct attrlist_cursor_kern;
-struct xfs_ext_attr;
 struct xfs_da_args;
 
 /*
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_attr_leaf.c linux-2.4.23-bk14/fs/xfs/xfs_attr_leaf.c
--- linux-2.4.23-bk13/fs/xfs/xfs_attr_leaf.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_attr_leaf.c	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -444,8 +444,10 @@
 							< context->bufsize) {
 		for (i = 0, sfe = &sf->list[0];
 				i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
-			int ns = (sfe->flags & XFS_ATTR_ROOT)?
-						ROOT_NAMES : USER_NAMES;
+			attrnames_t	*namesp;
+
+			namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+				  &attr_user;
 			if (((context->flags & ATTR_ROOT) != 0) !=
 			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
 			    !(context->flags & ATTR_KERNFULLS)) {
@@ -454,11 +456,11 @@
 			}
 			if (context->flags & ATTR_KERNOVAL) {
 				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += xfs_namespaces[ns].namelen +
+				context->count += namesp->attr_namelen +
 					INT_GET(sfe->namelen, ARCH_CONVERT) + 1;
 			}
 			else {
-				if (xfs_attr_put_listent(context, ns,
+				if (xfs_attr_put_listent(context, namesp,
 						   (char *)sfe->nameval,
 						   (int)sfe->namelen,
 						   (int)INT_GET(sfe->valuelen,
@@ -544,18 +546,22 @@
 	 * Loop putting entries into the user buffer.
 	 */
 	for ( ; i < nsbuf; i++, sbp++) {
-		int ns = (sbp->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES;
+		attrnames_t	*namesp;
+
+		namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+			  &attr_user;
+
 		if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) {
 			cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT);
 			cursor->offset = 0;
 		}
 		if (context->flags & ATTR_KERNOVAL) {
 			ASSERT(context->flags & ATTR_KERNAMELS);
-			context->count += xfs_namespaces[ns].namelen
-					+ sbp->namelen + 1;
+			context->count += namesp->attr_namelen +
+						sbp->namelen + 1;
 		}
 		else {
-			if (xfs_attr_put_listent(context, ns,
+			if (xfs_attr_put_listent(context, namesp,
 					sbp->name, sbp->namelen,
 					INT_GET(sbp->valuelen, ARCH_CONVERT)))
 				break;
@@ -2270,7 +2276,7 @@
 	retval = 0;
 	for (  ; (i < INT_GET(leaf->hdr.count, ARCH_CONVERT))
 	     && (retval == 0); entry++, i++) {
-		int ns = (entry->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES;
+		attrnames_t	*namesp;
 
 		if (INT_GET(entry->hashval, ARCH_CONVERT) != cursor->hashval) {
 			cursor->hashval = INT_GET(entry->hashval, ARCH_CONVERT);
@@ -2284,14 +2290,17 @@
 		    !(context->flags & ATTR_KERNFULLS))
 			continue;		/* skip non-matching entries */
 
+		namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+			  &attr_user;
+
 		if (entry->flags & XFS_ATTR_LOCAL) {
 			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
 			if (context->flags & ATTR_KERNOVAL) {
 				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += xfs_namespaces[ns].namelen
-						+ (int)name_loc->namelen + 1;
+				context->count += namesp->attr_namelen +
+						(int)name_loc->namelen + 1;
 			} else {
-				retval = xfs_attr_put_listent(context, ns,
+				retval = xfs_attr_put_listent(context, namesp,
 					(char *)name_loc->nameval,
 					(int)name_loc->namelen,
 					(int)INT_GET(name_loc->valuelen,
@@ -2301,10 +2310,10 @@
 			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
 			if (context->flags & ATTR_KERNOVAL) {
 				ASSERT(context->flags & ATTR_KERNAMELS);
-				context->count += xfs_namespaces[ns].namelen
-						+ (int)name_rmt->namelen + 1;
+				context->count += namesp->attr_namelen +
+						(int)name_rmt->namelen + 1;
 			} else {
-				retval = xfs_attr_put_listent(context, ns,
+				retval = xfs_attr_put_listent(context, namesp,
 					(char *)name_rmt->name,
 					(int)name_rmt->namelen,
 					(int)INT_GET(name_rmt->valuelen,
@@ -2333,7 +2342,7 @@
 /*ARGSUSED*/
 int
 xfs_attr_put_listent(xfs_attr_list_context_t *context,
-		     int ns, char *name, int namelen, int valuelen)
+		     attrnames_t *namesp, char *name, int namelen, int valuelen)
 {
 	attrlist_ent_t *aep;
 	int arraytop;
@@ -2341,23 +2350,21 @@
 	ASSERT(!(context->flags & ATTR_KERNOVAL));
 	if (context->flags & ATTR_KERNAMELS) {
 		char *offset;
-		xattr_namespace_t *nsp;
 
 		ASSERT(context->count >= 0);
 
-		nsp = &xfs_namespaces[ns];
-		arraytop = context->count + nsp->namelen + namelen+1;
+		arraytop = context->count + namesp->attr_namelen + namelen + 1;
 		if (arraytop > context->firstu) {
 			context->count = -1;	/* insufficient space */
 			return(1);
 		}
 		offset = (char *)context->alist + context->count;
-		strncpy(offset, nsp->name, nsp->namelen);	/* namespace */
-		offset += nsp->namelen;
+		strncpy(offset, namesp->attr_name, namesp->attr_namelen);
+		offset += namesp->attr_namelen;
 		strncpy(offset, name, namelen);			/* real name */
 		offset += namelen;
 		*offset = '\0';
-		context->count += nsp->namelen + namelen + 1;
+		context->count += namesp->attr_namelen + namelen + 1;
 		return(0);
 	}
 
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_attr_leaf.h linux-2.4.23-bk14/fs/xfs/xfs_attr_leaf.h
--- linux-2.4.23-bk13/fs/xfs/xfs_attr_leaf.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_attr_leaf.h	2003-12-19 02:52:58.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000, 2002-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -44,6 +44,7 @@
 
 struct attrlist;
 struct attrlist_cursor_kern;
+struct attrnames;
 struct xfs_dabuf;
 struct xfs_da_args;
 struct xfs_da_state;
@@ -128,7 +129,7 @@
  * on the system call, they are "or"ed together for various operations.
  */
 #define	XFS_ATTR_LOCAL_BIT	0	/* attr is stored locally */
-#define	XFS_ATTR_ROOT_BIT	1	/* limit access to attr to userid 0 */
+#define	XFS_ATTR_ROOT_BIT	1	/* limit access to trusted attrs */
 #define	XFS_ATTR_INCOMPLETE_BIT	7	/* attr in middle of create/delete */
 #define XFS_ATTR_LOCAL		(1 << XFS_ATTR_LOCAL_BIT)
 #define XFS_ATTR_ROOT		(1 << XFS_ATTR_ROOT_BIT)
@@ -299,7 +300,8 @@
 					int *local);
 int	xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
 int	xfs_attr_put_listent(struct xfs_attr_list_context *context,
-			     int ns, char *name, int namelen, int valuelen);
+			     struct attrnames *, char *name, int namelen,
+			     int valuelen);
 int	xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
 
 #endif	/* __XFS_ATTR_LEAF_H__ */
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_buf.h linux-2.4.23-bk14/fs/xfs/xfs_buf.h
--- linux-2.4.23-bk13/fs/xfs/xfs_buf.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_buf.h	2003-12-19 02:52:58.000000000 -0800
@@ -181,7 +181,7 @@
 #define XFS_BUF_SET_VTYPE(bp, type)
 #define XFS_BUF_SET_REF(bp, ref)
 
-#define XFS_BUF_ISPINNED(bp)   pagebuf_ispin(bp)
+#define XFS_BUF_ISPINNED(bp)	pagebuf_ispin(bp)
 
 #define XFS_BUF_VALUSEMA(bp)	pagebuf_lock_value(bp)
 #define XFS_BUF_CPSEMA(bp)	(pagebuf_cond_lock(bp) == 0)
@@ -191,16 +191,10 @@
 
 /* setup the buffer target from a buftarg structure */
 #define XFS_BUF_SET_TARGET(bp, target)	\
-	(bp)->pb_target = (target)
-
+		(bp)->pb_target = (target)
 #define XFS_BUF_TARGET(bp)	((bp)->pb_target)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#define XFS_BUFTARG_NAME(target)    bdevname((target)->pbr_kdev)
-#else
-#define XFS_BUFTARG_NAME(target) \
-	({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; })
-#endif
+#define XFS_BUFTARG_NAME(target)	\
+		pagebuf_target_name(target)
 
 #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
 #define XFS_BUF_SET_VTYPE(bp, type)
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_log.c linux-2.4.23-bk14/fs/xfs/xfs_log.c
--- linux-2.4.23-bk13/fs/xfs/xfs_log.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_log.c	2003-12-19 02:52:58.000000000 -0800
@@ -1056,7 +1056,7 @@
 			if (xfs_physmem <= btoc(128*1024*1024)) { 
 				log->l_iclog_bufs = XLOG_MIN_ICLOGS; 
 			} else if (xfs_physmem <= btoc(400*1024*1024)) { 
-				log->l_iclog_bufs = XLOG_MED_ICLOGS;; 
+				log->l_iclog_bufs = XLOG_MED_ICLOGS; 
 			} else {
 				/* 256K with 32K bufs */
 				log->l_iclog_bufs = XLOG_MAX_ICLOGS;
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_rename.c linux-2.4.23-bk14/fs/xfs/xfs_rename.c
--- linux-2.4.23-bk13/fs/xfs/xfs_rename.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_rename.c	2003-12-19 02:52:58.000000000 -0800
@@ -485,7 +485,7 @@
 		error = xfs_droplink(tp, target_ip);
 		if (error) {
 			rename_which_error_return = __LINE__;
-			goto abort_return;;
+			goto abort_return;
 		}
 		target_ip_dropped = 1;
 
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_trans.c linux-2.4.23-bk14/fs/xfs/xfs_trans.c
--- linux-2.4.23-bk13/fs/xfs/xfs_trans.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_trans.c	2003-12-19 02:52:58.000000000 -0800
@@ -142,9 +142,9 @@
 	uint		type)
 {
 	xfs_trans_t	*tp;
+
 	ASSERT(xfs_trans_zone != NULL);
 	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
-	tp->t_dqinfo = NULL;
 
 	/*
 	 * Initialize the transaction structure.
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_types.h linux-2.4.23-bk14/fs/xfs/xfs_types.h
--- linux-2.4.23-bk13/fs/xfs/xfs_types.h	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_types.h	2003-12-19 02:52:58.000000000 -0800
@@ -75,24 +75,6 @@
 #error BITS_PER_LONG must be 32 or 64
 #endif
 
-/*
- * Some types are conditional depending on the target system.
- * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits.
- * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well
- * as requiring XFS_BIG_BLKNOS to be set.
- */
-#if defined(CONFIG_LBD) || (defined(HAVE_SECTOR_T) && (BITS_PER_LONG == 64))
-# define XFS_BIG_BLKNOS	1
-# if BITS_PER_LONG == 64
-#  define XFS_BIG_INUMS	1
-# else
-#  define XFS_BIG_INUMS	0
-# endif
-#else
-# define XFS_BIG_BLKNOS	0
-# define XFS_BIG_INUMS	0
-#endif
-
 #endif	/* __KERNEL__ */
 
 typedef __uint32_t	xfs_agblock_t;	/* blockno in alloc. group */
@@ -197,20 +179,4 @@
 	XFS_BTNUM_MAX
 } xfs_btnum_t;
 
-
-/*
- * Juggle IRIX device numbers - still used in ondisk structures
- */
-#define XFS_DEV_BITSMAJOR	14
-#define XFS_DEV_BITSMINOR	18
-#define XFS_DEV_MAXMAJ		0x1ff
-#define XFS_DEV_MAXMIN		0x3ffff
-#define XFS_DEV_MAJOR(dev)	((int)(((unsigned)(dev)>>XFS_DEV_BITSMINOR) \
-				    & XFS_DEV_MAXMAJ))
-#define XFS_DEV_MINOR(dev)	((int)((dev)&XFS_DEV_MAXMIN))
-#define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \
-				    | (minor&XFS_DEV_MAXMIN)))
-
-#define XFS_DEV_TO_KDEVT(dev)	mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev))
-
 #endif	/* __XFS_TYPES_H__ */
diff -urN linux-2.4.23-bk13/fs/xfs/xfs_vfsops.c linux-2.4.23-bk14/fs/xfs/xfs_vfsops.c
--- linux-2.4.23-bk13/fs/xfs/xfs_vfsops.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfs_vfsops.c	2003-12-19 02:52:58.000000000 -0800
@@ -772,8 +772,9 @@
 #if XFS_BIG_INUMS
 		if (!mp->m_inoadd)
 #endif
-			statp->f_files =
-			    min_t(sector_t, statp->f_files, mp->m_maxicount);
+			statp->f_files = min_t(typeof(statp->f_files),
+						statp->f_files,
+						mp->m_maxicount);
 	statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
 	XFS_SB_UNLOCK(mp, s);
 
@@ -1782,10 +1783,14 @@
 		char	*str;
 	} xfs_info[] = {
 		/* the few simple ones we can get from the mount struct */
+		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },
+		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },
 		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },
+		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },
 		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY },
 		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC },
-		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },
+		{ XFS_MOUNT_NOLOGFLUSH,		"," MNTOPT_NOLOGFLUSH },
+		{ XFS_MOUNT_IDELETE,		"," MNTOPT_NOIKEEP },
 		{ 0, NULL }
 	};
 	struct proc_xfs_info	*xfs_infop;
@@ -1821,6 +1826,9 @@
 		seq_printf(m, "," MNTOPT_SWIDTH "=%d",
 				(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
 
+	if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT))
+		seq_printf(m, "," MNTOPT_64BITINODE);
+	
 	return 0;
 }
 
diff -urN linux-2.4.23-bk13/fs/xfs/xfsidbg.c linux-2.4.23-bk14/fs/xfs/xfsidbg.c
--- linux-2.4.23-bk13/fs/xfs/xfsidbg.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/fs/xfs/xfsidbg.c	2003-12-19 02:52:58.000000000 -0800
@@ -3177,13 +3177,13 @@
 	static char *attr_arg_flags[] = {
 		"DONTFOLLOW",	/* 0x0001 */
 		"ROOT",		/* 0x0002 */
-		"?",		/* 0x0004 */
-		"REPLACE",	/* 0x0008 */
+		"TRUSTED",	/* 0x0004 */
+		"?",		/* 0x0008 */
 		"CREATE",	/* 0x0010 */
-		"?",		/* 0x0020 */
+		"REPLACE",	/* 0x0020 */
 		"?",		/* 0x0040 */
 		"?",		/* 0x0080 */
-		"?",		/* 0x0100 */
+		"SYSTEM",	/* 0x0100 */
 		"?",		/* 0x0200 */
 		"?",		/* 0x0400 */
 		"?",		/* 0x0800 */
diff -urN linux-2.4.23-bk13/include/asm-ppc64/hvcall.h linux-2.4.23-bk14/include/asm-ppc64/hvcall.h
--- linux-2.4.23-bk13/include/asm-ppc64/hvcall.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk14/include/asm-ppc64/hvcall.h	2003-12-19 02:52:58.000000000 -0800
@@ -59,7 +59,7 @@
 #define H_XIRR			0x74
 #define H_PERFMON		0x7c
 
-#define HSC			".long 0x44000022\n"
+#define HVSC			".long 0x44000022\n"
 #define H_ENTER_r3		"li	3, 0x08\n"
 
 /* plpar_hcall() -- Generic call interface using above opcodes
@@ -84,3 +84,34 @@
  */
 long plpar_hcall_norets(unsigned long opcode, ...);
 
+/*
+ * Special hcall interface for ibmveth support.
+ * Takes 8 input parms. Returns a rc and stores the
+ * R4 return value in *out1.
+ */
+long plpar_hcall_8arg_2ret(unsigned long opcode,
+			unsigned long arg1,
+			unsigned long arg2,
+			unsigned long arg3,
+			unsigned long arg4,
+			unsigned long arg5,
+			unsigned long arg6,
+			unsigned long arg7,
+			unsigned long arg8,
+			unsigned long *out1);
+
+
+/* plpar_hcall_4out()
+ *
+ * same as plpar_hcall except with 4 output arguments.
+ *
+ */
+long plpar_hcall_4out(unsigned long opcode,
+		      unsigned long arg1,
+		      unsigned long arg2,
+		      unsigned long arg3,
+		      unsigned long arg4,
+		      unsigned long *out1,
+		      unsigned long *out2,
+		      unsigned long *out3,
+		      unsigned long *out4);
diff -urN linux-2.4.23-bk13/include/asm-ppc64/hw_irq.h linux-2.4.23-bk14/include/asm-ppc64/hw_irq.h
--- linux-2.4.23-bk13/include/asm-ppc64/hw_irq.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-bk14/include/asm-ppc64/hw_irq.h	2003-12-19 02:52:58.000000000 -0800
@@ -71,9 +71,21 @@
 
 #endif /* CONFIG_PPC_ISERIES */
 
-#define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);})
-#define unmask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq);})
-#define ack_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->ack) irq_desc[irq].handler->ack(irq);})
+#define mask_irq(irq) ({ 				\
+	irq_desc_t *desc = irqdesc(irq);		\
+	if (desc->handler && desc->handler->disable)	\
+		desc->handler->disable(irq);		\
+})
+#define unmask_irq(irq) ({				\
+	irq_desc_t *desc = irqdesc(irq);		\
+	if (desc->handler && desc->handler->enable)	\
+		desc->handler->enable(irq);		\
+})
+#define ack_irq(irq) ({					\
+	irq_desc_t *desc = irqdesc(irq);		\
+	if (desc->handler && desc->handler->ack)	\
+		desc->handler->ack(irq);		\
+})
 
 /* Should we handle this via lost interrupts and IPIs or should we don't care like
  * we do now ? --BenH.
diff -urN linux-2.4.23-bk13/include/asm-ppc64/irq.h linux-2.4.23-bk14/include/asm-ppc64/irq.h
--- linux-2.4.23-bk13/include/asm-ppc64/irq.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-bk14/include/asm-ppc64/irq.h	2003-12-19 02:52:58.000000000 -0800
@@ -15,31 +15,22 @@
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
 
-/*
- * this is the maximum number of virtual irqs we will use.
- */
-#define NR_IRQS			512
+/* Need to keep at 256 (minimum) for iSeries */
+#define NR_IRQS  256
 
-#define NUM_8259_INTERRUPTS	16
+#define MAX_IRQS (1<<24)
 
-/* Interrupt numbers are virtual in case they are sparsely
- * distributed by the hardware.
- */
-#define NR_HW_IRQS		8192
-extern unsigned short real_irq_to_virt_map[NR_HW_IRQS];
-extern unsigned short virt_irq_to_real_map[NR_IRQS];
-/* Create a mapping for a real_irq if it doesn't already exist.
- * Return the virtual irq as a convenience.
- */
-unsigned long virt_irq_create_mapping(unsigned long real_irq);
+extern unsigned int _next_irq(unsigned int irq);
 
-/* These funcs map irqs between real and virtual */
-static inline unsigned long real_irq_to_virt(unsigned long real_irq) {
-	return real_irq_to_virt_map[real_irq];
-}
-static inline unsigned long virt_irq_to_real(unsigned long virt_irq) {
-	return virt_irq_to_real_map[virt_irq];
-}
+/* Define a way to iterate across irqs fairly efficiently. */
+#define for_each_irq(i) \
+	for ((i) = 0; (i) < MAX_IRQS; (i) = _next_irq(i))
+
+
+extern void *_irqdesc(unsigned int irq);
+extern void *_real_irqdesc(unsigned int irq);
+#define irqdesc(irq) ((irq_desc_t *)_irqdesc(irq))
+#define real_irqdesc(irq) ((irq_desc_t *)_real_irqdesc(irq))
 
 /*
  * This gets called from serial.c, which is now used on
@@ -51,5 +42,34 @@
 	return irq;
 }
 
+/*
+ * Because many systems have two overlapping names spaces for
+ * interrupts (ISA and XICS for example), and the ISA interrupts
+ * have historically not been easy to renumber, we allow ISA
+ * interrupts to take values 0 - 15, and shift up the remaining
+ * interrupts by 0x10.
+ *
+ * This would be nice to remove at some point as it adds confusion
+ * and adds a nasty end case if any platform native interrupts have
+ * values within 0x10 of the end of that namespace.
+ */
+
+#define NUM_ISA_INTERRUPTS	0x10
+
+extern inline int irq_offset_up(int irq)
+{
+	return(irq + NUM_ISA_INTERRUPTS);
+}
+
+extern inline int irq_offset_down(int irq)
+{
+	return(irq - NUM_ISA_INTERRUPTS);
+}
+
+extern inline int irq_offset_value(void)
+{
+	return NUM_ISA_INTERRUPTS;
+}
+
 #endif /* _ASM_IRQ_H */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.23-bk13/include/asm-ppc64/machdep.h linux-2.4.23-bk14/include/asm-ppc64/machdep.h
--- linux-2.4.23-bk13/include/asm-ppc64/machdep.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-bk14/include/asm-ppc64/machdep.h	2003-12-19 02:52:58.000000000 -0800
@@ -10,6 +10,8 @@
  */
 
 #include <linux/config.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
 
 struct pt_regs;
 struct pci_bus;	
@@ -62,6 +64,7 @@
 	unsigned int	(*irq_cannonicalize)(unsigned int irq);
 	void		(*init_IRQ)(void);
 	void		(*init_ras_IRQ)(void);
+	void		(*init_irq_desc)(irq_desc_t *desc);
 	int		(*get_irq)(struct pt_regs *);
 	
 	/* A general init function, called by ppc_init in init/main.c.
diff -urN linux-2.4.23-bk13/mm/page_alloc.c linux-2.4.23-bk14/mm/page_alloc.c
--- linux-2.4.23-bk13/mm/page_alloc.c	2003-12-19 02:52:51.000000000 -0800
+++ linux-2.4.23-bk14/mm/page_alloc.c	2003-12-19 02:52:58.000000000 -0800
@@ -378,7 +378,7 @@
 
 	/* here we're in the low on memory slow path */
 
-	if (((current->flags & PF_MEMALLOC) && 
+	if ((current->flags & PF_MEMALLOC) && 
 			(!in_interrupt() || (current->flags & PF_MEMDIE))) {
 		zone = zonelist->zones;
 		for (;;) {
