All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
       [not found] <no>
@ 2008-08-15  2:20 ` Yinghai Lu
  2008-08-15  2:20   ` [PATCH 1/7] x86: some debug info for 32bit sparse_irq Yinghai Lu
  2008-08-15  8:27   ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Ingo Molnar
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                   ` (37 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

	fix the 32bit with bigsmp
	fix 64 bit with irq migration
	ordering functions in io_apic_xx.c


to do:
    merge io_apic_xx.c

Thanks

Yinghai Lu


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/7] x86: some debug info for 32bit sparse_irq
  2008-08-15  2:20 ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Yinghai Lu
@ 2008-08-15  2:20   ` Yinghai Lu
  2008-08-15  2:20     ` [PATCH 2/7] x86: remove union about dest for log/phy Yinghai Lu
  2008-08-15  8:27   ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Ingo Molnar
  1 sibling, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

so could figure out who get interrupt, but vector_irq is not initialized.

Signed-off-by: Yinghai Lu  <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_32.c |    8 ++++++--
 arch/x86/kernel/io_apic_64.c |    2 ++
 arch/x86/kernel/irq_32.c     |    4 ++--
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 9e111d6..429889d 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -1120,8 +1120,12 @@ next:
                         cfg->move_in_progress = 1;
                         cfg->old_domain = cfg->domain;
                 }
-                for_each_cpu_mask_nr(new_cpu, new_mask)
-                        per_cpu(vector_irq, new_cpu)[vector] = irq;
+		printk(KERN_DEBUG "assign_irq_vector: irq %d vector %#x cpu ", irq, vector);
+		for_each_cpu_mask_nr(new_cpu, new_mask) {
+			per_cpu(vector_irq, new_cpu)[vector] = irq;
+			printk(KERN_CONT " %d ", new_cpu);
+		}
+		printk(KERN_CONT "\n");
                 cfg->vector = vector;
                 cfg->domain = domain;
                 return 0;
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index a11515f..4d1b02d 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -1392,6 +1392,8 @@ __apicdebuginit(void) print_IO_APIC(void)
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
 
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 63b4f6c..30b58b3 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -237,8 +237,8 @@ unsigned int do_IRQ(struct pt_regs *regs)
 
 	desc = irq_desc(irq);
 	if (unlikely(!desc)) {
-		printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x\n",
-					__func__, irq, vector);
+		printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n",
+					__func__, irq, vector, smp_processor_id());
 		BUG();
 	}
 
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/7] x86: remove union about dest for log/phy
  2008-08-15  2:20   ` [PATCH 1/7] x86: some debug info for 32bit sparse_irq Yinghai Lu
@ 2008-08-15  2:20     ` Yinghai Lu
  2008-08-15  2:20       ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

let user decide the bits.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_32.c |   18 +++++++-----------
 include/asm-x86/io_apic.h    |   16 ----------------
 2 files changed, 7 insertions(+), 27 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 429889d..2d504fa 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -1230,7 +1230,7 @@ static int setup_ioapic_entry(int apic, int irq,
 
 	entry->delivery_mode = INT_DELIVERY_MODE;
 	entry->dest_mode = INT_DEST_MODE;
-	entry->dest.logical.logical_dest = destination;
+	entry->dest = destination;
 
 	entry->mask = 0;                                /* enable IRQ */
 	entry->trigger = trigger;
@@ -1342,7 +1342,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
 	 */
 	entry.dest_mode = INT_DEST_MODE;
 	entry.mask = 1;					/* mask IRQ now */
-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.delivery_mode = INT_DELIVERY_MODE;
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -1431,19 +1431,15 @@ __apicdebuginit(void) print_IO_APIC(void)
 
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
-	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
-			  " Stat Dest Deli Vect:   \n");
+	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+			  " Stat Dmod Deli Vect:   \n");
 
 	for (i = 0; i <= reg_01.bits.entries; i++) {
 		struct IO_APIC_route_entry entry;
 
 		entry = ioapic_read_entry(apic, i);
 
-		printk(KERN_DEBUG " %02x %03X %02X  ",
-			i,
-			entry.dest.logical.logical_dest,
-			entry.dest.physical.physical_dest
-		);
+		printk(KERN_DEBUG " %02x %02X  ", i, entry.dest);
 
 		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
 			entry.mask,
@@ -1723,7 +1719,7 @@ void disable_IO_APIC(void)
 		entry.dest_mode       = 0; /* Physical */
 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
 		entry.vector          = 0;
-		entry.dest.physical.physical_dest = read_apic_id();
+		entry.dest	      = read_apic_id();
 
 		/*
 		 * Add it to the IO-APIC irq-routing table:
@@ -2188,7 +2184,7 @@ static inline void __init unlock_ExtINT_logic(void)
 
 	entry1.dest_mode = 0;			/* physical delivery */
 	entry1.mask = 0;			/* unmask IRQ now */
-	entry1.dest.physical.physical_dest = hard_smp_processor_id();
+	entry1.dest = hard_smp_processor_id();
 	entry1.delivery_mode = dest_ExtINT;
 	entry1.polarity = entry0.polarity;
 	entry1.trigger = 0;
diff --git a/include/asm-x86/io_apic.h b/include/asm-x86/io_apic.h
index 3b297e4..bdb64c3 100644
--- a/include/asm-x86/io_apic.h
+++ b/include/asm-x86/io_apic.h
@@ -87,24 +87,8 @@ struct IO_APIC_route_entry {
 		mask		:  1,	/* 0: enabled, 1: disabled */
 		__reserved_2	: 15;
 
-#ifdef CONFIG_X86_32
-	union {
-		struct {
-			__u32	__reserved_1	: 24,
-				physical_dest	:  4,
-				__reserved_2	:  4;
-		} physical;
-
-		struct {
-			__u32	__reserved_1	: 24,
-				logical_dest	:  8;
-		} logical;
-	} dest;
-#else
 	__u32	__reserved_3	: 24,
 		dest		:  8;
-#endif
-
 } __attribute__ ((packed));
 
 struct IR_IO_APIC_route_entry {
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1
  2008-08-15  2:20     ` [PATCH 2/7] x86: remove union about dest for log/phy Yinghai Lu
@ 2008-08-15  2:20       ` Yinghai Lu
  2008-08-15  2:20         ` [PATCH 4/7] x86_64: rename irq_desc/irq_desc_with_new - fix Yinghai Lu
  2008-08-15  8:21         ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Ingo Molnar
  0 siblings, 2 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

use cpu_online_map as target cpus for bigsmp. just like 64 bit doing

also remove some unused TARGET_CPUS macro.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 include/asm-x86/bigsmp/apic.h |   15 +++++----------
 include/asm-x86/es7000/apic.h |    3 +--
 include/asm-x86/numaq/apic.h  |    2 --
 include/asm-x86/summit/apic.h |    1 -
 4 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/include/asm-x86/bigsmp/apic.h b/include/asm-x86/bigsmp/apic.h
index 0a9cd7c..1d9543b 100644
--- a/include/asm-x86/bigsmp/apic.h
+++ b/include/asm-x86/bigsmp/apic.h
@@ -9,22 +9,17 @@ static inline int apic_id_registered(void)
 	return (1);
 }
 
-/* Round robin the irqs amoung the online cpus */
 static inline cpumask_t target_cpus(void)
 {
-	static unsigned long cpu = NR_CPUS;
-	do {
-		if (cpu >= NR_CPUS)
-			cpu = first_cpu(cpu_online_map);
-		else
-			cpu = next_cpu(cpu, cpu_online_map);
-	} while (cpu >= NR_CPUS);
-	return cpumask_of_cpu(cpu);
+#ifdef CONFIG_SMP
+        return cpu_online_map;
+#else
+        return cpumask_of_cpu(0);
+#endif
 }
 
 #undef APIC_DEST_LOGICAL
 #define APIC_DEST_LOGICAL	0
-#define TARGET_CPUS		(target_cpus())
 #define APIC_DFR_VALUE		(APIC_DFR_FLAT)
 #define INT_DELIVERY_MODE	(dest_Fixed)
 #define INT_DEST_MODE		(0)    /* phys delivery to target proc */
diff --git a/include/asm-x86/es7000/apic.h b/include/asm-x86/es7000/apic.h
index bd2c44d..750afad 100644
--- a/include/asm-x86/es7000/apic.h
+++ b/include/asm-x86/es7000/apic.h
@@ -17,7 +17,6 @@ static inline cpumask_t target_cpus(void)
 	return cpumask_of_cpu(smp_processor_id());
 #endif
 }
-#define TARGET_CPUS	(target_cpus())
 
 #if defined CONFIG_ES7000_CLUSTERED_APIC
 #define APIC_DFR_VALUE		(APIC_DFR_CLUSTER)
@@ -81,7 +80,7 @@ static inline void setup_apic_routing(void)
 	int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
 	printk("Enabling APIC mode:  %s.  Using %d I/O APICs, target cpus %lx\n",
 		(apic_version[apic] == 0x14) ?
-		"Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]);
+		"Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(target_cpus())[0]);
 }
 
 static inline int multi_timer_check(int apic, int irq)
diff --git a/include/asm-x86/numaq/apic.h b/include/asm-x86/numaq/apic.h
index a8344ba..0bf2a06 100644
--- a/include/asm-x86/numaq/apic.h
+++ b/include/asm-x86/numaq/apic.h
@@ -12,8 +12,6 @@ static inline cpumask_t target_cpus(void)
 	return CPU_MASK_ALL;
 }
 
-#define TARGET_CPUS (target_cpus())
-
 #define NO_BALANCE_IRQ (1)
 #define esr_disable (1)
 
diff --git a/include/asm-x86/summit/apic.h b/include/asm-x86/summit/apic.h
index c5b2e4b..0f68037 100644
--- a/include/asm-x86/summit/apic.h
+++ b/include/asm-x86/summit/apic.h
@@ -22,7 +22,6 @@ static inline cpumask_t target_cpus(void)
 	 */
 	return cpumask_of_cpu(0);
 }
-#define TARGET_CPUS	(target_cpus())
 
 #define INT_DELIVERY_MODE (dest_LowestPrio)
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 4/7] x86_64: rename irq_desc/irq_desc_with_new - fix
  2008-08-15  2:20       ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Yinghai Lu
@ 2008-08-15  2:20         ` Yinghai Lu
  2008-08-15  2:20           ` [PATCH 5/7] x86: make 32bit support per_cpu vector fix #2 Yinghai Lu
  2008-08-15  8:21         ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Ingo Molnar
  1 sibling, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

need to check if desc is null in smp_irq_move_cleanup

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_64.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 4d1b02d..e4f03cc 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -1950,6 +1950,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
 		irq = __get_cpu_var(vector_irq)[vector];
 
 		desc = irq_desc(irq);
+		if (!desc)
+			continue;
+
 		cfg = irq_cfg(irq);
 		spin_lock(&desc->lock);
 		if (!cfg->move_cleanup_count)
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 5/7] x86: make 32bit support per_cpu vector fix #2
  2008-08-15  2:20         ` [PATCH 4/7] x86_64: rename irq_desc/irq_desc_with_new - fix Yinghai Lu
@ 2008-08-15  2:20           ` Yinghai Lu
  2008-08-15  2:20             ` [PATCH 6/7] x86: ordering functions in io_apic_32.c Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

need to check if desc is null in smp_irq_move_cleanup

also migration need to reset vector too, so copy __target_IO_APIC_irq from 64bit

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_32.c |  188 +++++++++++++++++++++++++----------------
 1 files changed, 115 insertions(+), 73 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 2d504fa..e0f85b5 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -268,6 +268,7 @@ static struct irq_cfg *irq_cfg_with_new(unsigned int irq)
 	return cfg;
 }
 
+static int assign_irq_vector(int irq, cpumask_t mask);
 /*
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
@@ -437,6 +438,65 @@ static void ioapic_mask_entry(int apic, int pin)
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
+#ifdef CONFIG_SMP
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
+{
+	int apic, pin;
+	struct irq_cfg *cfg;
+	struct irq_pin_list *entry;
+
+	cfg = irq_cfg(irq);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		unsigned int reg;
+
+		if (!entry)
+			break;
+
+		apic = entry->apic;
+		pin = entry->pin;
+		io_apic_write(apic, 0x11 + pin*2, dest);
+		reg = io_apic_read(apic, 0x10 + pin*2);
+		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+		reg |= vector;
+		io_apic_modify(apic, 0x10 + pin *2, reg);
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+}
+static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int dest;
+	cpumask_t tmp;
+
+	cfg = irq_cfg(irq);
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(tmp, cfg->domain, mask);
+
+	dest = cpu_mask_to_apicid(tmp);
+	/*
+	 * Only the high 8 bits are valid.
+	 */
+	dest = SET_APIC_LOGICAL_ID(dest);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__target_IO_APIC_irq(irq, dest, cfg->vector);
+	desc->affinity = mask;
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+#endif /* CONFIG_SMP */
+
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
@@ -591,44 +651,6 @@ static void clear_IO_APIC(void)
 			clear_IO_APIC_pin(apic, pin);
 }
 
-#ifdef CONFIG_SMP
-static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t cpumask)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	int pin;
-	struct irq_pin_list *entry;
-	unsigned int apicid_value;
-	cpumask_t tmp;
-
-	cfg = irq_cfg(irq);
-	entry = cfg->irq_2_pin;
-
-	cpus_and(tmp, cpumask, cpu_online_map);
-	if (cpus_empty(tmp))
-		tmp = TARGET_CPUS;
-
-	cpus_and(cpumask, tmp, CPU_MASK_ALL);
-
-	apicid_value = cpu_mask_to_apicid(cpumask);
-	/* Prepare to do the io_apic_write */
-	apicid_value = apicid_value << 24;
-	spin_lock_irqsave(&ioapic_lock, flags);
-	for (;;) {
-		if (!entry)
-			break;
-		pin = entry->pin;
-		io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-	desc->affinity = cpumask;
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#endif /* CONFIG_SMP */
-
 #ifndef CONFIG_SMP
 void send_IPI_self(int vector)
 {
@@ -793,34 +815,6 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 }
 EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 
-/*
- * This function currently is only a helper for the i386 smp boot process where
- * we need to reprogram the ioredtbls to cater for the cpus which have come online
- * so mask in all cases should simply be TARGET_CPUS
- */
-#ifdef CONFIG_SMP
-void __init setup_ioapic_dest(void)
-{
-	int pin, ioapic, irq, irq_entry;
-	struct irq_desc *desc;
-
-	if (skip_ioapic_setup == 1)
-		return;
-
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
-			if (irq_entry == -1)
-				continue;
-			irq = pin_2_irq(irq_entry, ioapic, pin);
-			desc = irq_desc(irq);
-			set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-		}
-
-	}
-}
-#endif
-
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 /*
  * EISA Edge/Level control register, ELCR
@@ -2003,6 +1997,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
 		irq = __get_cpu_var(vector_irq)[vector];
 
 		desc = irq_desc(irq);
+		if (!desc)
+			continue;
+
 		cfg = irq_cfg(irq);
 		spin_lock(&desc->lock);
 		if (!cfg->move_cleanup_count)
@@ -2695,15 +2692,15 @@ void arch_teardown_msi_irq(unsigned int irq)
 
 #ifdef CONFIG_SMP
 
-static void target_ht_irq(unsigned int irq, unsigned int dest)
+static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 {
 	struct ht_irq_msg msg;
 	fetch_ht_irq_msg(irq, &msg);
 
-	msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
+	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
 	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
 
-	msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
+	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
 	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
 
 	write_ht_irq_msg(irq, &msg);
@@ -2711,18 +2708,22 @@ static void target_ht_irq(unsigned int irq, unsigned int dest)
 
 static void set_ht_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
 {
+	struct irq_cfg *cfg;
 	unsigned int dest;
 	cpumask_t tmp;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
-		tmp = TARGET_CPUS;
+		return;
 
-	cpus_and(mask, tmp, CPU_MASK_ALL);
+	if (assign_irq_vector(irq, mask))
+		return;
 
-	dest = cpu_mask_to_apicid(mask);
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
 
-	target_ht_irq(irq, dest);
+	target_ht_irq(irq, dest, cfg->vector);
 	desc->affinity = mask;
 }
 #endif
@@ -2925,6 +2926,47 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
 
 #endif /* CONFIG_ACPI */
 
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+#ifdef CONFIG_SMP
+void __init setup_ioapic_dest(void)
+{
+	int pin, ioapic, irq, irq_entry;
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+
+	if (skip_ioapic_setup == 1)
+		return;
+
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+			if (irq_entry == -1)
+				continue;
+			irq = pin_2_irq(irq_entry, ioapic, pin);
+
+			/* setup_IO_APIC_irqs could fail to get vector for some device
+			 * when you have too many devices, because at that time only boot
+			 * cpu is online.
+			 */
+			cfg = irq_cfg(irq);
+			if (!cfg->vector)
+				setup_IO_APIC_irq(ioapic, pin, irq,
+						  irq_trigger(irq_entry),
+						  irq_polarity(irq_entry));
+			else {
+				desc = irq_desc(irq);
+				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
+			}
+		}
+
+	}
+}
+#endif
+
 static int __init parse_disable_timer_pin_1(char *arg)
 {
 	disable_timer_pin_1 = 1;
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 6/7] x86: ordering functions in io_apic_32.c
  2008-08-15  2:20           ` [PATCH 5/7] x86: make 32bit support per_cpu vector fix #2 Yinghai Lu
@ 2008-08-15  2:20             ` Yinghai Lu
  2008-08-15  2:20               ` [PATCH 7/7] x86: ordering functions in io_apic_64.c Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

try to make functions in the same order to io_apic_64.c

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_32.c |  176 ++++++++++++++++++++++--------------------
 1 files changed, 93 insertions(+), 83 deletions(-)

diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index e0f85b5..5639404 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -1029,23 +1029,6 @@ static int pin_2_irq(int idx, int apic, int pin)
 	return irq;
 }
 
-static inline int IO_APIC_irq_trigger(int irq)
-{
-	int apic, idx, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			idx = find_irq_entry(apic, pin, mp_INT);
-			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-				return irq_trigger(idx);
-		}
-	}
-	/*
-	 * nonexistent IRQs are edge default
-	 */
-	return 0;
-}
-
 void lock_vector_lock(void)
 {
 	/* Used to the online set of cpus does not change
@@ -1190,6 +1173,23 @@ static struct irq_chip ioapic_chip;
 #define IOAPIC_EDGE	0
 #define IOAPIC_LEVEL	1
 
+static inline int IO_APIC_irq_trigger(int irq)
+{
+	int apic, idx, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			idx = find_irq_entry(apic, pin, mp_INT);
+			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+				return irq_trigger(idx);
+		}
+	}
+	/*
+	 * nonexistent IRQs are edge default
+	 */
+	return 0;
+}
+
 static void ioapic_register_intr(int irq, unsigned long trigger)
 {
 	struct irq_desc *desc;
@@ -1926,55 +1926,6 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
 	return was_pending;
 }
 
-static void irq_complete_move(unsigned int irq);
-static void ack_ioapic_irq(unsigned int irq, struct irq_desc *desc)
-{
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-	ack_APIC_irq();
-}
-
-static void ack_ioapic_quirk_irq(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned long v;
-	int i;
-
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-/*
- * It appears there is an erratum which affects at least version 0x11
- * of I/O APIC (that's the 82093AA and cores integrated into various
- * chipsets).  Under certain conditions a level-triggered interrupt is
- * erroneously delivered as edge-triggered one but the respective IRR
- * bit gets set nevertheless.  As a result the I/O unit expects an EOI
- * message but it will never arrive and further interrupts are blocked
- * from the source.  The exact reason is so far unknown, but the
- * phenomenon was observed when two consecutive interrupt requests
- * from a given source get delivered to the same CPU and the source is
- * temporarily disabled in between.
- *
- * A workaround is to simulate an EOI message manually.  We achieve it
- * by setting the trigger mode to edge and then to level when the edge
- * trigger mode gets detected in the TMR of a local APIC for a
- * level-triggered interrupt.  We mask the source for the time of the
- * operation to prevent an edge-triggered interrupt escaping meanwhile.
- * The idea is from Manfred Spraul.  --macro
- */
-	i = irq_cfg(irq)->vector;
-
-	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
-
-	ack_APIC_irq();
-
-	if (!(v & (1 << (i & 0x1f)))) {
-		atomic_inc(&irq_mis_count);
-		spin_lock(&ioapic_lock);
-		__mask_and_edge_IO_APIC_irq(irq);
-		__unmask_and_level_IO_APIC_irq(irq);
-		spin_unlock(&ioapic_lock);
-	}
-}
-
 static int ioapic_retrigger_irq(unsigned int irq)
 {
 	send_IPI_self(irq_cfg(irq)->vector);
@@ -2040,13 +1991,61 @@ static void irq_complete_move(unsigned int irq)
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
 
+static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
+{
+	irq_complete_move(irq);
+	move_native_irq(irq, desc);
+	ack_APIC_irq();
+}
+
+static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long v;
+	int i;
+
+	irq_complete_move(irq);
+	move_native_irq(irq, desc);
+/*
+ * It appears there is an erratum which affects at least version 0x11
+ * of I/O APIC (that's the 82093AA and cores integrated into various
+ * chipsets).  Under certain conditions a level-triggered interrupt is
+ * erroneously delivered as edge-triggered one but the respective IRR
+ * bit gets set nevertheless.  As a result the I/O unit expects an EOI
+ * message but it will never arrive and further interrupts are blocked
+ * from the source.  The exact reason is so far unknown, but the
+ * phenomenon was observed when two consecutive interrupt requests
+ * from a given source get delivered to the same CPU and the source is
+ * temporarily disabled in between.
+ *
+ * A workaround is to simulate an EOI message manually.  We achieve it
+ * by setting the trigger mode to edge and then to level when the edge
+ * trigger mode gets detected in the TMR of a local APIC for a
+ * level-triggered interrupt.  We mask the source for the time of the
+ * operation to prevent an edge-triggered interrupt escaping meanwhile.
+ * The idea is from Manfred Spraul.  --macro
+ */
+	i = irq_cfg(irq)->vector;
+
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+	ack_APIC_irq();
+
+	if (!(v & (1 << (i & 0x1f)))) {
+		atomic_inc(&irq_mis_count);
+		spin_lock(&ioapic_lock);
+		__mask_and_edge_IO_APIC_irq(irq);
+		__unmask_and_level_IO_APIC_irq(irq);
+		spin_unlock(&ioapic_lock);
+	}
+}
+
 static struct irq_chip ioapic_chip __read_mostly = {
 	.name 		= "IO-APIC",
 	.startup 	= startup_ioapic_irq,
 	.mask	 	= mask_IO_APIC_irq,
 	.unmask	 	= unmask_IO_APIC_irq,
-	.ack 		= ack_ioapic_irq,
-	.eoi 		= ack_ioapic_quirk_irq,
+	.ack 		= ack_apic_edge,
+	.eoi 		= ack_apic_level,
 #ifdef CONFIG_SMP
 	.set_affinity 	= set_ioapic_affinity_irq,
 #endif
@@ -2094,11 +2093,6 @@ static inline void init_IO_APIC_traps(void)
  * The local APIC irq-chip implementation:
  */
 
-static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
-{
-	ack_APIC_irq();
-}
-
 static void mask_lapic_irq(unsigned int irq)
 {
 	unsigned long v;
@@ -2115,6 +2109,11 @@ static void unmask_lapic_irq(unsigned int irq)
 	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
+static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
+{
+	ack_APIC_irq();
+}
+
 static struct irq_chip lapic_chip __read_mostly = {
 	.name		= "local-APIC",
 	.mask		= mask_lapic_irq,
@@ -2631,13 +2630,31 @@ static struct irq_chip msi_chip = {
 	.name		= "PCI-MSI",
 	.unmask		= unmask_msi_irq,
 	.mask		= mask_msi_irq,
-	.ack		= ack_ioapic_irq,
+	.ack		= ack_apic_edge,
 #ifdef CONFIG_SMP
 	.set_affinity	= set_msi_irq_affinity,
 #endif
 	.retrigger	= ioapic_retrigger_irq,
 };
 
+
+static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(dev, irq, &msg);
+	if (ret < 0)
+		return ret;
+
+	set_irq_msi(irq, desc);
+	write_msi_msg(irq, &msg);
+
+	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+
+	return 0;
+}
+
 static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
 {
 	unsigned int irq;
@@ -2663,17 +2680,10 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 	if (irq == 0)
 		return -1;
 
-	ret = msi_compose_msg(dev, irq, &msg);
 	if (ret < 0) {
 		destroy_irq(irq);
 		return ret;
-	}
-
-	set_irq_msi(irq, desc);
-	write_msi_msg(irq, &msg);
-
-	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
-				      "edge");
+        }
 
 	return 0;
 }
@@ -2732,7 +2742,7 @@ static struct irq_chip ht_irq_chip = {
 	.name		= "PCI-HT",
 	.mask		= mask_ht_irq,
 	.unmask		= unmask_ht_irq,
-	.ack		= ack_ioapic_irq,
+	.ack		= ack_apic_edge,
 #ifdef CONFIG_SMP
 	.set_affinity	= set_ht_irq_affinity,
 #endif
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 7/7] x86: ordering functions in io_apic_64.c
  2008-08-15  2:20             ` [PATCH 6/7] x86: ordering functions in io_apic_32.c Yinghai Lu
@ 2008-08-15  2:20               ` Yinghai Lu
  0 siblings, 0 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  2:20 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

try to make functions in the same order

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/x86/kernel/io_apic_64.c |   67 ++++++++++++++++++++---------------------
 1 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index e4f03cc..a14c29e 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -409,40 +409,6 @@ static bool io_apic_level_ack_pending(unsigned int irq)
 	return false;
 }
 
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	readl(&io_apic->data);
-}
-
-#define __DO_ACTION(R, ACTION, FINAL)					\
-									\
-{									\
-	int pin;							\
-	struct irq_cfg *cfg;						\
-	struct irq_pin_list *entry;					\
-									\
-	cfg = irq_cfg(irq);						\
-	entry = cfg->irq_2_pin;						\
-	for (;;) {							\
-		unsigned int reg;					\
-		if (!entry)						\
-			break;						\
-		pin = entry->pin;					\
-		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
-		reg ACTION;						\
-		io_apic_modify(entry->apic, reg);			\
-		FINAL;							\
-		if (!entry->next)					\
-			break;						\
-		entry = entry->next;					\
-	}								\
-}
-
 union entry_union {
 	struct { u32 w1, w2; };
 	struct IO_APIC_route_entry entry;
@@ -625,6 +591,39 @@ static void __init replace_pin_at_irq(unsigned int irq,
 		add_pin_to_irq(irq, newapic, newpin);
 }
 
+/*
+ * Synchronize the IO-APIC and the CPU by doing
+ * a dummy read from the IO-APIC
+ */
+static inline void io_apic_sync(unsigned int apic)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	readl(&io_apic->data);
+}
+
+#define __DO_ACTION(R, ACTION, FINAL)					\
+									\
+{									\
+	int pin;							\
+	struct irq_cfg *cfg;						\
+	struct irq_pin_list *entry;					\
+									\
+	cfg = irq_cfg(irq);						\
+	entry = cfg->irq_2_pin;						\
+	for (;;) {							\
+		unsigned int reg;					\
+		if (!entry)						\
+			break;						\
+		pin = entry->pin;					\
+		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
+		reg ACTION;						\
+		io_apic_modify(entry->apic, reg);			\
+		FINAL;							\
+		if (!entry->next)					\
+			break;						\
+		entry = entry->next;					\
+	}								\
+}
 
 #define DO_ACTION(name,R,ACTION, FINAL)					\
 									\
-- 
1.5.4.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1
  2008-08-15  2:20       ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Yinghai Lu
  2008-08-15  2:20         ` [PATCH 4/7] x86_64: rename irq_desc/irq_desc_with_new - fix Yinghai Lu
@ 2008-08-15  8:21         ` Ingo Molnar
  2008-08-15  8:29           ` Yinghai Lu
  1 sibling, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15  8:21 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> +#ifdef CONFIG_SMP
> +        return cpu_online_map;
> +#else
> +        return cpumask_of_cpu(0);
> +#endif

unrelated sidenote - shouldnt the scheduler define cpu_online_map to 
cpumask_of_cpu(0) on UP, to avoid such ugly #ifdefs?

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15  2:20 ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Yinghai Lu
  2008-08-15  2:20   ` [PATCH 1/7] x86: some debug info for 32bit sparse_irq Yinghai Lu
@ 2008-08-15  8:27   ` Ingo Molnar
  2008-08-15  8:34     ` Yinghai Lu
  1 sibling, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15  8:27 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> 	fix the 32bit with bigsmp
> 	fix 64 bit with irq migration
> 	ordering functions in io_apic_xx.c
> 
> 
> to do:
>     merge io_apic_xx.c

applied to tip/irq/sparseirq - thanks Yinghai, great work!

What do you think about Eric's abstraction suggestion, that irq_desc's 
structure should be hidden from all but kernel/irq/* code. I think 
that's a sane suggestion. We do it in mm/slab.c too: no external code 
knows the structure of 'struct kmem_cache'.

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1
  2008-08-15  8:21         ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Ingo Molnar
@ 2008-08-15  8:29           ` Yinghai Lu
  2008-08-15  8:51             ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  8:29 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Fri, Aug 15, 2008 at 1:21 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>> +#ifdef CONFIG_SMP
>> +        return cpu_online_map;
>> +#else
>> +        return cpumask_of_cpu(0);
>> +#endif
>
> unrelated sidenote - shouldnt the scheduler define cpu_online_map to
> cpumask_of_cpu(0) on UP, to avoid such ugly #ifdefs?

copy that from mach_default...

should double check if cpu_online_map is cpu_mask_of_cpu(0) if !CONFIG_SMP

YH

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15  8:27   ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Ingo Molnar
@ 2008-08-15  8:34     ` Yinghai Lu
  2008-08-15  8:51       ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15  8:34 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Fri, Aug 15, 2008 at 1:27 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>>       fix the 32bit with bigsmp
>>       fix 64 bit with irq migration
>>       ordering functions in io_apic_xx.c
>>
>>
>> to do:
>>     merge io_apic_xx.c
>
> applied to tip/irq/sparseirq - thanks Yinghai, great work!
>
> What do you think about Eric's abstraction suggestion, that irq_desc's
> structure should be hidden from all but kernel/irq/* code. I think
> that's a sane suggestion. We do it in mm/slab.c too: no external code
> knows the structure of 'struct kmem_cache'.

current arch code use irq_desc directly..., if need to irq_desc to
them, need to provide set_irq(..., ...)

YH

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15  8:34     ` Yinghai Lu
@ 2008-08-15  8:51       ` Ingo Molnar
  2008-08-15  9:35         ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15  8:51 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> On Fri, Aug 15, 2008 at 1:27 AM, Ingo Molnar <mingo@elte.hu> wrote:
> >
> > * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> >
> >>       fix the 32bit with bigsmp
> >>       fix 64 bit with irq migration
> >>       ordering functions in io_apic_xx.c
> >>
> >>
> >> to do:
> >>     merge io_apic_xx.c
> >
> > applied to tip/irq/sparseirq - thanks Yinghai, great work!
> >
> > What do you think about Eric's abstraction suggestion, that irq_desc's
> > structure should be hidden from all but kernel/irq/* code. I think
> > that's a sane suggestion. We do it in mm/slab.c too: no external code
> > knows the structure of 'struct kmem_cache'.
> 
> current arch code use irq_desc directly..., if need to irq_desc to 
> them, need to provide set_irq(..., ...)

that's ok - we can do include/linux/irq_desc.h that isnt generally 
included by drivers via interrupt.h. Then later on we can eliminate that 
include file altogether.

here's the current field usage histogram:

      3 desc->action
      3 desc->depth
      9 desc->affinity
     15 desc->chip
     22 desc->status

desc->status: mostly IRQ_MOVE_PENDING related. irq-balancing code should 
be abstracted into kernel/irq/* perhaps?

desc->action / desc->depth / desc->action: i dont think those should be 
accessed by genirq arch irq code.

desc->chip: there's a get_irq_chip() method already. irq_chip is 
something that obviously is known to architecture code - it's the irq 
controller 'driver' that the architecture code provides.

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1
  2008-08-15  8:29           ` Yinghai Lu
@ 2008-08-15  8:51             ` Ingo Molnar
  0 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15  8:51 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> On Fri, Aug 15, 2008 at 1:21 AM, Ingo Molnar <mingo@elte.hu> wrote:
> >
> > * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> >
> >> +#ifdef CONFIG_SMP
> >> +        return cpu_online_map;
> >> +#else
> >> +        return cpumask_of_cpu(0);
> >> +#endif
> >
> > unrelated sidenote - shouldnt the scheduler define cpu_online_map to
> > cpumask_of_cpu(0) on UP, to avoid such ugly #ifdefs?
> 
> copy that from mach_default...

sure, that's the right approach - preserve existing code to reduce risk.

> should double check if cpu_online_map is cpu_mask_of_cpu(0) if !CONFIG_SMP

yeah. Separate clean-up patch i think.

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15  8:51       ` Ingo Molnar
@ 2008-08-15  9:35         ` Ingo Molnar
  2008-08-15 10:00           ` Peter Zijlstra
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15  9:35 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel, Peter Zijlstra


btw., one new thing i got in testing due to irq/sparseirq is this new 
lockdep splat:

[    0.000000] Initializing CPU#0
[    0.000000] found new irq_desc for irq 0
[    0.000000] INFO: trying to register non-static key.
[    0.000000] the code is fine but needs lockdep annotation.
[    0.000000] turning off the locking correctness validator.
[    0.000000] Pid: 0, comm: swapper Not tainted 2.6.27-rc3-tip-00191-g98ccb89-dirty #1
[    0.000000]  [<c0153c22>] register_lock_class+0x3d2/0x400
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c0154f3a>] __lock_acquire+0x22a/0x5d0
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c0155351>] lock_acquire+0x71/0xa0
[    0.000000]  [<c016d61f>] ? set_irq_chip+0x3f/0x90
[    0.000000]  [<c070f148>] _spin_lock_irqsave+0x58/0x90
[    0.000000]  [<c016d61f>] ? set_irq_chip+0x3f/0x90
[    0.000000]  [<c016d61f>] set_irq_chip+0x3f/0x90
[    0.000000]  [<c016d7e0>] ? handle_level_irq+0x0/0xe0
[    0.000000]  [<c016da1a>] set_irq_chip_and_handler_name+0x1a/0x40
[    0.000000]  [<c0a396c1>] init_ISA_irqs+0x51/0xa0
[    0.000000]  [<c0a4a365>] pre_intr_init_hook+0x25/0x30
[    0.000000]  [<c0a39723>] native_init_IRQ+0x13/0x370
[    0.000000]  [<c015569c>] ? lock_release+0xcc/0x1d0
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c070dc22>] ? __mutex_unlock_slowpath+0x92/0x110
[    0.000000]  [<c070dcad>] ? mutex_unlock+0xd/0x10
[    0.000000]  [<c0135f62>] ? cpu_maps_update_done+0x12/0x20
[    0.000000]  [<c06c6743>] ? register_cpu_notifier+0x23/0x30
[    0.000000]  [<c011e8ae>] init_IRQ+0xe/0x10
[    0.000000]  [<c0a357a5>] start_kernel+0x1c5/0x340
[    0.000000]  [<c0a35280>] ? unknown_bootoption+0x0/0x210
[    0.000000]  [<c0a3506b>] i386_start_kernel+0x6b/0x80
[    0.000000]  =======================
[    0.000000] found new irq_desc for irq 1
[    0.000000] found new irq_desc for irq 2
[    0.000000] found new irq_desc for irq 3

this:

 static void init_one_irq_desc(struct irq_desc *desc)
 {
         memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
 #ifdef CONFIG_TRACE_IRQFLAGS
         lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 #endif
 }

looks wrong - it should be unconditional (i've done that via the patch 
below). I dont remember why we made early_init_irq_lock_class() 
dependent on CONFIG_TRACE_IRQFLAGS before. Peter, do you have any 
memories?

	Ingo

--------------------------->
>From bba3b43f2383c2fd06c4befee45ef30d5cf59d32 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 15 Aug 2008 11:34:35 +0200
Subject: [PATCH] sparseirq: fix lockdep

-tip testing found this lockdep splat:

[    0.000000] Initializing CPU#0
[    0.000000] found new irq_desc for irq 0
[    0.000000] INFO: trying to register non-static key.
[    0.000000] the code is fine but needs lockdep annotation.
[    0.000000] turning off the locking correctness validator.
[    0.000000] Pid: 0, comm: swapper Not tainted 2.6.27-rc3-tip-00191-g98ccb89-dirty #1
[    0.000000]  [<c0153c22>] register_lock_class+0x3d2/0x400
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c0154f3a>] __lock_acquire+0x22a/0x5d0
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c0155351>] lock_acquire+0x71/0xa0
[    0.000000]  [<c016d61f>] ? set_irq_chip+0x3f/0x90
[    0.000000]  [<c070f148>] _spin_lock_irqsave+0x58/0x90
[    0.000000]  [<c016d61f>] ? set_irq_chip+0x3f/0x90
[    0.000000]  [<c016d61f>] set_irq_chip+0x3f/0x90
[    0.000000]  [<c016d7e0>] ? handle_level_irq+0x0/0xe0
[    0.000000]  [<c016da1a>] set_irq_chip_and_handler_name+0x1a/0x40
[    0.000000]  [<c0a396c1>] init_ISA_irqs+0x51/0xa0
[    0.000000]  [<c0a4a365>] pre_intr_init_hook+0x25/0x30
[    0.000000]  [<c0a39723>] native_init_IRQ+0x13/0x370
[    0.000000]  [<c015569c>] ? lock_release+0xcc/0x1d0
[    0.000000]  [<c0104d87>] ? mcount_call+0x5/0xa
[    0.000000]  [<c070dc22>] ? __mutex_unlock_slowpath+0x92/0x110
[    0.000000]  [<c070dcad>] ? mutex_unlock+0xd/0x10
[    0.000000]  [<c0135f62>] ? cpu_maps_update_done+0x12/0x20
[    0.000000]  [<c06c6743>] ? register_cpu_notifier+0x23/0x30
[    0.000000]  [<c011e8ae>] init_IRQ+0xe/0x10
[    0.000000]  [<c0a357a5>] start_kernel+0x1c5/0x340
[    0.000000]  [<c0a35280>] ? unknown_bootoption+0x0/0x210
[    0.000000]  [<c0a3506b>] i386_start_kernel+0x6b/0x80
[    0.000000]  =======================
[    0.000000] found new irq_desc for irq 1
[    0.000000] found new irq_desc for irq 2
[    0.000000] found new irq_desc for irq 3

this:

 static void init_one_irq_desc(struct irq_desc *desc)
 {
         memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
 #ifdef CONFIG_TRACE_IRQFLAGS
         lockdep_set_class(&desc->lock, &irq_desc_lock_class);
 #endif
 }

should be unconditional.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 kernel/irq/handle.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index ce8774b..8cd0c68 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -75,9 +75,7 @@ static struct irq_desc irq_desc_init = {
 static void init_one_irq_desc(struct irq_desc *desc)
 {
 	memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
-#ifdef CONFIG_TRACE_IRQFLAGS
 	lockdep_set_class(&desc->lock, &irq_desc_lock_class);
-#endif
 }
 
 extern int after_bootmem;

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15  9:35         ` Ingo Molnar
@ 2008-08-15 10:00           ` Peter Zijlstra
  2008-08-15 10:19             ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Peter Zijlstra @ 2008-08-15 10:00 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Yinghai Lu, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Fri, 2008-08-15 at 11:35 +0200, Ingo Molnar wrote:

> looks wrong - it should be unconditional (i've done that via the patch 
> below). I dont remember why we made early_init_irq_lock_class() 
> dependent on CONFIG_TRACE_IRQFLAGS before. Peter, do you have any 
> memories?

Nope, git suggests I poke you about it.. :-)

commit 243c7621aac4ed1aa79524c9a1cecf7c05a28124
Author: Ingo Molnar <mingo@elte.hu>
Date:   Mon Jul 3 00:25:06 2006 -0700

    [PATCH] lockdep: annotate genirq
    
    Teach special (recursive) locking code to the lock validator.  Has no effect
    on non-lockdep kernels.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
    Signed-off-by: Andrew Morton <akpm@osdl.org>
    Signed-off-by: Linus Torvalds <torvalds@osdl.org>

diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 80ec7a4..316e0fb 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -270,6 +270,12 @@ static inline int lockdep_internal(void)
 struct lock_class_key { };
 #endif /* !LOCKDEP */
 
+#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
+extern void early_init_irq_lock_class(void);
+#else
+# define early_init_irq_lock_class()		do { } while (0)
+#endif
+
 #ifdef CONFIG_TRACE_IRQFLAGS
 extern void early_boot_irqs_off(void);
 extern void early_boot_irqs_on(void);
diff --git a/init/main.c b/init/main.c
index fc473d4..628b8e9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -466,6 +466,7 @@ asmlinkage void __init start_kernel(void)
 
 	local_irq_disable();
 	early_boot_irqs_off();
+	early_init_irq_lock_class();
 
 /*
  * Interrupts are still disabled. Do necessary setups, then
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index aeb6e39..a7b497e 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -249,3 +249,19 @@ out:
 	return 1;
 }
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+/*
+ * lockdep: we want to handle all irq_desc locks as a single lock-class:
+ */
+static struct lock_class_key irq_desc_lock_class;
+
+void early_init_irq_lock_class(void)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++)
+		lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class);
+}
+
+#endif



^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15 10:00           ` Peter Zijlstra
@ 2008-08-15 10:19             ` Ingo Molnar
  2008-08-15 10:28               ` Peter Zijlstra
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-15 10:19 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Yinghai Lu, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:

> On Fri, 2008-08-15 at 11:35 +0200, Ingo Molnar wrote:
> 
> > looks wrong - it should be unconditional (i've done that via the patch 
> > below). I dont remember why we made early_init_irq_lock_class() 
> > dependent on CONFIG_TRACE_IRQFLAGS before. Peter, do you have any 
> > memories?
> 
> Nope, git suggests I poke you about it.. :-)

muhaha - i dont even know that guy who did this sloppy commit 2 years 
ago - "Ingo Molnar", or however he is called.

I believe my (mistaken) thinking would have been that desc->irq lockdep 
class does not matter as long as we dont do irq-tracing. Which might 
have been borderline correct then but is wrong now, for things like 
lockstat?

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15 10:19             ` Ingo Molnar
@ 2008-08-15 10:28               ` Peter Zijlstra
  2008-08-15 17:07                 ` Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Peter Zijlstra @ 2008-08-15 10:28 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Yinghai Lu, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Fri, 2008-08-15 at 12:19 +0200, Ingo Molnar wrote:
> * Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:
> 
> > On Fri, 2008-08-15 at 11:35 +0200, Ingo Molnar wrote:
> > 
> > > looks wrong - it should be unconditional (i've done that via the patch 
> > > below). I dont remember why we made early_init_irq_lock_class() 
> > > dependent on CONFIG_TRACE_IRQFLAGS before. Peter, do you have any 
> > > memories?
> > 
> > Nope, git suggests I poke you about it.. :-)
> 
> muhaha - i dont even know that guy who did this sloppy commit 2 years 
> ago - "Ingo Molnar", or however he is called.
> 
> I believe my (mistaken) thinking would have been that desc->irq lockdep 
> class does not matter as long as we dont do irq-tracing. Which might 
> have been borderline correct then but is wrong now, for things like 
> lockstat?

/me pokes a bit at kconfig dependancies, and yes, it seems you're right
- lockstat doesn't require irq tracing..




^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix
  2008-08-15 10:28               ` Peter Zijlstra
@ 2008-08-15 17:07                 ` Yinghai Lu
  0 siblings, 0 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 17:07 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Fri, Aug 15, 2008 at 3:28 AM, Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:
> On Fri, 2008-08-15 at 12:19 +0200, Ingo Molnar wrote:
>> * Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:
>>
>> > On Fri, 2008-08-15 at 11:35 +0200, Ingo Molnar wrote:
>> >
>> > > looks wrong - it should be unconditional (i've done that via the patch
>> > > below). I dont remember why we made early_init_irq_lock_class()
>> > > dependent on CONFIG_TRACE_IRQFLAGS before. Peter, do you have any
>> > > memories?
>> >
>> > Nope, git suggests I poke you about it.. :-)
>>
>> muhaha - i dont even know that guy who did this sloppy commit 2 years
>> ago - "Ingo Molnar", or however he is called.
>>
>> I believe my (mistaken) thinking would have been that desc->irq lockdep
>> class does not matter as long as we dont do irq-tracing. Which might
>> have been borderline correct then but is wrong now, for things like
>> lockstat?
>
> /me pokes a bit at kconfig dependancies, and yes, it seems you're right
> - lockstat doesn't require irq tracing..

can you check if

#ifdef CONFIG_TRACE_IRQFLAGS
void early_init_irq_lock_class(void)
{
#ifndef CONFIG_HAVE_DYN_ARRAY
        int i;

        for (i = 0; i < nr_irqs; i++)
                lockdep_set_class(&irq_descX[i].lock, &irq_desc_lock_class);
#endif
}
#endif

in kernel/irq/handle.c is right too?

YH

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 0/7] merge io_apic_xx.c
       [not found] <no>
  2008-08-15  2:20 ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Yinghai Lu
@ 2008-08-15 23:42 ` Yinghai Lu
  2008-08-15 23:42   ` [PATCH 1/7] x86: ordering functions in io_apic_32.c - fix Yinghai Lu
  2008-08-18  4:12 ` [PATCH] x86: apic - unify lapic_resume - fix Yinghai Lu
                   ` (36 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

    merge io_apic_xx.c

Thanks

Yinghai Lu


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/7] x86: ordering functions in io_apic_32.c - fix
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
@ 2008-08-15 23:42   ` Yinghai Lu
  2008-08-15 23:42     ` [PATCH 2/7] x86: make headers files the smae in io_apic_xx.c Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

add calling setup_msi_irq back to arch_setup_msi_irq

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_32.c
+++ linux-2.6/arch/x86/kernel/io_apic_32.c
@@ -2686,7 +2695,6 @@ static unsigned int build_irq_for_pci_de
 
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	struct msi_msg msg;
 	int irq, ret;
         unsigned int irq_want;
 
@@ -2697,6 +2705,7 @@ int arch_setup_msi_irq(struct pci_dev *d
 	if (irq == 0)
 		return -1;
 
+	ret = setup_msi_irq(dev, desc, irq);
 	if (ret < 0) {
 		destroy_irq(irq);
 		return ret;

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 2/7] x86: make headers files the smae in io_apic_xx.c
  2008-08-15 23:42   ` [PATCH 1/7] x86: ordering functions in io_apic_32.c - fix Yinghai Lu
@ 2008-08-15 23:42     ` Yinghai Lu
  2008-08-15 23:42       ` [PATCH 3/7] x86: make 64 handle sis_apic_bug like the 32 bit Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

also make no_timer_check to be global on 64 bit, because vmi_32 is using that.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/x86/kernel/io_apic_32.c |   15 ++++++++++++---
 arch/x86/kernel/io_apic_64.c |   12 +++++++++---
 2 files changed, 21 insertions(+), 6 deletions(-)

Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_32.c
+++ linux-2.6/arch/x86/kernel/io_apic_32.c
@@ -25,28 +25,37 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/bootmem.h>
+#include <linux/pci.h>
 #include <linux/mc146818rtc.h>
 #include <linux/compiler.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/sysdev.h>
-#include <linux/pci.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
-#include <linux/jiffies.h>	/* time_after() */
+#include <linux/jiffies.h>      /* time_after() */
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+#endif
+#include <linux/bootmem.h>
+#include <linux/dmar.h>
 
+#include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/acpi.h>
+#include <asm/dma.h>
 #include <asm/timer.h>
 #include <asm/i8259.h>
 #include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 #include <asm/setup.h>
+#include <asm/irq_remapping.h>
 
 #include <mach_ipi.h>
 #include <mach_apic.h>
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_64.c
+++ linux-2.6/arch/x86/kernel/io_apic_64.c
@@ -27,12 +27,15 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/mc146818rtc.h>
+#include <linux/compiler.h>
 #include <linux/acpi.h>
+#include <linux/module.h>
 #include <linux/sysdev.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
-#include <linux/dmar.h>
-#include <linux/jiffies.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/jiffies.h>	/* time_after() */
 #ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
 #endif
@@ -46,14 +49,17 @@
 #include <asm/proto.h>
 #include <asm/acpi.h>
 #include <asm/dma.h>
+#include <asm/timer.h>
 #include <asm/i8259.h>
 #include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
+#include <asm/setup.h>
 #include <asm/irq_remapping.h>
 
 #include <mach_ipi.h>
 #include <mach_apic.h>
+#include <mach_apicdef.h>
 
 #define __apicdebuginit(type) static type __init
 
@@ -1683,7 +1689,7 @@ void disable_IO_APIC(void)
 	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
-static int no_timer_check;
+int no_timer_check __initdata;
 
 static int __init notimercheck(char *s)
 {

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 3/7] x86: make 64 handle sis_apic_bug like the 32 bit
  2008-08-15 23:42     ` [PATCH 2/7] x86: make headers files the smae in io_apic_xx.c Yinghai Lu
@ 2008-08-15 23:42       ` Yinghai Lu
  2008-08-15 23:42         ` [PATCH 4/7] x86: remve ioapic_force Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

do we have 64bit system with sis chipset?

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/x86/kernel/io_apic_64.c |   28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_64.c
+++ linux-2.6/arch/x86/kernel/io_apic_64.c
@@ -65,7 +65,11 @@
 
 int ioapic_force;
 
-int sis_apic_bug; /* not actually supported, dummy for compile */
+/*
+ *      Is the SiS APIC rmw bug present ?
+ *      -1 = don't know, 0 = no, 1 = yes
+ */
+int sis_apic_bug = -1;
 
 static DEFINE_SPINLOCK(ioapic_lock);
 static DEFINE_SPINLOCK(vector_lock);
@@ -373,9 +377,11 @@ static inline void io_apic_write(unsigne
  * Re-write a value: to be used for read-modify-write
  * cycles where the read already set up the index register.
  */
-static inline void io_apic_modify(unsigned int apic, unsigned int value)
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
 	struct io_apic __iomem *io_apic = io_apic_base(apic);
+        if (sis_apic_bug)
+                writel(reg, &io_apic->index);
 	writel(value, &io_apic->data);
 }
 
@@ -494,7 +500,7 @@ static void __target_IO_APIC_irq(unsigne
 		reg = io_apic_read(apic, 0x10 + pin*2);
 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
 		reg |= vector;
-		io_apic_modify(apic, reg);
+		io_apic_modify(apic, 0x10 + pin*2, reg);
 		if (!entry->next)
 			break;
 		entry = entry->next;
@@ -622,7 +628,7 @@ static inline void io_apic_sync(unsigned
 		pin = entry->pin;					\
 		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
 		reg ACTION;						\
-		io_apic_modify(entry->apic, reg);			\
+		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
 		FINAL;							\
 		if (!entry->next)					\
 			break;						\
@@ -2446,6 +2452,20 @@ void __init setup_IO_APIC(void)
 	check_timer();
 }
 
+/*
+ *      Called after all the initialization is done. If we didnt find any
+ *      APIC bugs then we can allow the modify fast path
+ */
+
+static int __init io_apic_bug_finalize(void)
+{
+        if (sis_apic_bug == -1)
+                sis_apic_bug = 0;
+        return 0;
+}
+
+late_initcall(io_apic_bug_finalize);
+
 struct sysfs_ioapic_data {
 	struct sys_device dev;
 	struct IO_APIC_route_entry entry[0];

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 4/7] x86: remve ioapic_force
  2008-08-15 23:42       ` [PATCH 3/7] x86: make 64 handle sis_apic_bug like the 32 bit Yinghai Lu
@ 2008-08-15 23:42         ` Yinghai Lu
  2008-08-15 23:42           ` [PATCH 5/7] x86: make io_apic_64.c and io_apic_32.c the same Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

no user

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 6709393..cf89524 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -1555,7 +1555,6 @@ static int __init apic_set_verbosity(char *str)
 {
 	if (str == NULL)  {
 		skip_ioapic_setup = 0;
-		ioapic_force = 1;
 		return 0;
 	}
 	if (strcmp("debug", str) == 0)
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index bb024d1..ca87077 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -63,8 +63,6 @@
 
 #define __apicdebuginit(type) static type __init
 
-int ioapic_force;
-
 /*
  *      Is the SiS APIC rmw bug present ?
  *      -1 = don't know, 0 = no, 1 = yes
diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
index d76a083..2d970f6 100644
--- a/include/asm-x86/apic.h
+++ b/include/asm-x86/apic.h
@@ -40,8 +40,6 @@ extern void generic_apic_probe(void);
 extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
-extern int ioapic_force;
-
 extern int disable_apic;
 /*
  * Basic functions accessing APICs.

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 5/7] x86: make io_apic_64.c and io_apic_32.c the same
  2008-08-15 23:42         ` [PATCH 4/7] x86: remve ioapic_force Yinghai Lu
@ 2008-08-15 23:42           ` Yinghai Lu
  2008-08-15 23:42             ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

all the same except INTR_REMAPPING related and ioapic io resource

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/x86/kernel/io_apic_32.c |  213 ++++++++++++-
 arch/x86/kernel/io_apic_64.c |  666 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 832 insertions(+), 47 deletions(-)

Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_32.c
+++ linux-2.6/arch/x86/kernel/io_apic_32.c
@@ -123,7 +123,6 @@ struct irq_cfg {
 	u8 move_in_progress : 1;
 };
 
-
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
 static struct irq_cfg irq_cfg_legacy[] __initdata = {
 	[0]  = { .irq =  0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
@@ -391,6 +390,38 @@ static inline void io_apic_modify(unsign
 	writel(value, &io_apic->data);
 }
 
+#ifdef CONFIG_X86_64
+static bool io_apic_level_ack_pending(unsigned int irq)
+{
+	struct irq_pin_list *entry;
+	unsigned long flags;
+	struct irq_cfg *cfg = irq_cfg(irq);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		unsigned int reg;
+		int pin;
+
+		if (!entry)
+			break;
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+		/* Is the remote IRR bit set? */
+		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+			spin_unlock_irqrestore(&ioapic_lock, flags);
+			return true;
+		}
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return false;
+}
+#endif
+
 union entry_union {
 	struct { u32 w1, w2; };
 	struct IO_APIC_route_entry entry;
@@ -483,17 +514,15 @@ static void set_ioapic_affinity_irq(unsi
 	unsigned int dest;
 	cpumask_t tmp;
 
-	cfg = irq_cfg(irq);
-
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
 		return;
 
+	cfg = irq_cfg(irq);
 	if (assign_irq_vector(irq, mask))
 		return;
 
 	cpus_and(tmp, cfg->domain, mask);
-
 	dest = cpu_mask_to_apicid(tmp);
 	/*
 	 * Only the high 8 bits are valid.
@@ -572,6 +601,54 @@ static void __init replace_pin_at_irq(un
 		add_pin_to_irq(irq, newapic, newpin);
 }
 
+#ifdef CONFIG_X86_64
+/*
+ * Synchronize the IO-APIC and the CPU by doing
+ * a dummy read from the IO-APIC
+ */
+static inline void io_apic_sync(unsigned int apic)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	readl(&io_apic->data);
+}
+
+#define __DO_ACTION(R, ACTION, FINAL)					\
+									\
+{									\
+	int pin;							\
+	struct irq_cfg *cfg;						\
+	struct irq_pin_list *entry;					\
+									\
+	cfg = irq_cfg(irq);						\
+	entry = cfg->irq_2_pin;						\
+	for (;;) {							\
+		unsigned int reg;					\
+		if (!entry)						\
+			break;						\
+		pin = entry->pin;					\
+		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
+		reg ACTION;						\
+		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
+		FINAL;							\
+		if (!entry->next)					\
+			break;						\
+		entry = entry->next;					\
+	}								\
+}
+
+#define DO_ACTION(name,R,ACTION, FINAL)					\
+									\
+	static void name##_IO_APIC_irq (unsigned int irq)		\
+	__DO_ACTION(R, ACTION, FINAL)
+
+/* mask = 1 */
+DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
+
+/* mask = 0 */
+DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
+
+#else
+
 static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
 {
 	struct irq_cfg *cfg;
@@ -620,6 +697,8 @@ static void __unmask_and_level_IO_APIC_i
 				IO_APIC_REDIR_MASKED);
 }
 
+#endif
+
 static void mask_IO_APIC_irq(unsigned int irq)
 {
 	unsigned long flags;
@@ -1055,6 +1134,17 @@ void unlock_vector_lock(void)
 
 static int __assign_irq_vector(int irq, cpumask_t mask)
 {
+	/*
+	 * NOTE! The local APIC isn't very good at handling
+	 * multiple interrupts at the same interrupt level.
+	 * As the interrupt level is determined by taking the
+	 * vector number and shifting that right by 4, we
+	 * want to spread these out a bit so that they don't
+	 * all fall in the same interrupt level.
+	 *
+	 * Also, we've got to be careful not to trash gate
+	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+	 */
         static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
         unsigned int old_vector;
         int cpu;
@@ -1095,9 +1185,13 @@ next:
                 }
                 if (unlikely(current_vector == vector))
                         continue;
-		if (vector == SYSCALL_VECTOR)
+#ifdef CONFIG_X86_64
+                if (vector == IA32_SYSCALL_VECTOR)
                         goto next;
-
+#else
+                if (vector == SYSCALL_VECTOR)
+                        goto next;
+#endif
                 for_each_cpu_mask_nr(new_cpu, new_mask)
                         if (per_cpu(vector_irq, new_cpu)[vector] != -1)
                                 goto next;
@@ -1184,6 +1278,7 @@ static struct irq_chip ioapic_chip;
 #define IOAPIC_EDGE	0
 #define IOAPIC_LEVEL	1
 
+#ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
 {
 	int apic, idx, pin;
@@ -1200,6 +1295,12 @@ static inline int IO_APIC_irq_trigger(in
 	 */
 	return 0;
 }
+#else
+static inline int IO_APIC_irq_trigger(int irq)
+{
+        return 1;
+}
+#endif
 
 static void ioapic_register_intr(int irq, unsigned long trigger)
 {
@@ -1212,15 +1313,18 @@ static void ioapic_register_intr(int irq
 		desc = irq_desc_with_new(irq);
 
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL) {
+	    trigger == IOAPIC_LEVEL)
 		desc->status |= IRQ_LEVEL;
+	else
+		desc->status &= ~IRQ_LEVEL;
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					 handle_fasteoi_irq, "fasteoi");
-	} else {
-		desc->status &= ~IRQ_LEVEL;
+	else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					 handle_edge_irq, "edge");
-	}
 }
 
 static int setup_ioapic_entry(int apic, int irq,
@@ -1662,7 +1766,6 @@ static void __init enable_IO_APIC(void)
 			struct IO_APIC_route_entry entry;
 			entry = ioapic_read_entry(apic, pin);
 
-
 			/* If the interrupt line is enabled and in ExtInt mode
 			 * I have found the pin where the i8259 is connected.
 			 */
@@ -2012,6 +2115,60 @@ static void ack_apic_edge(unsigned int i
 	ack_APIC_irq();
 }
 
+#ifdef CONFIG_X86_64
+static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+{
+        int do_unmask_irq = 0;
+
+        irq_complete_move(irq);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+        /* If we are moving the irq we need to mask it */
+        if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+                do_unmask_irq = 1;
+                mask_IO_APIC_irq(irq);
+        }
+#endif
+
+        /*
+         * We must acknowledge the irq before we move it or the acknowledge will
+         * not propagate properly.
+         */
+        ack_APIC_irq();
+
+        /* Now we can move and renable the irq */
+        if (unlikely(do_unmask_irq)) {
+                /* Only migrate the irq if the ack has been received.
+                 *
+                 * On rare occasions the broadcast level triggered ack gets
+                 * delayed going to ioapics, and if we reprogram the
+                 * vector while Remote IRR is still set the irq will never
+                 * fire again.
+                 *
+                 * To prevent this scenario we read the Remote IRR bit
+                 * of the ioapic.  This has two effects.
+                 * - On any sane system the read of the ioapic will
+                 *   flush writes (and acks) going to the ioapic from
+                 *   this cpu.
+                 * - We get to see if the ACK has actually been delivered.
+                 *
+                 * Based on failed experiments of reprogramming the
+                 * ioapic entry from outside of irq context starting
+                 * with masking the ioapic entry and then polling until
+                 * Remote IRR was clear before reprogramming the
+                 * ioapic I don't trust the Remote IRR bit to be
+                 * completey accurate.
+                 *
+                 * However there appears to be no other way to plug
+                 * this race, so if the Remote IRR bit is not
+                 * accurate and is causing problems then it is a hardware bug
+                 * and you can go talk to the chipset vendor about it.
+                 */
+                if (!io_apic_level_ack_pending(irq))
+                        move_masked_irq(irq, desc);
+                unmask_IO_APIC_irq(irq);
+        }
+}
+#else
 atomic_t irq_mis_count;
 static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
 {
@@ -2053,6 +2210,7 @@ static void ack_apic_level(unsigned int
 		spin_unlock(&ioapic_lock);
 	}
 }
+#endif
 
 static struct irq_chip ioapic_chip __read_mostly = {
 	.name 		= "IO-APIC",
@@ -2224,7 +2382,7 @@ static inline void __init unlock_ExtINT_
 }
 
 static int disable_timer_pin_1 __initdata;
-
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
 static int __init parse_disable_timer_pin_1(char *arg)
 {
 	disable_timer_pin_1 = 1;
@@ -2244,9 +2402,9 @@ static inline void __init check_timer(vo
 {
 	struct irq_cfg *cfg = irq_cfg(0);
 	int apic1, pin1, apic2, pin2;
-	int no_pin1 = 0;
-	unsigned int ver;
 	unsigned long flags;
+	unsigned int ver;
+	int no_pin1 = 0;
 
 	local_irq_save(flags);
 
@@ -2550,6 +2708,7 @@ unsigned int create_irq(unsigned int irq
 		cfg_new = irq_cfg(new);
 		if (cfg_new && cfg_new->vector != 0)
 			continue;
+		/* check if need to create one */
 		if (!cfg_new)
 			cfg_new = irq_cfg_with_new(new);
 		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
@@ -2714,6 +2873,32 @@ int arch_setup_msi_irq(struct pci_dev *d
 	return 0;
 }
 
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+        unsigned int irq;
+        int ret, sub_handle;
+        struct msi_desc *desc;
+        unsigned int irq_want;
+
+        irq_want = build_irq_for_pci_dev(dev) + 0x100;
+        sub_handle = 0;
+        list_for_each_entry(desc, &dev->msi_list, list) {
+                irq = create_irq(irq_want--);
+                if (irq == 0)
+                        return -1;
+                ret = setup_msi_irq(dev, desc, irq);
+                if (ret < 0)
+                        goto error;
+                sub_handle++;
+        }
+        return 0;
+
+error:
+        destroy_irq(irq);
+        return ret;
+}
+
+
 void arch_teardown_msi_irq(unsigned int irq)
 {
 	destroy_irq(irq);
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_64.c
+++ linux-2.6/arch/x86/kernel/io_apic_64.c
@@ -94,18 +94,22 @@ struct mp_config_intsrc mp_irqs[MAX_IRQ_
 /* # of MP IRQ source entries */
 int mp_irq_entries;
 
+#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+int mp_bus_id_to_type[MAX_MP_BUSSES];
+#endif
+
 DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 int skip_ioapic_setup;
 
 static int __init parse_noapic(char *str)
 {
+	/* disable IO-APIC */
 	disable_ioapic_setup();
 	return 0;
 }
 early_param("noapic", parse_noapic);
 
-
 struct irq_cfg;
 struct irq_pin_list;
 struct irq_cfg {
@@ -374,6 +378,8 @@ static inline void io_apic_write(unsigne
 /*
  * Re-write a value: to be used for read-modify-write
  * cycles where the read already set up the index register.
+ *
+ * Older SiS APIC requires we rewrite the index register
  */
 static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
@@ -383,6 +389,7 @@ static inline void io_apic_modify(unsign
 	writel(value, &io_apic->data);
 }
 
+#ifdef CONFIG_X86_64
 static bool io_apic_level_ack_pending(unsigned int irq)
 {
 	struct irq_pin_list *entry;
@@ -412,6 +419,7 @@ static bool io_apic_level_ack_pending(un
 
 	return false;
 }
+#endif
 
 union entry_union {
 	struct { u32 w1, w2; };
@@ -509,7 +517,7 @@ static int assign_irq_vector(int irq, cp
 
 static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
 {
-	struct irq_cfg *cfg = irq_cfg(irq);
+	struct irq_cfg *cfg;
 	unsigned long flags;
 	unsigned int dest;
 	cpumask_t tmp;
@@ -518,12 +526,12 @@ static void set_ioapic_affinity_irq(unsi
 	if (cpus_empty(tmp))
 		return;
 
+	cfg = irq_cfg(irq);
 	if (assign_irq_vector(irq, mask))
 		return;
 
 	cpus_and(tmp, cfg->domain, mask);
 	dest = cpu_mask_to_apicid(tmp);
-
 	/*
 	 * Only the high 8 bits are valid.
 	 */
@@ -534,7 +542,7 @@ static void set_ioapic_affinity_irq(unsi
 	desc->affinity = mask;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
-#endif
+#endif /* CONFIG_SMP */
 
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
@@ -600,6 +608,7 @@ static void __init replace_pin_at_irq(un
 		add_pin_to_irq(irq, newapic, newpin);
 }
 
+#ifdef CONFIG_X86_64
 /*
  * Synchronize the IO-APIC and the CPU by doing
  * a dummy read from the IO-APIC
@@ -645,6 +654,58 @@ DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MA
 /* mask = 0 */
 DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
 
+#else
+
+static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
+{
+	struct irq_cfg *cfg;
+	struct irq_pin_list *entry;
+	unsigned int pin, reg;
+
+	cfg = irq_cfg(irq);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		if (!entry)
+			break;
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+		reg &= ~disable;
+		reg |= enable;
+		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+}
+
+/* mask = 1 */
+static void __mask_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
+}
+
+/* mask = 0 */
+static void __unmask_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
+}
+
+/* mask = 1, trigger = 0 */
+static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
+				IO_APIC_REDIR_LEVEL_TRIGGER);
+}
+
+/* mask = 0, trigger = 1 */
+static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
+				IO_APIC_REDIR_MASKED);
+}
+
+#endif
+
 static void mask_IO_APIC_irq (unsigned int irq)
 {
 	unsigned long flags;
@@ -686,6 +747,64 @@ static void clear_IO_APIC (void)
 			clear_IO_APIC_pin(apic, pin);
 }
 
+#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
+void send_IPI_self(int vector)
+{
+	unsigned int cfg;
+
+	/*
+	 * Wait for idle.
+	 */
+	apic_wait_icr_idle();
+	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+	/*
+	 * Send the IPI. The write to APIC_ICR fires this off.
+	 */
+	apic_write(APIC_ICR, cfg);
+}
+#endif /* !CONFIG_SMP && CONFIG_X86_32*/
+
+#ifdef CONFIG_X86_32
+/*
+ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
+ * specific CPU-side IRQs.
+ */
+
+#define MAX_PIRQS 8
+static int pirq_entries [MAX_PIRQS];
+static int pirqs_enabled;
+
+static int __init ioapic_pirq_setup(char *str)
+{
+	int i, max;
+	int ints[MAX_PIRQS+1];
+
+	get_options(str, ARRAY_SIZE(ints), ints);
+
+	for (i = 0; i < MAX_PIRQS; i++)
+		pirq_entries[i] = -1;
+
+	pirqs_enabled = 1;
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"PIRQ redirection, working around broken MP-BIOS.\n");
+	max = MAX_PIRQS;
+	if (ints[0] < MAX_PIRQS)
+		max = ints[0];
+
+	for (i = 0; i < max; i++) {
+		apic_printk(APIC_VERBOSE, KERN_DEBUG
+				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		/*
+		 * PIRQs are mapped upside down, usually.
+		 */
+		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+	}
+	return 1;
+}
+
+__setup("pirq=", ioapic_pirq_setup);
+#endif /* CONFIG_X86_32 */
+
 #ifdef CONFIG_INTR_REMAP
 /* I/O APIC RTE contents at the OS boot up */
 static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
@@ -859,18 +978,54 @@ int IO_APIC_get_PCI_irq_vector(int bus,
 	return best_guess;
 }
 
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+/*
+ * EISA Edge/Level control register, ELCR
+ */
+static int EISA_ELCR(unsigned int irq)
+{
+	if (irq < 16) {
+		unsigned int port = 0x4d0 + (irq >> 3);
+		return (inb(port) >> (irq & 7)) & 1;
+	}
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"Broken MPtable reports ISA irq %d\n", irq);
+	return 0;
+}
+
+#endif
+
 /* ISA interrupts are always polarity zero edge triggered,
  * when listed as conforming in the MP table. */
 
 #define default_ISA_trigger(idx)	(0)
 #define default_ISA_polarity(idx)	(0)
 
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
+
 /* PCI interrupts are always polarity one level triggered,
  * when listed as conforming in the MP table. */
 
 #define default_PCI_trigger(idx)	(1)
 #define default_PCI_polarity(idx)	(1)
 
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
+
+
 static int MPBIOS_polarity(int idx)
 {
 	int bus = mp_irqs[idx].mp_srcbus;
@@ -928,6 +1083,36 @@ static int MPBIOS_trigger(int idx)
 				trigger = default_ISA_trigger(idx);
 			else
 				trigger = default_PCI_trigger(idx);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+			switch (mp_bus_id_to_type[bus]) {
+				case MP_BUS_ISA: /* ISA pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_EISA: /* EISA pin */
+				{
+					trigger = default_EISA_trigger(idx);
+					break;
+				}
+				case MP_BUS_PCI: /* PCI pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_MCA: /* MCA pin */
+				{
+					trigger = default_MCA_trigger(idx);
+					break;
+				}
+				default:
+				{
+					printk(KERN_WARNING "broken BIOS!!\n");
+					trigger = 1;
+					break;
+				}
+			}
+#endif
 			break;
 		case 1: /* edge */
 		{
@@ -965,6 +1150,7 @@ static inline int irq_trigger(int idx)
 	return MPBIOS_trigger(idx);
 }
 
+int (*ioapic_renumber_irq)(int ioapic, int irq);
 static int pin_2_irq(int idx, int apic, int pin)
 {
 	int irq, i;
@@ -986,7 +1172,32 @@ static int pin_2_irq(int idx, int apic,
 		while (i < apic)
 			irq += nr_ioapic_registers[i++];
 		irq += pin;
+                /*
+                 * For MPS mode, so far only needed by ES7000 platform
+                 */
+                if (ioapic_renumber_irq)
+                        irq = ioapic_renumber_irq(apic, irq);
+	}
+
+#ifdef CONFIG_X86_32
+	/*
+	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
+	 */
+	if ((pin >= 16) && (pin <= 23)) {
+		if (pirq_entries[pin-16] != -1) {
+			if (!pirq_entries[pin-16]) {
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"disabling PIRQ%d\n", pin-16);
+			} else {
+				irq = pirq_entries[pin-16];
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"using PIRQ%d -> IRQ %d\n",
+						pin-16, irq);
+			}
+		}
 	}
+#endif
+
 	return irq;
 }
 
@@ -1056,8 +1267,13 @@ next:
 		}
 		if (unlikely(current_vector == vector))
 			continue;
+#ifdef CONFIG_X86_64
 		if (vector == IA32_SYSCALL_VECTOR)
 			goto next;
+#else
+		if (vector == SYSCALL_VECTOR)
+			goto next;
+#endif
 		for_each_cpu_mask_nr(new_cpu, new_mask)
 			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
 				goto next;
@@ -1138,6 +1354,34 @@ static struct irq_chip ioapic_chip;
 static struct irq_chip ir_ioapic_chip;
 #endif
 
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
+
+#ifdef CONFIG_X86_32
+static inline int IO_APIC_irq_trigger(int irq)
+{
+        int apic, idx, pin;
+
+        for (apic = 0; apic < nr_ioapics; apic++) {
+                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                        idx = find_irq_entry(apic, pin, mp_INT);
+                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+                                return irq_trigger(idx);
+                }
+        }
+        /*
+         * nonexistent IRQs are edge default
+         */
+        return 0;
+}
+#else
+static inline int IO_APIC_irq_trigger(int irq)
+{
+	return 1;
+}
+#endif
+
 static void ioapic_register_intr(int irq, unsigned long trigger)
 {
 	struct irq_desc *desc;
@@ -1148,7 +1392,8 @@ static void ioapic_register_intr(int irq
 	else
 		desc = irq_desc_with_new(irq);
 
-	if (trigger)
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
 		desc->status |= IRQ_LEVEL;
 	else
 		desc->status &= ~IRQ_LEVEL;
@@ -1166,7 +1411,8 @@ static void ioapic_register_intr(int irq
 		return;
 	}
 #endif
-	if (trigger)
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
 					      handle_fasteoi_irq,
 					      "fasteoi");
@@ -1301,6 +1547,10 @@ static void __init setup_IO_APIC_irqs(vo
 		}
 
 		irq = pin_2_irq(idx, apic, pin);
+#ifdef CONFIG_X86_32
+                if (multi_timer_check(apic, irq))
+                        continue;
+#endif
 		add_pin_to_irq(irq, apic, pin);
 
 		setup_IO_APIC_irq(apic, pin, irq,
@@ -1358,6 +1608,7 @@ __apicdebuginit(void) print_IO_APIC(void
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
 	union IO_APIC_reg_02 reg_02;
+	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 	struct irq_cfg *cfg;
 
@@ -1382,6 +1633,8 @@ __apicdebuginit(void) print_IO_APIC(void
 	reg_01.raw = io_apic_read(apic, 1);
 	if (reg_01.bits.version >= 0x10)
 		reg_02.raw = io_apic_read(apic, 2);
+        if (reg_01.bits.version >= 0x20)
+                reg_03.raw = io_apic_read(apic, 3);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
@@ -1397,11 +1650,27 @@ __apicdebuginit(void) print_IO_APIC(void
 	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
 	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
 
-	if (reg_01.bits.version >= 0x10) {
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+	 * but the value of reg_02 is read as the previous read register
+	 * value, so ignore it if reg_02 == reg_01.
+	 */
+	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
 		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
 		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
 	}
 
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
+	 * or reg_03, but the value of reg_0[23] is read as the previous read
+	 * register value, so ignore it if reg_03 == reg_0[12].
+	 */
+	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+	    reg_03.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+	}
+
 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
 
 	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
@@ -1473,7 +1742,7 @@ __apicdebuginit(void) print_APIC_bitfiel
 __apicdebuginit(void) print_local_APIC(void *dummy)
 {
 	unsigned int v, ver, maxlvt;
-	unsigned long icr;
+	u64 icr;
 
 	if (apic_verbosity == APIC_QUIET)
 		return;
@@ -1490,11 +1759,13 @@ __apicdebuginit(void) print_local_APIC(v
 	v = apic_read(APIC_TASKPRI);
 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
-	v = apic_read(APIC_ARBPRI);
-	printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-		v & APIC_ARBPRI_MASK);
-	v = apic_read(APIC_PROCPRI);
-	printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
+		v = apic_read(APIC_ARBPRI);
+		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+			v & APIC_ARBPRI_MASK);
+		v = apic_read(APIC_PROCPRI);
+		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+	}
 
 	v = apic_read(APIC_EOI);
 	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
@@ -1514,8 +1785,13 @@ __apicdebuginit(void) print_local_APIC(v
 	printk(KERN_DEBUG "... APIC IRR field:\n");
 	print_APIC_bitfield(APIC_IRR);
 
-	v = apic_read(APIC_ESR);
-	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
+		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
+			apic_write(APIC_ESR, 0);
+
+		v = apic_read(APIC_ESR);
+		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+	}
 
 	icr = apic_icr_read();
 	printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
@@ -1606,6 +1882,13 @@ void __init enable_IO_APIC(void)
 	int apic;
 	unsigned long flags;
 
+#ifdef CONFIG_X86_32
+	int i;
+	if (!pirqs_enabled)
+		for (i = 0; i < MAX_PIRQS; i++)
+			pirq_entries[i] = -1;
+#endif
+
 	/*
 	 * The number of IO-APIC IRQ registers (== #pins):
 	 */
@@ -1634,6 +1917,10 @@ void __init enable_IO_APIC(void)
 	}
  found_i8259:
 	/* Look to see what if the MP table has reported the ExtINT */
+	/* If we could not find the appropriate pin by looking at the ioapic
+	 * the i8259 probably is not connected the ioapic but give the
+	 * mptable a chance anyway.
+	 */
 	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
 	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
 	/* Trust the MP table if nothing is setup in the hardware */
@@ -1693,6 +1980,122 @@ void disable_IO_APIC(void)
 	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
+#ifdef CONFIG_X86_32
+/*
+ * function to set the IO-APIC physical IDs based on the
+ * values stored in the MPC table.
+ *
+ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+ */
+
+static void __init setup_ioapic_ids_from_mpc(void)
+{
+	union IO_APIC_reg_00 reg_00;
+	physid_mask_t phys_id_present_map;
+	int apic;
+	int i;
+	unsigned char old_id;
+	unsigned long flags;
+
+	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
+		return;
+
+	/*
+	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+	 * no meaning without the serial APIC bus.
+	 */
+	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return;
+	/*
+	 * This is broken; anything with a real cpu count has to
+	 * circumvent this idiocy regardless.
+	 */
+	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
+
+	/*
+	 * Set the IOAPIC ID to the value stored in the MPC table.
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+
+		/* Read the register 0 value */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		old_id = mp_ioapics[apic].mp_apicid;
+
+		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+				apic, mp_ioapics[apic].mp_apicid);
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				reg_00.bits.ID);
+			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
+		}
+
+		/*
+		 * Sanity check, is the ID really free? Every APIC in a
+		 * system must have a unique ID or we get lots of nice
+		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+		 */
+		if (check_apicid_used(phys_id_present_map,
+					mp_ioapics[apic].mp_apicid)) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+				apic, mp_ioapics[apic].mp_apicid);
+			for (i = 0; i < get_physical_broadcast(); i++)
+				if (!physid_isset(i, phys_id_present_map))
+					break;
+			if (i >= get_physical_broadcast())
+				panic("Max APIC ID exceeded!\n");
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				i);
+			physid_set(i, phys_id_present_map);
+			mp_ioapics[apic].mp_apicid = i;
+		} else {
+			physid_mask_t tmp;
+			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
+			apic_printk(APIC_VERBOSE, "Setting %d in the "
+					"phys_id_present_map\n",
+					mp_ioapics[apic].mp_apicid);
+			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+		}
+
+
+		/*
+		 * We need to adjust the IRQ routing table
+		 * if the ID changed.
+		 */
+		if (old_id != mp_ioapics[apic].mp_apicid)
+			for (i = 0; i < mp_irq_entries; i++)
+				if (mp_irqs[i].mp_dstapic == old_id)
+					mp_irqs[i].mp_dstapic
+						= mp_ioapics[apic].mp_apicid;
+
+		/*
+		 * Read the right value from the MPC table and
+		 * write it into the ID register.
+		 */
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"...changing IO-APIC physical APIC ID to %d ...",
+			mp_ioapics[apic].mp_apicid);
+
+		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
+		spin_lock_irqsave(&ioapic_lock, flags);
+
+		/*
+		 * Sanity check
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
+			printk("could not set ID!\n");
+		else
+			apic_printk(APIC_VERBOSE, " ok.\n");
+	}
+}
+#endif
+
 int no_timer_check __initdata;
 
 static int __init notimercheck(char *s)
@@ -1778,8 +2181,10 @@ static unsigned int startup_ioapic_irq(u
 	return was_pending;
 }
 
+#ifdef CONFIG_X86_64
 static int ioapic_retrigger_irq(unsigned int irq)
 {
+
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long flags;
 
@@ -1789,6 +2194,14 @@ static int ioapic_retrigger_irq(unsigned
 
 	return 1;
 }
+#else
+static int ioapic_retrigger_irq(unsigned int irq)
+{
+        send_IPI_self(irq_cfg(irq)->vector);
+
+        return 1;
+}
+#endif
 
 /*
  * Level and edge triggered IO-APIC interrupts need different handling,
@@ -1948,7 +2361,9 @@ asmlinkage void smp_irq_move_cleanup_int
 {
 	unsigned vector, me;
 	ack_APIC_irq();
+#ifdef CONFIG_X86_64
 	exit_idle();
+#endif
 	irq_enter();
 
 	me = smp_processor_id();
@@ -2020,6 +2435,7 @@ static void ack_apic_edge(unsigned int i
 	ack_APIC_irq();
 }
 
+#ifdef CONFIG_X86_64
 static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
 {
 	int do_unmask_irq = 0;
@@ -2072,6 +2488,49 @@ static void ack_apic_level(unsigned int
 		unmask_IO_APIC_irq(irq);
 	}
 }
+#else
+atomic_t irq_mis_count;
+static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long v;
+	int i;
+
+	irq_complete_move(irq);
+	move_native_irq(irq, desc);
+	/*
+	* It appears there is an erratum which affects at least version 0x11
+	* of I/O APIC (that's the 82093AA and cores integrated into various
+	* chipsets).  Under certain conditions a level-triggered interrupt is
+	* erroneously delivered as edge-triggered one but the respective IRR
+	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
+	* message but it will never arrive and further interrupts are blocked
+	* from the source.  The exact reason is so far unknown, but the
+	* phenomenon was observed when two consecutive interrupt requests
+	* from a given source get delivered to the same CPU and the source is
+	* temporarily disabled in between.
+	*
+	* A workaround is to simulate an EOI message manually.  We achieve it
+	* by setting the trigger mode to edge and then to level when the edge
+	* trigger mode gets detected in the TMR of a local APIC for a
+	* level-triggered interrupt.  We mask the source for the time of the
+	* operation to prevent an edge-triggered interrupt escaping meanwhile.
+	* The idea is from Manfred Spraul.  --macro
+	*/
+	i = irq_cfg(irq)->vector;
+
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+	ack_APIC_irq();
+
+	if (!(v & (1 << (i & 0x1f)))) {
+		atomic_inc(&irq_mis_count);
+		spin_lock(&ioapic_lock);
+		__mask_and_edge_IO_APIC_irq(irq);
+		__unmask_and_level_IO_APIC_irq(irq);
+		spin_unlock(&ioapic_lock);
+	}
+}
+#endif
 
 static struct irq_chip ioapic_chip __read_mostly = {
 	.name 		= "IO-APIC",
@@ -2137,20 +2596,24 @@ static inline void init_IO_APIC_traps(vo
 	}
 }
 
-static void unmask_lapic_irq(unsigned int irq)
+/*
+ * The local APIC irq-chip implementation:
+ */
+
+static void mask_lapic_irq(unsigned int irq)
 {
 	unsigned long v;
 
 	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 }
 
-static void mask_lapic_irq(unsigned int irq)
+static void unmask_lapic_irq(unsigned int irq)
 {
 	unsigned long v;
 
 	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
 static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
@@ -2178,19 +2641,19 @@ static void lapic_register_intr(int irq)
 static void __init setup_nmi(void)
 {
 	/*
- 	 * Dirty trick to enable the NMI watchdog ...
+	 * Dirty trick to enable the NMI watchdog ...
 	 * We put the 8259A master into AEOI mode and
 	 * unmask on all local APICs LVT0 as NMI.
 	 *
 	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
 	 * is from Maciej W. Rozycki - so we do not have to EOI from
 	 * the NMI handler or the timer interrupt.
-	 */ 
-	printk(KERN_INFO "activating NMI Watchdog ...");
+	 */
+	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
 
 	enable_NMI_through_LVT0();
 
-	printk(" done.\n");
+	apic_printk(APIC_VERBOSE, " done.\n");
 }
 
 /*
@@ -2207,12 +2670,17 @@ static inline void __init unlock_ExtINT_
 	unsigned char save_control, save_freq_select;
 
 	pin  = find_isa_irq_pin(8, mp_INT);
+	if (pin == -1) {
+		WARN_ON_ONCE(1);
+		return;
+	}
 	apic = find_isa_irq_apic(8, mp_INT);
-	if (pin == -1)
+	if (apic == -1) {
+		WARN_ON_ONCE(1);
 		return;
+	}
 
 	entry0 = ioapic_read_entry(apic, pin);
-
 	clear_IO_APIC_pin(apic, pin);
 
 	memset(&entry1, 0, sizeof(entry1));
@@ -2264,17 +2732,21 @@ int timer_through_8259 __initdata;
  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  * fanatically on his truly buggy board.
  *
- * FIXME: really need to revamp this for modern platforms only.
+ * FIXME: really need to revamp this for all platforms.
  */
 static inline void __init check_timer(void)
 {
 	struct irq_cfg *cfg = irq_cfg(0);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
+	unsigned int ver;
 	int no_pin1 = 0;
 
 	local_irq_save(flags);
 
+        ver = apic_read(APIC_LVR);
+        ver = GET_APIC_VERSION(ver);
+
 	/*
 	 * get/set the timer IRQ vector:
 	 */
@@ -2283,10 +2755,18 @@ static inline void __init check_timer(vo
 
 	/*
 	 * As IRQ0 is to be enabled in the 8259A, the virtual
-	 * wire has to be disabled in the local APIC.
+	 * wire has to be disabled in the local APIC.  Also
+	 * timer interrupts need to be acknowledged manually in
+	 * the 8259A for the i82489DX when using the NMI
+	 * watchdog as that APIC treats NMIs as level-triggered.
+	 * The AEOI mode will finish them in the 8259A
+	 * automatically.
 	 */
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 	init_8259A(1);
+#ifdef CONFIG_X86_32
+	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+#endif
 
 	pin1  = find_isa_irq_pin(0, mp_INT);
 	apic1 = find_isa_irq_apic(0, mp_INT);
@@ -2378,6 +2858,9 @@ static inline void __init check_timer(vo
 			    "through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = NMI_NONE;
 	}
+#ifdef CONFIG_X86_32
+	timer_ack = 0;
+#endif
 
 	apic_printk(APIC_QUIET, KERN_INFO
 		    "...trying to set up timer as Virtual Wire IRQ...\n");
@@ -2431,19 +2914,29 @@ out:
  * the I/O APIC in all cases now.  No actual device should request
  * it anyway.  --macro
  */
-#define PIC_IRQS	(1<<2)
+#define PIC_IRQS	(1 << PIC_CASCADE_IR)
 
 void __init setup_IO_APIC(void)
 {
 
+#ifdef CONFIG_X86_32
+	enable_IO_APIC();
+#else
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
+#endif
 
 	io_apic_irqs = ~PIC_IRQS;
 
 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
-
+        /*
+         * Set up IO-APIC IRQ routing.
+         */
+#ifdef CONFIG_X86_32
+        if (!acpi_ioapic)
+                setup_ioapic_ids_from_mpc();
+#endif
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
@@ -3104,7 +3597,93 @@ int arch_setup_ht_irq(unsigned int irq,
 
 #ifdef CONFIG_ACPI
 
-#define IO_APIC_MAX_ID		0xFE
+#ifdef CONFIG_X86_32
+int __init io_apic_get_unique_id(int ioapic, int apic_id)
+{
+	union IO_APIC_reg_00 reg_00;
+	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
+	physid_mask_t tmp;
+	unsigned long flags;
+	int i = 0;
+
+	/*
+	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
+	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
+	 * supports up to 16 on one shared APIC bus.
+	 *
+	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+	 *      advantage of new APIC bus architecture.
+	 */
+
+	if (physids_empty(apic_id_map))
+		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(ioapic, 0);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	if (apic_id >= get_physical_broadcast()) {
+		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+			"%d\n", ioapic, apic_id, reg_00.bits.ID);
+		apic_id = reg_00.bits.ID;
+	}
+
+	/*
+	 * Every APIC in a system must have a unique ID or we get lots of nice
+	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+	 */
+	if (check_apicid_used(apic_id_map, apic_id)) {
+
+		for (i = 0; i < get_physical_broadcast(); i++) {
+			if (!check_apicid_used(apic_id_map, i))
+				break;
+		}
+
+		if (i == get_physical_broadcast())
+			panic("Max apic_id exceeded!\n");
+
+		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+			"trying %d\n", ioapic, apic_id, i);
+
+		apic_id = i;
+	}
+
+	tmp = apicid_to_cpu_present(apic_id);
+	physids_or(apic_id_map, apic_id_map, tmp);
+
+	if (reg_00.bits.ID != apic_id) {
+		reg_00.bits.ID = apic_id;
+
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(ioapic, 0, reg_00.raw);
+		reg_00.raw = io_apic_read(ioapic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		/* Sanity check */
+		if (reg_00.bits.ID != apic_id) {
+			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+			return -1;
+		}
+	}
+
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+
+	return apic_id;
+}
+
+int __init io_apic_get_version(int ioapic)
+{
+	union IO_APIC_reg_01	reg_01;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_01.raw = io_apic_read(ioapic, 1);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return reg_01.bits.version;
+}
+#endif
 
 int __init io_apic_get_redir_entries (int ioapic)
 {
@@ -3206,6 +3785,7 @@ void __init setup_ioapic_dest(void)
 }
 #endif
 
+#ifdef CONFIG_X86_64
 #define IOAPIC_RESOURCE_NAME_SIZE 11
 
 static struct resource *ioapic_resources;
@@ -3241,36 +3821,56 @@ static struct resource * __init ioapic_s
 
 	return res;
 }
+#endif
 
 void __init ioapic_init_mappings(void)
 {
 	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-	struct resource *ioapic_res;
 	int i;
+#ifdef CONFIG_X86_64
+	struct resource *ioapic_res;
 
 	ioapic_res = ioapic_setup_resources();
+#endif
 	for (i = 0; i < nr_ioapics; i++) {
 		if (smp_found_config) {
 			ioapic_phys = mp_ioapics[i].mp_apicaddr;
+#ifdef CONFIG_X86_32
+                        if (!ioapic_phys) {
+                                printk(KERN_ERR
+                                       "WARNING: bogus zero IO-APIC "
+                                       "address found in MPTABLE, "
+                                       "disabling IO/APIC support!\n");
+                                smp_found_config = 0;
+                                skip_ioapic_setup = 1;
+                                goto fake_ioapic_page;
+                        }
+#endif
 		} else {
+#ifdef CONFIG_X86_32
+fake_ioapic_page:
+#endif
 			ioapic_phys = (unsigned long)
 				alloc_bootmem_pages(PAGE_SIZE);
 			ioapic_phys = __pa(ioapic_phys);
 		}
 		set_fixmap_nocache(idx, ioapic_phys);
 		apic_printk(APIC_VERBOSE,
-			    "mapped IOAPIC to %016lx (%016lx)\n",
+			    "mapped IOAPIC to %08lx (%08lx)\n",
 			    __fix_to_virt(idx), ioapic_phys);
 		idx++;
 
+#ifdef CONFIG_X86_64
 		if (ioapic_res != NULL) {
 			ioapic_res->start = ioapic_phys;
 			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
 			ioapic_res++;
 		}
+#endif
 	}
 }
 
+#ifdef CONFIG_X86_64
 static int __init ioapic_insert_resources(void)
 {
 	int i;
@@ -3293,4 +3893,4 @@ static int __init ioapic_insert_resource
 /* Insert the IO APIC resources after PCI initialization has occured to handle
  * IO APICS that are mapped in on a BAR in PCI space. */
 late_initcall(ioapic_insert_resources);
-
+#endif

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 6/7] rename io_apic_64.c to io_apic.c
  2008-08-15 23:42           ` [PATCH 5/7] x86: make io_apic_64.c and io_apic_32.c the same Yinghai Lu
@ 2008-08-15 23:42             ` Yinghai Lu
  2008-08-15 23:42               ` [PATCH 7/7] make 32 bit have io_apic resource in /proc/iomem Yinghai Lu
  2008-08-16  8:02               ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Ingo Molnar
  0 siblings, 2 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/x86/kernel/Makefile     |    2 
 arch/x86/kernel/io_apic.c    | 3898 +++++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/io_apic_32.c | 3220 -----------------------------------
 arch/x86/kernel/io_apic_64.c | 3898 -------------------------------------------
 4 files changed, 3899 insertions(+), 7119 deletions(-)

Index: linux-2.6/arch/x86/kernel/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/kernel/Makefile
+++ linux-2.6/arch/x86/kernel/Makefile
@@ -65,7 +65,7 @@ obj-$(CONFIG_X86_64_SMP)	+= tsc_sync.o s
 obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline_$(BITS).o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic_$(BITS).o nmi.o
-obj-$(CONFIG_X86_IO_APIC)	+= io_apic_$(BITS).o
+obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec_$(BITS).o
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -0,0 +1,3896 @@
+/*
+ *	Intel IO-APIC support for multi-Pentium hosts.
+ *
+ *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
+ *
+ *	Many thanks to Stig Venaas for trying out countless experimental
+ *	patches and reporting/debugging problems patiently!
+ *
+ *	(c) 1999, Multiple IO-APIC support, developed by
+ *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+ *	further tested and cleaned up by Zach Brown <zab@redhat.com>
+ *	and Ingo Molnar <mingo@redhat.com>
+ *
+ *	Fixes
+ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+ *					thanks to Eric Gilmore
+ *					and Rolf G. Tews
+ *					for testing these extensively
+ *	Paul Diefenbaugh	:	Added full ACPI support
+ */
+
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/mc146818rtc.h>
+#include <linux/compiler.h>
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/sysdev.h>
+#include <linux/msi.h>
+#include <linux/htirq.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/jiffies.h>	/* time_after() */
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+#endif
+#include <linux/bootmem.h>
+#include <linux/dmar.h>
+
+#include <asm/idle.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/acpi.h>
+#include <asm/dma.h>
+#include <asm/timer.h>
+#include <asm/i8259.h>
+#include <asm/nmi.h>
+#include <asm/msidef.h>
+#include <asm/hypertransport.h>
+#include <asm/setup.h>
+#include <asm/irq_remapping.h>
+
+#include <mach_ipi.h>
+#include <mach_apic.h>
+#include <mach_apicdef.h>
+
+#define __apicdebuginit(type) static type __init
+
+/*
+ *      Is the SiS APIC rmw bug present ?
+ *      -1 = don't know, 0 = no, 1 = yes
+ */
+int sis_apic_bug = -1;
+
+static DEFINE_SPINLOCK(ioapic_lock);
+static DEFINE_SPINLOCK(vector_lock);
+
+int first_free_entry;
+/*
+ * Rough estimation of how many shared IRQs there are, can
+ * be changed anytime.
+ */
+int pin_map_size;
+
+/*
+ * # of IRQ routing registers
+ */
+int nr_ioapic_registers[MAX_IO_APICS];
+
+/* I/O APIC entries */
+struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
+int nr_ioapics;
+
+/* MP IRQ source entries */
+struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+
+/* # of MP IRQ source entries */
+int mp_irq_entries;
+
+#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+int mp_bus_id_to_type[MAX_MP_BUSSES];
+#endif
+
+DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+
+int skip_ioapic_setup;
+
+static int __init parse_noapic(char *str)
+{
+	/* disable IO-APIC */
+	disable_ioapic_setup();
+	return 0;
+}
+early_param("noapic", parse_noapic);
+
+struct irq_cfg;
+struct irq_pin_list;
+struct irq_cfg {
+	unsigned int irq;
+	struct irq_cfg *next;
+	struct irq_pin_list *irq_2_pin;
+	cpumask_t domain;
+	cpumask_t old_domain;
+	unsigned move_cleanup_count;
+	u8 vector;
+	u8 move_in_progress : 1;
+};
+
+/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+static struct irq_cfg irq_cfg_legacy[] __initdata = {
+	[0]  = { .irq =  0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
+	[1]  = { .irq =  1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
+	[2]  = { .irq =  2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
+	[3]  = { .irq =  3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR,  },
+	[4]  = { .irq =  4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR,  },
+	[5]  = { .irq =  5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR,  },
+	[6]  = { .irq =  6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR,  },
+	[7]  = { .irq =  7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR,  },
+	[8]  = { .irq =  8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR,  },
+	[9]  = { .irq =  9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR,  },
+	[10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
+	[11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
+	[12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
+	[13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
+	[14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
+	[15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
+};
+
+static struct irq_cfg irq_cfg_init = { .irq =  -1U, };
+/* need to be biger than size of irq_cfg_legacy */
+static int nr_irq_cfg = 32;
+
+static int __init parse_nr_irq_cfg(char *arg)
+{
+	if (arg) {
+		nr_irq_cfg = simple_strtoul(arg, NULL, 0);
+		if (nr_irq_cfg < 32)
+			nr_irq_cfg = 32;
+	}
+	return 0;
+}
+
+early_param("nr_irq_cfg", parse_nr_irq_cfg);
+
+static void init_one_irq_cfg(struct irq_cfg *cfg)
+{
+	memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
+}
+
+static struct irq_cfg *irq_cfgx;
+static struct irq_cfg *irq_cfgx_free;
+static void __init init_work(void *data)
+{
+	struct dyn_array *da = data;
+	struct irq_cfg *cfg;
+	int legacy_count;
+	int i;
+
+	cfg = *da->name;
+
+	memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
+
+	legacy_count = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
+	for (i = legacy_count; i < *da->nr; i++)
+		init_one_irq_cfg(&cfg[i]);
+
+	for (i = 1; i < *da->nr; i++)
+		cfg[i-1].next = &cfg[i];
+
+	irq_cfgx_free = &irq_cfgx[legacy_count];
+	irq_cfgx[legacy_count - 1].next = NULL;
+}
+
+#define for_each_irq_cfg(cfg)		\
+	for (cfg = irq_cfgx; cfg; cfg = cfg->next)
+
+DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
+
+static struct irq_cfg *irq_cfg(unsigned int irq)
+{
+	struct irq_cfg *cfg;
+
+	cfg = irq_cfgx;
+	while (cfg) {
+		if (cfg->irq == irq)
+			return cfg;
+
+		cfg = cfg->next;
+	}
+
+	return NULL;
+}
+
+static struct irq_cfg *irq_cfg_with_new(unsigned int irq)
+{
+	struct irq_cfg *cfg, *cfg_pri;
+	int i;
+	int count = 0;
+
+	cfg_pri = cfg = irq_cfgx;
+	while (cfg) {
+		if (cfg->irq == irq)
+			return cfg;
+
+		cfg_pri = cfg;
+		cfg = cfg->next;
+		count++;
+	}
+
+	if (!irq_cfgx_free) {
+		unsigned long phys;
+		unsigned long total_bytes;
+		/*
+		 *  we run out of pre-allocate ones, allocate more
+		 */
+		printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
+
+		total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
+		if (after_bootmem)
+			cfg = kzalloc(total_bytes, GFP_ATOMIC);
+		else
+			cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
+
+		if (!cfg)
+			panic("please boot with nr_irq_cfg= %d\n", count * 2);
+
+		phys = __pa(cfg);
+		printk(KERN_DEBUG "irq_irq ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
+
+		for (i = 0; i < nr_irq_cfg; i++)
+			init_one_irq_cfg(&cfg[i]);
+
+		for (i = 1; i < nr_irq_cfg; i++)
+			cfg[i-1].next = &cfg[i];
+
+		irq_cfgx_free = cfg;
+	}
+
+	cfg = irq_cfgx_free;
+	irq_cfgx_free = irq_cfgx_free->next;
+	cfg->next = NULL;
+	if (cfg_pri)
+		cfg_pri->next = cfg;
+	else
+		irq_cfgx = cfg;
+	cfg->irq = irq;
+	printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
+#ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
+	{
+		/* dump the results */
+		struct irq_cfg *cfg;
+		unsigned long phys;
+		unsigned long bytes = sizeof(struct irq_cfg);
+
+		printk(KERN_DEBUG "=========================== %d\n", irq);
+		printk(KERN_DEBUG "irq_cfg dump after get that for %d\n", irq);
+		for_each_irq_cfg(cfg) {
+			phys = __pa(cfg);
+			printk(KERN_DEBUG "irq_cfg %d ==> [%#lx - %#lx]\n", cfg->irq, phys, phys + bytes);
+		}
+		printk(KERN_DEBUG "===========================\n");
+	}
+#endif
+	return cfg;
+}
+
+/*
+ * This is performance-critical, we want to do it O(1)
+ *
+ * the indexing order of this array favors 1:1 mappings
+ * between pins and IRQs.
+ */
+
+struct irq_pin_list {
+	int apic, pin;
+	struct irq_pin_list *next;
+};
+
+static struct irq_pin_list *irq_2_pin_head;
+/* fill one page ? */
+static int nr_irq_2_pin = 0x100;
+static struct irq_pin_list *irq_2_pin_ptr;
+static void __init irq_2_pin_init_work(void *data)
+{
+	struct dyn_array *da = data;
+	struct irq_pin_list *pin;
+	int i;
+
+	pin = *da->name;
+
+	for (i = 1; i < *da->nr; i++)
+		pin[i-1].next = &pin[i];
+
+	irq_2_pin_ptr = &pin[0];
+}
+DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
+
+static struct irq_pin_list *get_one_free_irq_2_pin(void)
+{
+	struct irq_pin_list *pin;
+	int i;
+
+	pin = irq_2_pin_ptr;
+
+	if (pin) {
+		irq_2_pin_ptr = pin->next;
+		pin->next = NULL;
+		return pin;
+	}
+
+	/*
+	 *  we run out of pre-allocate ones, allocate more
+	 */
+	printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
+
+	if (after_bootmem)
+		pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
+				 GFP_ATOMIC);
+	else
+		pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
+				nr_irq_2_pin, PAGE_SIZE, 0);
+
+	if (!pin)
+		panic("can not get more irq_2_pin\n");
+
+	for (i = 1; i < nr_irq_2_pin; i++)
+		pin[i-1].next = &pin[i];
+
+	irq_2_pin_ptr = pin->next;
+	pin->next = NULL;
+
+	return pin;
+}
+
+struct io_apic {
+	unsigned int index;
+	unsigned int unused[3];
+	unsigned int data;
+};
+
+static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+{
+	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+}
+
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(reg, &io_apic->index);
+	return readl(&io_apic->data);
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(reg, &io_apic->index);
+	writel(value, &io_apic->data);
+}
+
+/*
+ * Re-write a value: to be used for read-modify-write
+ * cycles where the read already set up the index register.
+ *
+ * Older SiS APIC requires we rewrite the index register
+ */
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+        if (sis_apic_bug)
+                writel(reg, &io_apic->index);
+	writel(value, &io_apic->data);
+}
+
+#ifdef CONFIG_X86_64
+static bool io_apic_level_ack_pending(unsigned int irq)
+{
+	struct irq_pin_list *entry;
+	unsigned long flags;
+	struct irq_cfg *cfg = irq_cfg(irq);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		unsigned int reg;
+		int pin;
+
+		if (!entry)
+			break;
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+		/* Is the remote IRR bit set? */
+		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+			spin_unlock_irqrestore(&ioapic_lock, flags);
+			return true;
+		}
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return false;
+}
+#endif
+
+union entry_union {
+	struct { u32 w1, w2; };
+	struct IO_APIC_route_entry entry;
+};
+
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+	union entry_union eu;
+	unsigned long flags;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+	return eu.entry;
+}
+
+/*
+ * When we write a new IO APIC routing entry, we need to write the high
+ * word first! If the mask bit in the low word is clear, we will enable
+ * the interrupt, and we need to make sure the entry is fully populated
+ * before that happens.
+ */
+static void
+__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+	union entry_union eu;
+	eu.entry = e;
+	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__ioapic_write_entry(apic, pin, e);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+/*
+ * When we mask an IO APIC routing entry, we need to write the low
+ * word first, in order to set the mask bit before we change the
+ * high bits!
+ */
+static void ioapic_mask_entry(int apic, int pin)
+{
+	unsigned long flags;
+	union entry_union eu = { .entry.mask = 1 };
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
+{
+	int apic, pin;
+	struct irq_cfg *cfg;
+	struct irq_pin_list *entry;
+
+	cfg = irq_cfg(irq);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		unsigned int reg;
+
+		if (!entry)
+			break;
+
+		apic = entry->apic;
+		pin = entry->pin;
+#ifdef CONFIG_INTR_REMAP
+		/*
+		 * With interrupt-remapping, destination information comes
+		 * from interrupt-remapping table entry.
+		 */
+		if (!irq_remapped(irq))
+			io_apic_write(apic, 0x11 + pin*2, dest);
+#else
+		io_apic_write(apic, 0x11 + pin*2, dest);
+#endif
+		reg = io_apic_read(apic, 0x10 + pin*2);
+		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+		reg |= vector;
+		io_apic_modify(apic, 0x10 + pin*2, reg);
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+}
+
+static int assign_irq_vector(int irq, cpumask_t mask);
+
+static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int dest;
+	cpumask_t tmp;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	cfg = irq_cfg(irq);
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+	/*
+	 * Only the high 8 bits are valid.
+	 */
+	dest = SET_APIC_LOGICAL_ID(dest);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__target_IO_APIC_irq(irq, dest, cfg->vector);
+	desc->affinity = mask;
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+ * shared ISA-space IRQs, so we have to support them. We are super
+ * fast in the common case, and fast for shared ISA-space IRQs.
+ */
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
+{
+	struct irq_cfg *cfg;
+	struct irq_pin_list *entry;
+
+	/* first time to refer irq_cfg, so with new */
+	cfg = irq_cfg_with_new(irq);
+	entry = cfg->irq_2_pin;
+	if (!entry) {
+		entry = get_one_free_irq_2_pin();
+		cfg->irq_2_pin = entry;
+		entry->apic = apic;
+		entry->pin = pin;
+		printk(KERN_DEBUG " 0 add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
+		return;
+	}
+
+	while (entry->next) {
+		/* not again, please */
+		if (entry->apic == apic && entry->pin == pin)
+			return;
+
+		entry = entry->next;
+	}
+
+	entry->next = get_one_free_irq_2_pin();
+	entry = entry->next;
+	entry->apic = apic;
+	entry->pin = pin;
+	printk(KERN_DEBUG " x add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
+}
+
+/*
+ * Reroute an IRQ to a different pin.
+ */
+static void __init replace_pin_at_irq(unsigned int irq,
+				      int oldapic, int oldpin,
+				      int newapic, int newpin)
+{
+	struct irq_cfg *cfg = irq_cfg(irq);
+	struct irq_pin_list *entry = cfg->irq_2_pin;
+	int replaced = 0;
+
+	while (entry) {
+		if (entry->apic == oldapic && entry->pin == oldpin) {
+			entry->apic = newapic;
+			entry->pin = newpin;
+			replaced = 1;
+			/* every one is different, right? */
+			break;
+		}
+		entry = entry->next;
+	}
+
+	/* why? call replace before add? */
+	if (!replaced)
+		add_pin_to_irq(irq, newapic, newpin);
+}
+
+#ifdef CONFIG_X86_64
+/*
+ * Synchronize the IO-APIC and the CPU by doing
+ * a dummy read from the IO-APIC
+ */
+static inline void io_apic_sync(unsigned int apic)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	readl(&io_apic->data);
+}
+
+#define __DO_ACTION(R, ACTION, FINAL)					\
+									\
+{									\
+	int pin;							\
+	struct irq_cfg *cfg;						\
+	struct irq_pin_list *entry;					\
+									\
+	cfg = irq_cfg(irq);						\
+	entry = cfg->irq_2_pin;						\
+	for (;;) {							\
+		unsigned int reg;					\
+		if (!entry)						\
+			break;						\
+		pin = entry->pin;					\
+		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
+		reg ACTION;						\
+		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
+		FINAL;							\
+		if (!entry->next)					\
+			break;						\
+		entry = entry->next;					\
+	}								\
+}
+
+#define DO_ACTION(name,R,ACTION, FINAL)					\
+									\
+	static void name##_IO_APIC_irq (unsigned int irq)		\
+	__DO_ACTION(R, ACTION, FINAL)
+
+/* mask = 1 */
+DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
+
+/* mask = 0 */
+DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
+
+#else
+
+static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
+{
+	struct irq_cfg *cfg;
+	struct irq_pin_list *entry;
+	unsigned int pin, reg;
+
+	cfg = irq_cfg(irq);
+	entry = cfg->irq_2_pin;
+	for (;;) {
+		if (!entry)
+			break;
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+		reg &= ~disable;
+		reg |= enable;
+		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
+		if (!entry->next)
+			break;
+		entry = entry->next;
+	}
+}
+
+/* mask = 1 */
+static void __mask_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
+}
+
+/* mask = 0 */
+static void __unmask_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
+}
+
+/* mask = 1, trigger = 0 */
+static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
+				IO_APIC_REDIR_LEVEL_TRIGGER);
+}
+
+/* mask = 0, trigger = 1 */
+static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
+{
+	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
+				IO_APIC_REDIR_MASKED);
+}
+
+#endif
+
+static void mask_IO_APIC_irq (unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__mask_IO_APIC_irq(irq);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void unmask_IO_APIC_irq (unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__unmask_IO_APIC_irq(irq);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+{
+	struct IO_APIC_route_entry entry;
+
+	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+	entry = ioapic_read_entry(apic, pin);
+	if (entry.delivery_mode == dest_SMI)
+		return;
+	/*
+	 * Disable it in the IO-APIC irq-routing table:
+	 */
+	ioapic_mask_entry(apic, pin);
+}
+
+static void clear_IO_APIC (void)
+{
+	int apic, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			clear_IO_APIC_pin(apic, pin);
+}
+
+#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
+void send_IPI_self(int vector)
+{
+	unsigned int cfg;
+
+	/*
+	 * Wait for idle.
+	 */
+	apic_wait_icr_idle();
+	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+	/*
+	 * Send the IPI. The write to APIC_ICR fires this off.
+	 */
+	apic_write(APIC_ICR, cfg);
+}
+#endif /* !CONFIG_SMP && CONFIG_X86_32*/
+
+#ifdef CONFIG_X86_32
+/*
+ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
+ * specific CPU-side IRQs.
+ */
+
+#define MAX_PIRQS 8
+static int pirq_entries [MAX_PIRQS];
+static int pirqs_enabled;
+
+static int __init ioapic_pirq_setup(char *str)
+{
+	int i, max;
+	int ints[MAX_PIRQS+1];
+
+	get_options(str, ARRAY_SIZE(ints), ints);
+
+	for (i = 0; i < MAX_PIRQS; i++)
+		pirq_entries[i] = -1;
+
+	pirqs_enabled = 1;
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"PIRQ redirection, working around broken MP-BIOS.\n");
+	max = MAX_PIRQS;
+	if (ints[0] < MAX_PIRQS)
+		max = ints[0];
+
+	for (i = 0; i < max; i++) {
+		apic_printk(APIC_VERBOSE, KERN_DEBUG
+				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		/*
+		 * PIRQs are mapped upside down, usually.
+		 */
+		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+	}
+	return 1;
+}
+
+__setup("pirq=", ioapic_pirq_setup);
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_INTR_REMAP
+/* I/O APIC RTE contents at the OS boot up */
+static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
+
+/*
+ * Saves and masks all the unmasked IO-APIC RTE's
+ */
+int save_mask_IO_APIC_setup(void)
+{
+	union IO_APIC_reg_01 reg_01;
+	unsigned long flags;
+	int apic, pin;
+
+	/*
+	 * The number of IO-APIC IRQ registers (== #pins):
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_01.raw = io_apic_read(apic, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+	}
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		early_ioapic_entries[apic] =
+			kzalloc(sizeof(struct IO_APIC_route_entry) *
+				nr_ioapic_registers[apic], GFP_KERNEL);
+		if (!early_ioapic_entries[apic])
+			return -ENOMEM;
+	}
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+
+			entry = early_ioapic_entries[apic][pin] =
+				ioapic_read_entry(apic, pin);
+			if (!entry.mask) {
+				entry.mask = 1;
+				ioapic_write_entry(apic, pin, entry);
+			}
+		}
+	return 0;
+}
+
+void restore_IO_APIC_setup(void)
+{
+	int apic, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			ioapic_write_entry(apic, pin,
+					   early_ioapic_entries[apic][pin]);
+}
+
+void reinit_intr_remapped_IO_APIC(int intr_remapping)
+{
+	/*
+	 * for now plain restore of previous settings.
+	 * TBD: In the case of OS enabling interrupt-remapping,
+	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
+	 * table entries. for now, do a plain restore, and wait for
+	 * the setup_IO_APIC_irqs() to do proper initialization.
+	 */
+	restore_IO_APIC_setup();
+}
+#endif
+
+/*
+ * Find the IRQ entry number of a certain pin.
+ */
+static int find_irq_entry(int apic, int pin, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++)
+		if (mp_irqs[i].mp_irqtype == type &&
+		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
+		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
+		    mp_irqs[i].mp_dstirq == pin)
+			return i;
+
+	return -1;
+}
+
+/*
+ * Find the pin to which IRQ[irq] (ISA) is connected
+ */
+static int __init find_isa_irq_pin(int irq, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].mp_srcbus;
+
+		if (test_bit(lbus, mp_bus_not_pci) &&
+		    (mp_irqs[i].mp_irqtype == type) &&
+		    (mp_irqs[i].mp_srcbusirq == irq))
+
+			return mp_irqs[i].mp_dstirq;
+	}
+	return -1;
+}
+
+static int __init find_isa_irq_apic(int irq, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].mp_srcbus;
+
+		if (test_bit(lbus, mp_bus_not_pci) &&
+		    (mp_irqs[i].mp_irqtype == type) &&
+		    (mp_irqs[i].mp_srcbusirq == irq))
+			break;
+	}
+	if (i < mp_irq_entries) {
+		int apic;
+		for(apic = 0; apic < nr_ioapics; apic++) {
+			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
+				return apic;
+		}
+	}
+
+	return -1;
+}
+
+/*
+ * Find a specific PCI IRQ entry.
+ * Not an __init, possibly needed by modules
+ */
+static int pin_2_irq(int idx, int apic, int pin);
+
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+{
+	int apic, i, best_guess = -1;
+
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+		bus, slot, pin);
+	if (test_bit(bus, mp_bus_not_pci)) {
+		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		return -1;
+	}
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].mp_srcbus;
+
+		for (apic = 0; apic < nr_ioapics; apic++)
+			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
+			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
+				break;
+
+		if (!test_bit(lbus, mp_bus_not_pci) &&
+		    !mp_irqs[i].mp_irqtype &&
+		    (bus == lbus) &&
+		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
+			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
+
+			if (!(apic || IO_APIC_IRQ(irq)))
+				continue;
+
+			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
+				return irq;
+			/*
+			 * Use the first all-but-pin matching entry as a
+			 * best-guess fuzzy result for broken mptables.
+			 */
+			if (best_guess < 0)
+				best_guess = irq;
+		}
+	}
+	return best_guess;
+}
+
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+/*
+ * EISA Edge/Level control register, ELCR
+ */
+static int EISA_ELCR(unsigned int irq)
+{
+	if (irq < 16) {
+		unsigned int port = 0x4d0 + (irq >> 3);
+		return (inb(port) >> (irq & 7)) & 1;
+	}
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"Broken MPtable reports ISA irq %d\n", irq);
+	return 0;
+}
+
+#endif
+
+/* ISA interrupts are always polarity zero edge triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_ISA_trigger(idx)	(0)
+#define default_ISA_polarity(idx)	(0)
+
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
+
+/* PCI interrupts are always polarity one level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_PCI_trigger(idx)	(1)
+#define default_PCI_polarity(idx)	(1)
+
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
+
+
+static int MPBIOS_polarity(int idx)
+{
+	int bus = mp_irqs[idx].mp_srcbus;
+	int polarity;
+
+	/*
+	 * Determine IRQ line polarity (high active or low active):
+	 */
+	switch (mp_irqs[idx].mp_irqflag & 3)
+	{
+		case 0: /* conforms, ie. bus-type dependent polarity */
+			if (test_bit(bus, mp_bus_not_pci))
+				polarity = default_ISA_polarity(idx);
+			else
+				polarity = default_PCI_polarity(idx);
+			break;
+		case 1: /* high active */
+		{
+			polarity = 0;
+			break;
+		}
+		case 2: /* reserved */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
+		case 3: /* low active */
+		{
+			polarity = 1;
+			break;
+		}
+		default: /* invalid */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
+	}
+	return polarity;
+}
+
+static int MPBIOS_trigger(int idx)
+{
+	int bus = mp_irqs[idx].mp_srcbus;
+	int trigger;
+
+	/*
+	 * Determine IRQ trigger mode (edge or level sensitive):
+	 */
+	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
+	{
+		case 0: /* conforms, ie. bus-type dependent */
+			if (test_bit(bus, mp_bus_not_pci))
+				trigger = default_ISA_trigger(idx);
+			else
+				trigger = default_PCI_trigger(idx);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+			switch (mp_bus_id_to_type[bus]) {
+				case MP_BUS_ISA: /* ISA pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_EISA: /* EISA pin */
+				{
+					trigger = default_EISA_trigger(idx);
+					break;
+				}
+				case MP_BUS_PCI: /* PCI pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_MCA: /* MCA pin */
+				{
+					trigger = default_MCA_trigger(idx);
+					break;
+				}
+				default:
+				{
+					printk(KERN_WARNING "broken BIOS!!\n");
+					trigger = 1;
+					break;
+				}
+			}
+#endif
+			break;
+		case 1: /* edge */
+		{
+			trigger = 0;
+			break;
+		}
+		case 2: /* reserved */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			trigger = 1;
+			break;
+		}
+		case 3: /* level */
+		{
+			trigger = 1;
+			break;
+		}
+		default: /* invalid */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			trigger = 0;
+			break;
+		}
+	}
+	return trigger;
+}
+
+static inline int irq_polarity(int idx)
+{
+	return MPBIOS_polarity(idx);
+}
+
+static inline int irq_trigger(int idx)
+{
+	return MPBIOS_trigger(idx);
+}
+
+int (*ioapic_renumber_irq)(int ioapic, int irq);
+static int pin_2_irq(int idx, int apic, int pin)
+{
+	int irq, i;
+	int bus = mp_irqs[idx].mp_srcbus;
+
+	/*
+	 * Debugging check, we are in big trouble if this message pops up!
+	 */
+	if (mp_irqs[idx].mp_dstirq != pin)
+		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+
+	if (test_bit(bus, mp_bus_not_pci)) {
+		irq = mp_irqs[idx].mp_srcbusirq;
+	} else {
+		/*
+		 * PCI IRQs are mapped in order
+		 */
+		i = irq = 0;
+		while (i < apic)
+			irq += nr_ioapic_registers[i++];
+		irq += pin;
+                /*
+                 * For MPS mode, so far only needed by ES7000 platform
+                 */
+                if (ioapic_renumber_irq)
+                        irq = ioapic_renumber_irq(apic, irq);
+	}
+
+#ifdef CONFIG_X86_32
+	/*
+	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
+	 */
+	if ((pin >= 16) && (pin <= 23)) {
+		if (pirq_entries[pin-16] != -1) {
+			if (!pirq_entries[pin-16]) {
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"disabling PIRQ%d\n", pin-16);
+			} else {
+				irq = pirq_entries[pin-16];
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"using PIRQ%d -> IRQ %d\n",
+						pin-16, irq);
+			}
+		}
+	}
+#endif
+
+	return irq;
+}
+
+void lock_vector_lock(void)
+{
+	/* Used to the online set of cpus does not change
+	 * during assign_irq_vector.
+	 */
+	spin_lock(&vector_lock);
+}
+
+void unlock_vector_lock(void)
+{
+	spin_unlock(&vector_lock);
+}
+
+static int __assign_irq_vector(int irq, cpumask_t mask)
+{
+	/*
+	 * NOTE! The local APIC isn't very good at handling
+	 * multiple interrupts at the same interrupt level.
+	 * As the interrupt level is determined by taking the
+	 * vector number and shifting that right by 4, we
+	 * want to spread these out a bit so that they don't
+	 * all fall in the same interrupt level.
+	 *
+	 * Also, we've got to be careful not to trash gate
+	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+	 */
+	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	unsigned int old_vector;
+	int cpu;
+	struct irq_cfg *cfg;
+
+	cfg = irq_cfg(irq);
+
+	/* Only try and allocate irqs on cpus that are present */
+	cpus_and(mask, mask, cpu_online_map);
+
+	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+		return -EBUSY;
+
+	old_vector = cfg->vector;
+	if (old_vector) {
+		cpumask_t tmp;
+		cpus_and(tmp, cfg->domain, mask);
+		if (!cpus_empty(tmp))
+			return 0;
+	}
+
+	for_each_cpu_mask_nr(cpu, mask) {
+		cpumask_t domain, new_mask;
+		int new_cpu;
+		int vector, offset;
+
+		domain = vector_allocation_domain(cpu);
+		cpus_and(new_mask, domain, cpu_online_map);
+
+		vector = current_vector;
+		offset = current_offset;
+next:
+		vector += 8;
+		if (vector >= first_system_vector) {
+			/* If we run out of vectors on large boxen, must share them. */
+			offset = (offset + 1) % 8;
+			vector = FIRST_DEVICE_VECTOR + offset;
+		}
+		if (unlikely(current_vector == vector))
+			continue;
+#ifdef CONFIG_X86_64
+		if (vector == IA32_SYSCALL_VECTOR)
+			goto next;
+#else
+		if (vector == SYSCALL_VECTOR)
+			goto next;
+#endif
+		for_each_cpu_mask_nr(new_cpu, new_mask)
+			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
+				goto next;
+		/* Found one! */
+		current_vector = vector;
+		current_offset = offset;
+		if (old_vector) {
+			cfg->move_in_progress = 1;
+			cfg->old_domain = cfg->domain;
+		}
+		for_each_cpu_mask_nr(new_cpu, new_mask)
+			per_cpu(vector_irq, new_cpu)[vector] = irq;
+		cfg->vector = vector;
+		cfg->domain = domain;
+		return 0;
+	}
+	return -ENOSPC;
+}
+
+static int assign_irq_vector(int irq, cpumask_t mask)
+{
+	int err;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	err = __assign_irq_vector(irq, mask);
+	spin_unlock_irqrestore(&vector_lock, flags);
+	return err;
+}
+
+static void __clear_irq_vector(int irq)
+{
+	struct irq_cfg *cfg;
+	cpumask_t mask;
+	int cpu, vector;
+
+	cfg = irq_cfg(irq);
+	BUG_ON(!cfg->vector);
+
+	vector = cfg->vector;
+	cpus_and(mask, cfg->domain, cpu_online_map);
+	for_each_cpu_mask_nr(cpu, mask)
+		per_cpu(vector_irq, cpu)[vector] = -1;
+
+	cfg->vector = 0;
+	cpus_clear(cfg->domain);
+}
+
+void __setup_vector_irq(int cpu)
+{
+	/* Initialize vector_irq on a new cpu */
+	/* This function must be called with vector_lock held */
+	int irq, vector;
+	struct irq_cfg *cfg;
+
+	/* Mark the inuse vectors */
+	for_each_irq_cfg(cfg) {
+		if (!cpu_isset(cpu, cfg->domain))
+			continue;
+		vector = cfg->vector;
+		irq = cfg->irq;
+		per_cpu(vector_irq, cpu)[vector] = irq;
+	}
+	/* Mark the free vectors */
+	for (vector = 0; vector < NR_VECTORS; ++vector) {
+		irq = per_cpu(vector_irq, cpu)[vector];
+		if (irq < 0)
+			continue;
+
+		cfg = irq_cfg(irq);
+		if (!cpu_isset(cpu, cfg->domain))
+			per_cpu(vector_irq, cpu)[vector] = -1;
+	}
+}
+
+static struct irq_chip ioapic_chip;
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip;
+#endif
+
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
+
+#ifdef CONFIG_X86_32
+static inline int IO_APIC_irq_trigger(int irq)
+{
+        int apic, idx, pin;
+
+        for (apic = 0; apic < nr_ioapics; apic++) {
+                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                        idx = find_irq_entry(apic, pin, mp_INT);
+                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+                                return irq_trigger(idx);
+                }
+        }
+        /*
+         * nonexistent IRQs are edge default
+         */
+        return 0;
+}
+#else
+static inline int IO_APIC_irq_trigger(int irq)
+{
+	return 1;
+}
+#endif
+
+static void ioapic_register_intr(int irq, unsigned long trigger)
+{
+	struct irq_desc *desc;
+
+	/* first time to use this irq_desc */
+	if (irq < 16)
+		desc = irq_desc(irq);
+	else
+		desc = irq_desc_with_new(irq);
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
+		desc->status |= IRQ_LEVEL;
+	else
+		desc->status &= ~IRQ_LEVEL;
+
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		desc->status |= IRQ_MOVE_PCNTXT;
+		if (trigger)
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_fasteoi_irq,
+						     "fasteoi");
+		else
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_edge_irq, "edge");
+		return;
+	}
+#endif
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_fasteoi_irq,
+					      "fasteoi");
+	else
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_edge_irq, "edge");
+}
+
+static int setup_ioapic_entry(int apic, int irq,
+			      struct IO_APIC_route_entry *entry,
+			      unsigned int destination, int trigger,
+			      int polarity, int vector)
+{
+	/*
+	 * add it to the IO-APIC irq-routing table:
+	 */
+	memset(entry,0,sizeof(*entry));
+
+#ifdef CONFIG_INTR_REMAP
+	if (intr_remapping_enabled) {
+		struct intel_iommu *iommu = map_ioapic_to_ir(apic);
+		struct irte irte;
+		struct IR_IO_APIC_route_entry *ir_entry =
+			(struct IR_IO_APIC_route_entry *) entry;
+		int index;
+
+		if (!iommu)
+			panic("No mapping iommu for ioapic %d\n", apic);
+
+		index = alloc_irte(iommu, irq, 1);
+		if (index < 0)
+			panic("Failed to allocate IRTE for ioapic %d\n", apic);
+
+		memset(&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = INT_DEST_MODE;
+		irte.trigger_mode = trigger;
+		irte.dlvry_mode = INT_DELIVERY_MODE;
+		irte.vector = vector;
+		irte.dest_id = IRTE_DEST(destination);
+
+		modify_irte(irq, &irte);
+
+		ir_entry->index2 = (index >> 15) & 0x1;
+		ir_entry->zero = 0;
+		ir_entry->format = 1;
+		ir_entry->index = (index & 0x7fff);
+	} else
+#endif
+	{
+		entry->delivery_mode = INT_DELIVERY_MODE;
+		entry->dest_mode = INT_DEST_MODE;
+		entry->dest = destination;
+	}
+
+	entry->mask = 0;				/* enable IRQ */
+	entry->trigger = trigger;
+	entry->polarity = polarity;
+	entry->vector = vector;
+
+	/* Mask level triggered irqs.
+	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+	 */
+	if (trigger)
+		entry->mask = 1;
+	return 0;
+}
+
+static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
+			      int trigger, int polarity)
+{
+	struct irq_cfg *cfg;
+	struct IO_APIC_route_entry entry;
+	cpumask_t mask;
+
+	if (!IO_APIC_IRQ(irq))
+		return;
+
+	cfg = irq_cfg(irq);
+
+	mask = TARGET_CPUS;
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cpus_and(mask, cfg->domain, mask);
+
+	apic_printk(APIC_VERBOSE,KERN_DEBUG
+		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+		    "IRQ %d Mode:%i Active:%i)\n",
+		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
+		    irq, trigger, polarity);
+
+
+	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
+			       cpu_mask_to_apicid(mask), trigger, polarity,
+			       cfg->vector)) {
+		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+		       mp_ioapics[apic].mp_apicid, pin);
+		__clear_irq_vector(irq);
+		return;
+	}
+
+	ioapic_register_intr(irq, trigger);
+	if (irq < 16)
+		disable_8259A_irq(irq);
+
+	ioapic_write_entry(apic, pin, entry);
+}
+
+static void __init setup_IO_APIC_irqs(void)
+{
+	int apic, pin, idx, irq, first_notcon = 1;
+
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+
+		idx = find_irq_entry(apic,pin,mp_INT);
+		if (idx == -1) {
+			if (first_notcon) {
+				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
+				first_notcon = 0;
+			} else
+				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
+			continue;
+		}
+		if (!first_notcon) {
+			apic_printk(APIC_VERBOSE, " not connected.\n");
+			first_notcon = 1;
+		}
+
+		irq = pin_2_irq(idx, apic, pin);
+#ifdef CONFIG_X86_32
+                if (multi_timer_check(apic, irq))
+                        continue;
+#endif
+		add_pin_to_irq(irq, apic, pin);
+
+		setup_IO_APIC_irq(apic, pin, irq,
+				  irq_trigger(idx), irq_polarity(idx));
+	}
+	}
+
+	if (!first_notcon)
+		apic_printk(APIC_VERBOSE, " not connected.\n");
+}
+
+/*
+ * Set up the timer pin, possibly with the 8259A-master behind.
+ */
+static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
+					int vector)
+{
+	struct IO_APIC_route_entry entry;
+
+#ifdef CONFIG_INTR_REMAP
+	if (intr_remapping_enabled)
+		return;
+#endif
+
+	memset(&entry, 0, sizeof(entry));
+
+	/*
+	 * We use logical delivery to get the timer IRQ
+	 * to the first CPU.
+	 */
+	entry.dest_mode = INT_DEST_MODE;
+	entry.mask = 1;					/* mask IRQ now */
+	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
+	entry.delivery_mode = INT_DELIVERY_MODE;
+	entry.polarity = 0;
+	entry.trigger = 0;
+	entry.vector = vector;
+
+	/*
+	 * The timer IRQ doesn't have to know that behind the
+	 * scene we may have a 8259A-master in AEOI mode ...
+	 */
+	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+
+	/*
+	 * Add it to the IO-APIC irq-routing table:
+	 */
+	ioapic_write_entry(apic, pin, entry);
+}
+
+
+__apicdebuginit(void) print_IO_APIC(void)
+{
+	int apic, i;
+	union IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_02 reg_02;
+	union IO_APIC_reg_03 reg_03;
+	unsigned long flags;
+	struct irq_cfg *cfg;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	for (i = 0; i < nr_ioapics; i++)
+		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
+
+	/*
+	 * We are a bit conservative about what we expect.  We have to
+	 * know about every hardware change ASAP.
+	 */
+	printk(KERN_INFO "testing the IO APIC.......................\n");
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(apic, 0);
+	reg_01.raw = io_apic_read(apic, 1);
+	if (reg_01.bits.version >= 0x10)
+		reg_02.raw = io_apic_read(apic, 2);
+        if (reg_01.bits.version >= 0x20)
+                reg_03.raw = io_apic_read(apic, 3);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	printk("\n");
+	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
+	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
+
+	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
+	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+
+	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+	 * but the value of reg_02 is read as the previous read register
+	 * value, so ignore it if reg_02 == reg_01.
+	 */
+	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+	}
+
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
+	 * or reg_03, but the value of reg_0[23] is read as the previous read
+	 * register value, so ignore it if reg_03 == reg_0[12].
+	 */
+	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+	    reg_03.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+	}
+
+	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+
+	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+			  " Stat Dmod Deli Vect:   \n");
+
+	for (i = 0; i <= reg_01.bits.entries; i++) {
+		struct IO_APIC_route_entry entry;
+
+		entry = ioapic_read_entry(apic, i);
+
+		printk(KERN_DEBUG " %02x %03X ",
+			i,
+			entry.dest
+		);
+
+		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
+			entry.mask,
+			entry.trigger,
+			entry.irr,
+			entry.polarity,
+			entry.delivery_status,
+			entry.dest_mode,
+			entry.delivery_mode,
+			entry.vector
+		);
+	}
+	}
+	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+	for_each_irq_cfg(cfg) {
+		struct irq_pin_list *entry = cfg->irq_2_pin;
+		if (!entry)
+			continue;
+		printk(KERN_DEBUG "IRQ%d ", cfg->irq);
+		for (;;) {
+			printk("-> %d:%d", entry->apic, entry->pin);
+			if (!entry->next)
+				break;
+			entry = entry->next;
+		}
+		printk("\n");
+	}
+
+	printk(KERN_INFO ".................................... done.\n");
+
+	return;
+}
+
+__apicdebuginit(void) print_APIC_bitfield(int base)
+{
+	unsigned int v;
+	int i, j;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
+	for (i = 0; i < 8; i++) {
+		v = apic_read(base + i*0x10);
+		for (j = 0; j < 32; j++) {
+			if (v & (1<<j))
+				printk("1");
+			else
+				printk("0");
+		}
+		printk("\n");
+	}
+}
+
+__apicdebuginit(void) print_local_APIC(void *dummy)
+{
+	unsigned int v, ver, maxlvt;
+	u64 icr;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+		smp_processor_id(), hard_smp_processor_id());
+	v = apic_read(APIC_ID);
+	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
+	v = apic_read(APIC_LVR);
+	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+	ver = GET_APIC_VERSION(v);
+	maxlvt = lapic_get_maxlvt();
+
+	v = apic_read(APIC_TASKPRI);
+	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+
+	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
+		v = apic_read(APIC_ARBPRI);
+		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+			v & APIC_ARBPRI_MASK);
+		v = apic_read(APIC_PROCPRI);
+		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+	}
+
+	v = apic_read(APIC_EOI);
+	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
+	v = apic_read(APIC_RRR);
+	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+	v = apic_read(APIC_LDR);
+	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
+	v = apic_read(APIC_DFR);
+	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+	v = apic_read(APIC_SPIV);
+	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
+
+	printk(KERN_DEBUG "... APIC ISR field:\n");
+	print_APIC_bitfield(APIC_ISR);
+	printk(KERN_DEBUG "... APIC TMR field:\n");
+	print_APIC_bitfield(APIC_TMR);
+	printk(KERN_DEBUG "... APIC IRR field:\n");
+	print_APIC_bitfield(APIC_IRR);
+
+	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
+		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
+			apic_write(APIC_ESR, 0);
+
+		v = apic_read(APIC_ESR);
+		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+	}
+
+	icr = apic_icr_read();
+	printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
+	printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
+
+	v = apic_read(APIC_LVTT);
+	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
+
+	if (maxlvt > 3) {                       /* PC is LVT#4. */
+		v = apic_read(APIC_LVTPC);
+		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
+	}
+	v = apic_read(APIC_LVT0);
+	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
+	v = apic_read(APIC_LVT1);
+	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
+
+	if (maxlvt > 2) {			/* ERR is LVT#3. */
+		v = apic_read(APIC_LVTERR);
+		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
+	}
+
+	v = apic_read(APIC_TMICT);
+	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
+	v = apic_read(APIC_TMCCT);
+	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
+	v = apic_read(APIC_TDCR);
+	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+	printk("\n");
+}
+
+__apicdebuginit(void) print_all_local_APICs(void)
+{
+	on_each_cpu(print_local_APIC, NULL, 1);
+}
+
+__apicdebuginit(void) print_PIC(void)
+{
+	unsigned int v;
+	unsigned long flags;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "\nprinting PIC contents\n");
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+
+	v = inb(0xa1) << 8 | inb(0x21);
+	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
+
+	v = inb(0xa0) << 8 | inb(0x20);
+	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
+
+	outb(0x0b,0xa0);
+	outb(0x0b,0x20);
+	v = inb(0xa0) << 8 | inb(0x20);
+	outb(0x0a,0xa0);
+	outb(0x0a,0x20);
+
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+
+	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
+
+	v = inb(0x4d1) << 8 | inb(0x4d0);
+	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+}
+
+__apicdebuginit(int) print_all_ICs(void)
+{
+	print_PIC();
+	print_all_local_APICs();
+	print_IO_APIC();
+
+	return 0;
+}
+
+fs_initcall(print_all_ICs);
+
+
+/* Where if anywhere is the i8259 connect in external int mode */
+static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+
+void __init enable_IO_APIC(void)
+{
+	union IO_APIC_reg_01 reg_01;
+	int i8259_apic, i8259_pin;
+	int apic;
+	unsigned long flags;
+
+#ifdef CONFIG_X86_32
+	int i;
+	if (!pirqs_enabled)
+		for (i = 0; i < MAX_PIRQS; i++)
+			pirq_entries[i] = -1;
+#endif
+
+	/*
+	 * The number of IO-APIC IRQ registers (== #pins):
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_01.raw = io_apic_read(apic, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+	}
+	for(apic = 0; apic < nr_ioapics; apic++) {
+		int pin;
+		/* See if any of the pins is in ExtINT mode */
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+			entry = ioapic_read_entry(apic, pin);
+
+			/* If the interrupt line is enabled and in ExtInt mode
+			 * I have found the pin where the i8259 is connected.
+			 */
+			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+				ioapic_i8259.apic = apic;
+				ioapic_i8259.pin  = pin;
+				goto found_i8259;
+			}
+		}
+	}
+ found_i8259:
+	/* Look to see what if the MP table has reported the ExtINT */
+	/* If we could not find the appropriate pin by looking at the ioapic
+	 * the i8259 probably is not connected the ioapic but give the
+	 * mptable a chance anyway.
+	 */
+	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
+	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+	/* Trust the MP table if nothing is setup in the hardware */
+	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+		ioapic_i8259.pin  = i8259_pin;
+		ioapic_i8259.apic = i8259_apic;
+	}
+	/* Complain if the MP table and the hardware disagree */
+	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+	{
+		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
+	}
+
+	/*
+	 * Do not trust the IO-APIC being empty at bootup
+	 */
+	clear_IO_APIC();
+}
+
+/*
+ * Not an __init, needed by the reboot code
+ */
+void disable_IO_APIC(void)
+{
+	/*
+	 * Clear the IO-APIC before rebooting:
+	 */
+	clear_IO_APIC();
+
+	/*
+	 * If the i8259 is routed through an IOAPIC
+	 * Put that IOAPIC in virtual wire mode
+	 * so legacy interrupts can be delivered.
+	 */
+	if (ioapic_i8259.pin != -1) {
+		struct IO_APIC_route_entry entry;
+
+		memset(&entry, 0, sizeof(entry));
+		entry.mask            = 0; /* Enabled */
+		entry.trigger         = 0; /* Edge */
+		entry.irr             = 0;
+		entry.polarity        = 0; /* High */
+		entry.delivery_status = 0;
+		entry.dest_mode       = 0; /* Physical */
+		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+		entry.vector          = 0;
+		entry.dest            = read_apic_id();
+
+		/*
+		 * Add it to the IO-APIC irq-routing table:
+		 */
+		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+	}
+
+	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+}
+
+#ifdef CONFIG_X86_32
+/*
+ * function to set the IO-APIC physical IDs based on the
+ * values stored in the MPC table.
+ *
+ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+ */
+
+static void __init setup_ioapic_ids_from_mpc(void)
+{
+	union IO_APIC_reg_00 reg_00;
+	physid_mask_t phys_id_present_map;
+	int apic;
+	int i;
+	unsigned char old_id;
+	unsigned long flags;
+
+	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
+		return;
+
+	/*
+	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+	 * no meaning without the serial APIC bus.
+	 */
+	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return;
+	/*
+	 * This is broken; anything with a real cpu count has to
+	 * circumvent this idiocy regardless.
+	 */
+	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
+
+	/*
+	 * Set the IOAPIC ID to the value stored in the MPC table.
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+
+		/* Read the register 0 value */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		old_id = mp_ioapics[apic].mp_apicid;
+
+		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+				apic, mp_ioapics[apic].mp_apicid);
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				reg_00.bits.ID);
+			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
+		}
+
+		/*
+		 * Sanity check, is the ID really free? Every APIC in a
+		 * system must have a unique ID or we get lots of nice
+		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+		 */
+		if (check_apicid_used(phys_id_present_map,
+					mp_ioapics[apic].mp_apicid)) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+				apic, mp_ioapics[apic].mp_apicid);
+			for (i = 0; i < get_physical_broadcast(); i++)
+				if (!physid_isset(i, phys_id_present_map))
+					break;
+			if (i >= get_physical_broadcast())
+				panic("Max APIC ID exceeded!\n");
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				i);
+			physid_set(i, phys_id_present_map);
+			mp_ioapics[apic].mp_apicid = i;
+		} else {
+			physid_mask_t tmp;
+			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
+			apic_printk(APIC_VERBOSE, "Setting %d in the "
+					"phys_id_present_map\n",
+					mp_ioapics[apic].mp_apicid);
+			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+		}
+
+
+		/*
+		 * We need to adjust the IRQ routing table
+		 * if the ID changed.
+		 */
+		if (old_id != mp_ioapics[apic].mp_apicid)
+			for (i = 0; i < mp_irq_entries; i++)
+				if (mp_irqs[i].mp_dstapic == old_id)
+					mp_irqs[i].mp_dstapic
+						= mp_ioapics[apic].mp_apicid;
+
+		/*
+		 * Read the right value from the MPC table and
+		 * write it into the ID register.
+		 */
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"...changing IO-APIC physical APIC ID to %d ...",
+			mp_ioapics[apic].mp_apicid);
+
+		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
+		spin_lock_irqsave(&ioapic_lock, flags);
+
+		/*
+		 * Sanity check
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
+			printk("could not set ID!\n");
+		else
+			apic_printk(APIC_VERBOSE, " ok.\n");
+	}
+}
+#endif
+
+int no_timer_check __initdata;
+
+static int __init notimercheck(char *s)
+{
+	no_timer_check = 1;
+	return 1;
+}
+__setup("no_timer_check", notimercheck);
+
+/*
+ * There is a nasty bug in some older SMP boards, their mptable lies
+ * about the timer IRQ. We do the following to work around the situation:
+ *
+ *	- timer IRQ defaults to IO-APIC IRQ
+ *	- if this function detects that timer IRQs are defunct, then we fall
+ *	  back to ISA timer IRQs
+ */
+static int __init timer_irq_works(void)
+{
+	unsigned long t1 = jiffies;
+	unsigned long flags;
+
+	if (no_timer_check)
+		return 1;
+
+	local_save_flags(flags);
+	local_irq_enable();
+	/* Let ten ticks pass... */
+	mdelay((10 * 1000) / HZ);
+	local_irq_restore(flags);
+
+	/*
+	 * Expect a few ticks at least, to be sure some possible
+	 * glue logic does not lock up after one or two first
+	 * ticks in a non-ExtINT mode.  Also the local APIC
+	 * might have cached one ExtINT interrupt.  Finally, at
+	 * least one tick may be lost due to delays.
+	 */
+
+	/* jiffies wrap? */
+	if (time_after(jiffies, t1 + 4))
+		return 1;
+	return 0;
+}
+
+/*
+ * In the SMP+IOAPIC case it might happen that there are an unspecified
+ * number of pending IRQ events unhandled. These cases are very rare,
+ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
+ * better to do it this way as thus we do not have to be aware of
+ * 'pending' interrupts in the IRQ path, except at this point.
+ */
+/*
+ * Edge triggered needs to resend any interrupt
+ * that was delayed but this is now handled in the device
+ * independent code.
+ */
+
+/*
+ * Starting up a edge-triggered IO-APIC interrupt is
+ * nasty - we need to make sure that we get the edge.
+ * If it is already asserted for some reason, we need
+ * return 1 to indicate that is was pending.
+ *
+ * This is not complete - we should be able to fake
+ * an edge even if it isn't on the 8259A...
+ */
+
+static unsigned int startup_ioapic_irq(unsigned int irq)
+{
+	int was_pending = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	if (irq < 16) {
+		disable_8259A_irq(irq);
+		if (i8259A_irq_pending(irq))
+			was_pending = 1;
+	}
+	__unmask_IO_APIC_irq(irq);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return was_pending;
+}
+
+#ifdef CONFIG_X86_64
+static int ioapic_retrigger_irq(unsigned int irq)
+{
+
+	struct irq_cfg *cfg = irq_cfg(irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	return 1;
+}
+#else
+static int ioapic_retrigger_irq(unsigned int irq)
+{
+        send_IPI_self(irq_cfg(irq)->vector);
+
+        return 1;
+}
+#endif
+
+/*
+ * Level and edge triggered IO-APIC interrupts need different handling,
+ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+ * handled with the level-triggered descriptor, but that one has slightly
+ * more overhead. Level-triggered interrupts cannot be handled with the
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
+ */
+
+#ifdef CONFIG_SMP
+
+#ifdef CONFIG_INTR_REMAP
+static void ir_irq_migration(struct work_struct *work);
+
+static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
+
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For edge triggered, irq migration is a simple atomic update(of vector
+ * and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we need to modify the io-apic RTE aswell with the update
+ * vector information, along with modifying IRTE with vector and destination.
+ * So irq migration for level triggered is little  bit more complex compared to
+ * edge triggered migration. But the good news is, we use the same algorithm
+ * for level triggered migration as we have today, only difference being,
+ * we now initiate the irq migration from process context instead of the
+ * interrupt context.
+ *
+ * In future, when we do a directed EOI (combined with cpu EOI broadcast
+ * suppression) to the IO-APIC, level triggered irq migration will also be
+ * as simple as edge triggered migration and we can do the irq migration
+ * with a simple atomic update to IO-APIC RTE.
+ */
+static void migrate_ioapic_irq(int irq, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+	cpumask_t tmp, cleanup_mask;
+	struct irte irte;
+	int modify_ioapic_rte;
+	unsigned int dest;
+	unsigned long flags;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (get_irte(irq, &irte))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	desc = irq_desc(irq);
+	modify_ioapic_rte = desc->status & IRQ_LEVEL;
+	if (modify_ioapic_rte) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		__target_IO_APIC_irq(irq, dest, cfg->vector);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * Modified the IRTE and flushes the Interrupt entry cache.
+	 */
+	modify_irte(irq, &irte);
+
+	if (cfg->move_in_progress) {
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+
+	desc->affinity = mask;
+}
+
+static int migrate_irq_remapped_level(int irq)
+{
+	int ret = -1;
+	struct irq_desc *desc = irq_desc(irq);
+
+	mask_IO_APIC_irq(irq);
+
+	if (io_apic_level_ack_pending(irq)) {
+		/*
+	 	 * Interrupt in progress. Migrating irq now will change the
+		 * vector information in the IO-APIC RTE and that will confuse
+		 * the EOI broadcast performed by cpu.
+		 * So, delay the irq migration to the next instance.
+		 */
+		schedule_delayed_work(&ir_migration_work, 1);
+		goto unmask;
+	}
+
+	/* everthing is clear. we have right of way */
+	migrate_ioapic_irq(irq, desc->pending_mask);
+
+	ret = 0;
+	desc->status &= ~IRQ_MOVE_PENDING;
+	cpus_clear(desc->pending_mask);
+
+unmask:
+	unmask_IO_APIC_irq(irq);
+	return ret;
+}
+
+static void ir_irq_migration(struct work_struct *work)
+{
+	unsigned int irq;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(irq, desc) {
+		if (desc->status & IRQ_MOVE_PENDING) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&desc->lock, flags);
+			if (!desc->chip->set_affinity ||
+			    !(desc->status & IRQ_MOVE_PENDING)) {
+				desc->status &= ~IRQ_MOVE_PENDING;
+				spin_unlock_irqrestore(&desc->lock, flags);
+				continue;
+			}
+
+			desc->chip->set_affinity(irq, desc, desc->pending_mask);
+			spin_unlock_irqrestore(&desc->lock, flags);
+		}
+	}
+}
+
+/*
+ * Migrates the IRQ destination in the process context.
+ */
+static void set_ir_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	if (desc->status & IRQ_LEVEL) {
+		desc->status |= IRQ_MOVE_PENDING;
+		desc->pending_mask = mask;
+		migrate_irq_remapped_level(irq);
+		return;
+	}
+
+	migrate_ioapic_irq(irq, mask);
+}
+#endif
+
+asmlinkage void smp_irq_move_cleanup_interrupt(void)
+{
+	unsigned vector, me;
+	ack_APIC_irq();
+#ifdef CONFIG_X86_64
+	exit_idle();
+#endif
+	irq_enter();
+
+	me = smp_processor_id();
+	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+		unsigned int irq;
+		struct irq_desc *desc;
+		struct irq_cfg *cfg;
+		irq = __get_cpu_var(vector_irq)[vector];
+
+		desc = irq_desc(irq);
+		if (!desc)
+			continue;
+
+		cfg = irq_cfg(irq);
+		spin_lock(&desc->lock);
+		if (!cfg->move_cleanup_count)
+			goto unlock;
+
+		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+			goto unlock;
+
+		__get_cpu_var(vector_irq)[vector] = -1;
+		cfg->move_cleanup_count--;
+unlock:
+		spin_unlock(&desc->lock);
+	}
+
+	irq_exit();
+}
+
+static void irq_complete_move(unsigned int irq)
+{
+	struct irq_cfg *cfg = irq_cfg(irq);
+	unsigned vector, me;
+
+	if (likely(!cfg->move_in_progress))
+		return;
+
+	vector = ~get_irq_regs()->orig_ax;
+	me = smp_processor_id();
+	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
+		cpumask_t cleanup_mask;
+
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+}
+#else
+static inline void irq_complete_move(unsigned int irq) {}
+#endif
+#ifdef CONFIG_INTR_REMAP
+static void ack_x2apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	ack_x2APIC_irq();
+}
+
+static void ack_x2apic_edge(unsigned int irq, struct irq_desc *desc)
+{
+	ack_x2APIC_irq();
+}
+#endif
+
+static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
+{
+	irq_complete_move(irq);
+	move_native_irq(irq, desc);
+	ack_APIC_irq();
+}
+
+#ifdef CONFIG_X86_64
+static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	int do_unmask_irq = 0;
+
+	irq_complete_move(irq);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	/* If we are moving the irq we need to mask it */
+	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+		do_unmask_irq = 1;
+		mask_IO_APIC_irq(irq);
+	}
+#endif
+
+	/*
+	 * We must acknowledge the irq before we move it or the acknowledge will
+	 * not propagate properly.
+	 */
+	ack_APIC_irq();
+
+	/* Now we can move and renable the irq */
+	if (unlikely(do_unmask_irq)) {
+		/* Only migrate the irq if the ack has been received.
+		 *
+		 * On rare occasions the broadcast level triggered ack gets
+		 * delayed going to ioapics, and if we reprogram the
+		 * vector while Remote IRR is still set the irq will never
+		 * fire again.
+		 *
+		 * To prevent this scenario we read the Remote IRR bit
+		 * of the ioapic.  This has two effects.
+		 * - On any sane system the read of the ioapic will
+		 *   flush writes (and acks) going to the ioapic from
+		 *   this cpu.
+		 * - We get to see if the ACK has actually been delivered.
+		 *
+		 * Based on failed experiments of reprogramming the
+		 * ioapic entry from outside of irq context starting
+		 * with masking the ioapic entry and then polling until
+		 * Remote IRR was clear before reprogramming the
+		 * ioapic I don't trust the Remote IRR bit to be
+		 * completey accurate.
+		 *
+		 * However there appears to be no other way to plug
+		 * this race, so if the Remote IRR bit is not
+		 * accurate and is causing problems then it is a hardware bug
+		 * and you can go talk to the chipset vendor about it.
+		 */
+		if (!io_apic_level_ack_pending(irq))
+			move_masked_irq(irq, desc);
+		unmask_IO_APIC_irq(irq);
+	}
+}
+#else
+atomic_t irq_mis_count;
+static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long v;
+	int i;
+
+	irq_complete_move(irq);
+	move_native_irq(irq, desc);
+	/*
+	* It appears there is an erratum which affects at least version 0x11
+	* of I/O APIC (that's the 82093AA and cores integrated into various
+	* chipsets).  Under certain conditions a level-triggered interrupt is
+	* erroneously delivered as edge-triggered one but the respective IRR
+	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
+	* message but it will never arrive and further interrupts are blocked
+	* from the source.  The exact reason is so far unknown, but the
+	* phenomenon was observed when two consecutive interrupt requests
+	* from a given source get delivered to the same CPU and the source is
+	* temporarily disabled in between.
+	*
+	* A workaround is to simulate an EOI message manually.  We achieve it
+	* by setting the trigger mode to edge and then to level when the edge
+	* trigger mode gets detected in the TMR of a local APIC for a
+	* level-triggered interrupt.  We mask the source for the time of the
+	* operation to prevent an edge-triggered interrupt escaping meanwhile.
+	* The idea is from Manfred Spraul.  --macro
+	*/
+	i = irq_cfg(irq)->vector;
+
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+	ack_APIC_irq();
+
+	if (!(v & (1 << (i & 0x1f)))) {
+		atomic_inc(&irq_mis_count);
+		spin_lock(&ioapic_lock);
+		__mask_and_edge_IO_APIC_irq(irq);
+		__unmask_and_level_IO_APIC_irq(irq);
+		spin_unlock(&ioapic_lock);
+	}
+}
+#endif
+
+static struct irq_chip ioapic_chip __read_mostly = {
+	.name 		= "IO-APIC",
+	.startup 	= startup_ioapic_irq,
+	.mask	 	= mask_IO_APIC_irq,
+	.unmask	 	= unmask_IO_APIC_irq,
+	.ack 		= ack_apic_edge,
+	.eoi 		= ack_apic_level,
+#ifdef CONFIG_SMP
+	.set_affinity 	= set_ioapic_affinity_irq,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip __read_mostly = {
+	.name 		= "IR-IO-APIC",
+	.startup 	= startup_ioapic_irq,
+	.mask	 	= mask_IO_APIC_irq,
+	.unmask	 	= unmask_IO_APIC_irq,
+	.ack 		= ack_x2apic_edge,
+	.eoi 		= ack_x2apic_level,
+#ifdef CONFIG_SMP
+	.set_affinity 	= set_ir_ioapic_affinity_irq,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+#endif
+
+static inline void init_IO_APIC_traps(void)
+{
+	int irq;
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+
+	/*
+	 * NOTE! The local APIC isn't very good at handling
+	 * multiple interrupts at the same interrupt level.
+	 * As the interrupt level is determined by taking the
+	 * vector number and shifting that right by 4, we
+	 * want to spread these out a bit so that they don't
+	 * all fall in the same interrupt level.
+	 *
+	 * Also, we've got to be careful not to trash gate
+	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+	 */
+	for_each_irq_cfg(cfg) {
+		irq = cfg->irq;
+		if (IO_APIC_IRQ(irq) && !cfg->vector) {
+			/*
+			 * Hmm.. We don't have an entry for this,
+			 * so default to an old-fashioned 8259
+			 * interrupt if we can..
+			 */
+			if (irq < 16)
+				make_8259A_irq(irq);
+			else {
+				desc = irq_desc(irq);
+				/* Strange. Oh, well.. */
+				desc->chip = &no_irq_chip;
+			}
+		}
+	}
+}
+
+/*
+ * The local APIC irq-chip implementation:
+ */
+
+static void mask_lapic_irq(unsigned int irq)
+{
+	unsigned long v;
+
+	v = apic_read(APIC_LVT0);
+	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+}
+
+static void unmask_lapic_irq(unsigned int irq)
+{
+	unsigned long v;
+
+	v = apic_read(APIC_LVT0);
+	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+}
+
+static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
+{
+	ack_APIC_irq();
+}
+
+static struct irq_chip lapic_chip __read_mostly = {
+	.name		= "local-APIC",
+	.mask		= mask_lapic_irq,
+	.unmask		= unmask_lapic_irq,
+	.ack		= ack_lapic_irq,
+};
+
+static void lapic_register_intr(int irq)
+{
+	struct irq_desc *desc;
+
+	desc = irq_desc(irq);
+	desc->status &= ~IRQ_LEVEL;
+	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+				      "edge");
+}
+
+static void __init setup_nmi(void)
+{
+	/*
+	 * Dirty trick to enable the NMI watchdog ...
+	 * We put the 8259A master into AEOI mode and
+	 * unmask on all local APICs LVT0 as NMI.
+	 *
+	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+	 * is from Maciej W. Rozycki - so we do not have to EOI from
+	 * the NMI handler or the timer interrupt.
+	 */
+	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+
+	enable_NMI_through_LVT0();
+
+	apic_printk(APIC_VERBOSE, " done.\n");
+}
+
+/*
+ * This looks a bit hackish but it's about the only one way of sending
+ * a few INTA cycles to 8259As and any associated glue logic.  ICR does
+ * not support the ExtINT mode, unfortunately.  We need to send these
+ * cycles as some i82489DX-based boards have glue logic that keeps the
+ * 8259A interrupt line asserted until INTA.  --macro
+ */
+static inline void __init unlock_ExtINT_logic(void)
+{
+	int apic, pin, i;
+	struct IO_APIC_route_entry entry0, entry1;
+	unsigned char save_control, save_freq_select;
+
+	pin  = find_isa_irq_pin(8, mp_INT);
+	if (pin == -1) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+	apic = find_isa_irq_apic(8, mp_INT);
+	if (apic == -1) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	entry0 = ioapic_read_entry(apic, pin);
+	clear_IO_APIC_pin(apic, pin);
+
+	memset(&entry1, 0, sizeof(entry1));
+
+	entry1.dest_mode = 0;			/* physical delivery */
+	entry1.mask = 0;			/* unmask IRQ now */
+	entry1.dest = hard_smp_processor_id();
+	entry1.delivery_mode = dest_ExtINT;
+	entry1.polarity = entry0.polarity;
+	entry1.trigger = 0;
+	entry1.vector = 0;
+
+	ioapic_write_entry(apic, pin, entry1);
+
+	save_control = CMOS_READ(RTC_CONTROL);
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
+		   RTC_FREQ_SELECT);
+	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
+
+	i = 100;
+	while (i-- > 0) {
+		mdelay(10);
+		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
+			i -= 10;
+	}
+
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	clear_IO_APIC_pin(apic, pin);
+
+	ioapic_write_entry(apic, pin, entry0);
+}
+
+static int disable_timer_pin_1 __initdata;
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+static int __init disable_timer_pin_setup(char *arg)
+{
+	disable_timer_pin_1 = 1;
+	return 0;
+}
+early_param("disable_timer_pin_1", disable_timer_pin_setup);
+
+int timer_through_8259 __initdata;
+
+/*
+ * This code may look a bit paranoid, but it's supposed to cooperate with
+ * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+ * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
+ * fanatically on his truly buggy board.
+ *
+ * FIXME: really need to revamp this for all platforms.
+ */
+static inline void __init check_timer(void)
+{
+	struct irq_cfg *cfg = irq_cfg(0);
+	int apic1, pin1, apic2, pin2;
+	unsigned long flags;
+	unsigned int ver;
+	int no_pin1 = 0;
+
+	local_irq_save(flags);
+
+        ver = apic_read(APIC_LVR);
+        ver = GET_APIC_VERSION(ver);
+
+	/*
+	 * get/set the timer IRQ vector:
+	 */
+	disable_8259A_irq(0);
+	assign_irq_vector(0, TARGET_CPUS);
+
+	/*
+	 * As IRQ0 is to be enabled in the 8259A, the virtual
+	 * wire has to be disabled in the local APIC.  Also
+	 * timer interrupts need to be acknowledged manually in
+	 * the 8259A for the i82489DX when using the NMI
+	 * watchdog as that APIC treats NMIs as level-triggered.
+	 * The AEOI mode will finish them in the 8259A
+	 * automatically.
+	 */
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+	init_8259A(1);
+#ifdef CONFIG_X86_32
+	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+#endif
+
+	pin1  = find_isa_irq_pin(0, mp_INT);
+	apic1 = find_isa_irq_apic(0, mp_INT);
+	pin2  = ioapic_i8259.pin;
+	apic2 = ioapic_i8259.apic;
+
+	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+		    cfg->vector, apic1, pin1, apic2, pin2);
+
+	/*
+	 * Some BIOS writers are clueless and report the ExtINTA
+	 * I/O APIC input from the cascaded 8259A as the timer
+	 * interrupt input.  So just in case, if only one pin
+	 * was found above, try it both directly and through the
+	 * 8259A.
+	 */
+	if (pin1 == -1) {
+#ifdef CONFIG_INTR_REMAP
+		if (intr_remapping_enabled)
+			panic("BIOS bug: timer not connected to IO-APIC");
+#endif
+		pin1 = pin2;
+		apic1 = apic2;
+		no_pin1 = 1;
+	} else if (pin2 == -1) {
+		pin2 = pin1;
+		apic2 = apic1;
+	}
+
+	if (pin1 != -1) {
+		/*
+		 * Ok, does IRQ0 through the IOAPIC work?
+		 */
+		if (no_pin1) {
+			add_pin_to_irq(0, apic1, pin1);
+			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+		}
+		unmask_IO_APIC_irq(0);
+		if (timer_irq_works()) {
+			if (nmi_watchdog == NMI_IO_APIC) {
+				setup_nmi();
+				enable_8259A_irq(0);
+			}
+			if (disable_timer_pin_1 > 0)
+				clear_IO_APIC_pin(0, pin1);
+			goto out;
+		}
+#ifdef CONFIG_INTR_REMAP
+		if (intr_remapping_enabled)
+			panic("timer doesn't work through Interrupt-remapped IO-APIC");
+#endif
+		clear_IO_APIC_pin(apic1, pin1);
+		if (!no_pin1)
+			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+				    "8254 timer not connected to IO-APIC\n");
+
+		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+			    "(IRQ0) through the 8259A ...\n");
+		apic_printk(APIC_QUIET, KERN_INFO
+			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+		/*
+		 * legacy devices should be connected to IO APIC #0
+		 */
+		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+		unmask_IO_APIC_irq(0);
+		enable_8259A_irq(0);
+		if (timer_irq_works()) {
+			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+			timer_through_8259 = 1;
+			if (nmi_watchdog == NMI_IO_APIC) {
+				disable_8259A_irq(0);
+				setup_nmi();
+				enable_8259A_irq(0);
+			}
+			goto out;
+		}
+		/*
+		 * Cleanup, just in case ...
+		 */
+		disable_8259A_irq(0);
+		clear_IO_APIC_pin(apic2, pin2);
+		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+	}
+
+	if (nmi_watchdog == NMI_IO_APIC) {
+		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+			    "through the IO-APIC - disabling NMI Watchdog!\n");
+		nmi_watchdog = NMI_NONE;
+	}
+#ifdef CONFIG_X86_32
+	timer_ack = 0;
+#endif
+
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as Virtual Wire IRQ...\n");
+
+	lapic_register_intr(0);
+	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+	enable_8259A_irq(0);
+
+	if (timer_irq_works()) {
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+		goto out;
+	}
+	disable_8259A_irq(0);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as ExtINT IRQ...\n");
+
+	init_8259A(0);
+	make_8259A_irq(0);
+	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+
+	unlock_ExtINT_logic();
+
+	if (timer_irq_works()) {
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+		goto out;
+	}
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+		"report.  Then try booting with the 'noapic' option.\n");
+out:
+	local_irq_restore(flags);
+}
+
+/*
+ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
+ * to devices.  However there may be an I/O APIC pin available for
+ * this interrupt regardless.  The pin may be left unconnected, but
+ * typically it will be reused as an ExtINT cascade interrupt for
+ * the master 8259A.  In the MPS case such a pin will normally be
+ * reported as an ExtINT interrupt in the MP table.  With ACPI
+ * there is no provision for ExtINT interrupts, and in the absence
+ * of an override it would be treated as an ordinary ISA I/O APIC
+ * interrupt, that is edge-triggered and unmasked by default.  We
+ * used to do this, but it caused problems on some systems because
+ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
+ * the same ExtINT cascade interrupt to drive the local APIC of the
+ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
+ * the I/O APIC in all cases now.  No actual device should request
+ * it anyway.  --macro
+ */
+#define PIC_IRQS	(1 << PIC_CASCADE_IR)
+
+void __init setup_IO_APIC(void)
+{
+
+#ifdef CONFIG_X86_32
+	enable_IO_APIC();
+#else
+	/*
+	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
+	 */
+#endif
+
+	io_apic_irqs = ~PIC_IRQS;
+
+	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+        /*
+         * Set up IO-APIC IRQ routing.
+         */
+#ifdef CONFIG_X86_32
+        if (!acpi_ioapic)
+                setup_ioapic_ids_from_mpc();
+#endif
+	sync_Arb_IDs();
+	setup_IO_APIC_irqs();
+	init_IO_APIC_traps();
+	check_timer();
+}
+
+/*
+ *      Called after all the initialization is done. If we didnt find any
+ *      APIC bugs then we can allow the modify fast path
+ */
+
+static int __init io_apic_bug_finalize(void)
+{
+        if (sis_apic_bug == -1)
+                sis_apic_bug = 0;
+        return 0;
+}
+
+late_initcall(io_apic_bug_finalize);
+
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+		*entry = ioapic_read_entry(dev->id, i);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+		ioapic_write_entry(dev->id, i, entry[i]);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	.name = "ioapic",
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i;
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
+/*
+ * Dynamic irq allocate and deallocation
+ */
+unsigned int create_irq(unsigned int irq_want)
+{
+	/* Allocate an unused irq */
+	unsigned int irq;
+	unsigned int new;
+	unsigned long flags;
+	struct irq_cfg *cfg_new;
+
+#ifndef CONFIG_HAVE_SPARSE_IRQ
+	irq_want = nr_irqs - 1;
+#endif
+
+	irq = 0;
+	spin_lock_irqsave(&vector_lock, flags);
+	for (new = irq_want; new > 0; new--) {
+		if (platform_legacy_irq(new))
+			continue;
+		cfg_new = irq_cfg(new);
+		if (cfg_new && cfg_new->vector != 0)
+			continue;
+		/* check if need to create one */
+		if (!cfg_new)
+			cfg_new = irq_cfg_with_new(new);
+		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
+			irq = new;
+		break;
+	}
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	if (irq > 0) {
+		dynamic_irq_init(irq);
+	}
+	return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	dynamic_irq_cleanup(irq);
+
+#ifdef CONFIG_INTR_REMAP
+	free_irte(irq);
+#endif
+	spin_lock_irqsave(&vector_lock, flags);
+	__clear_irq_vector(irq);
+	spin_unlock_irqrestore(&vector_lock, flags);
+}
+
+/*
+ * MSI message composition
+ */
+#ifdef CONFIG_PCI_MSI
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+{
+	struct irq_cfg *cfg;
+	int err;
+	unsigned dest;
+	cpumask_t tmp;
+
+	tmp = TARGET_CPUS;
+	err = assign_irq_vector(irq, tmp);
+	if (err)
+		return err;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, tmp);
+	dest = cpu_mask_to_apicid(tmp);
+
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		struct irte irte;
+		int ir_index;
+		u16 sub_handle;
+
+		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
+		BUG_ON(ir_index == -1);
+
+		memset (&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = INT_DEST_MODE;
+		irte.trigger_mode = 0; /* edge */
+		irte.dlvry_mode = INT_DELIVERY_MODE;
+		irte.vector = cfg->vector;
+		irte.dest_id = IRTE_DEST(dest);
+
+		modify_irte(irq, &irte);
+
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->data = sub_handle;
+		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+				  MSI_ADDR_IR_SHV |
+				  MSI_ADDR_IR_INDEX1(ir_index) |
+				  MSI_ADDR_IR_INDEX2(ir_index);
+	} else
+#endif
+	{
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->address_lo =
+			MSI_ADDR_BASE_LO |
+			((INT_DEST_MODE == 0) ?
+				MSI_ADDR_DEST_MODE_PHYSICAL:
+				MSI_ADDR_DEST_MODE_LOGICAL) |
+			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+				MSI_ADDR_REDIRECTION_CPU:
+				MSI_ADDR_REDIRECTION_LOWPRI) |
+			MSI_ADDR_DEST_ID(dest);
+
+		msg->data =
+			MSI_DATA_TRIGGER_EDGE |
+			MSI_DATA_LEVEL_ASSERT |
+			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+				MSI_DATA_DELIVERY_FIXED:
+				MSI_DATA_DELIVERY_LOWPRI) |
+			MSI_DATA_VECTOR(cfg->vector);
+	}
+	return err;
+}
+
+#ifdef CONFIG_SMP
+static void set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+	cpumask_t tmp;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	read_msi_msg(irq, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+	write_msi_msg(irq, &msg);
+	desc->affinity = mask;
+}
+
+#ifdef CONFIG_INTR_REMAP
+/*
+ * Migrate the MSI irq to another cpumask. This migration is
+ * done in the process context using interrupt-remapping hardware.
+ */
+static void ir_set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	unsigned int dest;
+	cpumask_t tmp, cleanup_mask;
+	struct irte irte;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (get_irte(irq, &irte))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * atomically update the IRTE with the new destination and vector.
+	 */
+	modify_irte(irq, &irte);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress) {
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+
+	desc->affinity = mask;
+}
+#endif
+#endif /* CONFIG_SMP */
+
+/*
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
+ */
+static struct irq_chip msi_chip = {
+	.name		= "PCI-MSI",
+	.unmask		= unmask_msi_irq,
+	.mask		= mask_msi_irq,
+	.ack		= ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_msi_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip msi_ir_chip = {
+	.name		= "IR-PCI-MSI",
+	.unmask		= unmask_msi_irq,
+	.mask		= mask_msi_irq,
+	.ack		= ack_x2apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= ir_set_msi_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+/*
+ * Map the PCI dev to the corresponding remapping hardware unit
+ * and allocate 'nvec' consecutive interrupt-remapping table entries
+ * in it.
+ */
+static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
+{
+	struct intel_iommu *iommu;
+	int index;
+
+	iommu = map_dev_to_ir(dev);
+	if (!iommu) {
+		printk(KERN_ERR
+		       "Unable to map PCI %s to iommu\n", pci_name(dev));
+		return -ENOENT;
+	}
+
+	index = alloc_irte(iommu, irq, nvec);
+	if (index < 0) {
+		printk(KERN_ERR
+		       "Unable to allocate %d IRTE for PCI %s\n", nvec,
+		        pci_name(dev));
+		return -ENOSPC;
+	}
+	return index;
+}
+#endif
+
+static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(dev, irq, &msg);
+	if (ret < 0)
+		return ret;
+
+	set_irq_msi(irq, desc);
+	write_msi_msg(irq, &msg);
+
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		struct irq_desc *desc = irq_desc(irq);
+		/*
+		 * irq migration in process context
+		 */
+		desc->status |= IRQ_MOVE_PCNTXT;
+		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
+	} else
+#endif
+		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+
+	return 0;
+}
+
+static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
+{
+	unsigned int irq;
+
+	irq = dev->bus->number;
+	irq <<= 8;
+	irq |= dev->devfn;
+	irq <<= 12;
+
+	return irq;
+}
+
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+{
+	unsigned int irq;
+	int ret;
+	unsigned int irq_want;
+
+	irq_want = build_irq_for_pci_dev(dev) + 0x100;
+
+	irq = create_irq(irq_want);
+	if (irq == 0)
+		return -1;
+
+#ifdef CONFIG_INTR_REMAP
+	if (!intr_remapping_enabled)
+		goto no_ir;
+
+	ret = msi_alloc_irte(dev, irq, 1);
+	if (ret < 0)
+		goto error;
+no_ir:
+#endif
+	ret = setup_msi_irq(dev, desc, irq);
+	if (ret < 0) {
+		destroy_irq(irq);
+		return ret;
+	}
+	return 0;
+
+#ifdef CONFIG_INTR_REMAP
+error:
+	destroy_irq(irq);
+	return ret;
+#endif
+}
+
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	unsigned int irq;
+	int ret, sub_handle;
+	struct msi_desc *desc;
+	unsigned int irq_want;
+
+#ifdef CONFIG_INTR_REMAP
+	struct intel_iommu *iommu = 0;
+	int index = 0;
+#endif
+
+	irq_want = build_irq_for_pci_dev(dev) + 0x100;
+	sub_handle = 0;
+	list_for_each_entry(desc, &dev->msi_list, list) {
+		irq = create_irq(irq_want--);
+		if (irq == 0)
+			return -1;
+#ifdef CONFIG_INTR_REMAP
+		if (!intr_remapping_enabled)
+			goto no_ir;
+
+		if (!sub_handle) {
+			/*
+			 * allocate the consecutive block of IRTE's
+			 * for 'nvec'
+			 */
+			index = msi_alloc_irte(dev, irq, nvec);
+			if (index < 0) {
+				ret = index;
+				goto error;
+			}
+		} else {
+			iommu = map_dev_to_ir(dev);
+			if (!iommu) {
+				ret = -ENOENT;
+				goto error;
+			}
+			/*
+			 * setup the mapping between the irq and the IRTE
+			 * base index, the sub_handle pointing to the
+			 * appropriate interrupt remap table entry.
+			 */
+			set_irte_irq(irq, iommu, index, sub_handle);
+		}
+no_ir:
+#endif
+		ret = setup_msi_irq(dev, desc, irq);
+		if (ret < 0)
+			goto error;
+		sub_handle++;
+	}
+	return 0;
+
+error:
+	destroy_irq(irq);
+	return ret;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	destroy_irq(irq);
+}
+
+#ifdef CONFIG_DMAR
+#ifdef CONFIG_SMP
+static void dmar_msi_set_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+	cpumask_t tmp;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	dmar_msi_read(irq, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+	dmar_msi_write(irq, &msg);
+	desc->affinity = mask;
+}
+#endif /* CONFIG_SMP */
+
+struct irq_chip dmar_msi_type = {
+	.name = "DMAR_MSI",
+	.unmask = dmar_msi_unmask,
+	.mask = dmar_msi_mask,
+	.ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity = dmar_msi_set_affinity,
+#endif
+	.retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_dmar_msi(unsigned int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(NULL, irq, &msg);
+	if (ret < 0)
+		return ret;
+	dmar_msi_write(irq, &msg);
+	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+		"edge");
+	return 0;
+}
+#endif
+
+#endif /* CONFIG_PCI_MSI */
+/*
+ * Hypertransport interrupt support
+ */
+#ifdef CONFIG_HT_IRQ
+
+#ifdef CONFIG_SMP
+
+static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
+{
+	struct ht_irq_msg msg;
+	fetch_ht_irq_msg(irq, &msg);
+
+	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
+	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+
+	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
+	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
+
+	write_ht_irq_msg(irq, &msg);
+}
+
+static void set_ht_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	unsigned int dest;
+	cpumask_t tmp;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	target_ht_irq(irq, dest, cfg->vector);
+	desc->affinity = mask;
+}
+#endif
+
+static struct irq_chip ht_irq_chip = {
+	.name		= "PCI-HT",
+	.mask		= mask_ht_irq,
+	.unmask		= unmask_ht_irq,
+	.ack		= ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_ht_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
+{
+	struct irq_cfg *cfg;
+	int err;
+	cpumask_t tmp;
+
+	tmp = TARGET_CPUS;
+	err = assign_irq_vector(irq, tmp);
+	if (!err) {
+		struct ht_irq_msg msg;
+		unsigned dest;
+
+		cfg = irq_cfg(irq);
+		cpus_and(tmp, cfg->domain, tmp);
+		dest = cpu_mask_to_apicid(tmp);
+
+		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+
+		msg.address_lo =
+			HT_IRQ_LOW_BASE |
+			HT_IRQ_LOW_DEST_ID(dest) |
+			HT_IRQ_LOW_VECTOR(cfg->vector) |
+			((INT_DEST_MODE == 0) ?
+				HT_IRQ_LOW_DM_PHYSICAL :
+				HT_IRQ_LOW_DM_LOGICAL) |
+			HT_IRQ_LOW_RQEOI_EDGE |
+			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+				HT_IRQ_LOW_MT_FIXED :
+				HT_IRQ_LOW_MT_ARBITRATED) |
+			HT_IRQ_LOW_IRQ_MASKED;
+
+		write_ht_irq_msg(irq, &msg);
+
+		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+					      handle_edge_irq, "edge");
+	}
+	return err;
+}
+#endif /* CONFIG_HT_IRQ */
+
+/* --------------------------------------------------------------------------
+                          ACPI-based IOAPIC Configuration
+   -------------------------------------------------------------------------- */
+
+#ifdef CONFIG_ACPI
+
+#ifdef CONFIG_X86_32
+int __init io_apic_get_unique_id(int ioapic, int apic_id)
+{
+	union IO_APIC_reg_00 reg_00;
+	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
+	physid_mask_t tmp;
+	unsigned long flags;
+	int i = 0;
+
+	/*
+	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
+	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
+	 * supports up to 16 on one shared APIC bus.
+	 *
+	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+	 *      advantage of new APIC bus architecture.
+	 */
+
+	if (physids_empty(apic_id_map))
+		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(ioapic, 0);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	if (apic_id >= get_physical_broadcast()) {
+		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+			"%d\n", ioapic, apic_id, reg_00.bits.ID);
+		apic_id = reg_00.bits.ID;
+	}
+
+	/*
+	 * Every APIC in a system must have a unique ID or we get lots of nice
+	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+	 */
+	if (check_apicid_used(apic_id_map, apic_id)) {
+
+		for (i = 0; i < get_physical_broadcast(); i++) {
+			if (!check_apicid_used(apic_id_map, i))
+				break;
+		}
+
+		if (i == get_physical_broadcast())
+			panic("Max apic_id exceeded!\n");
+
+		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+			"trying %d\n", ioapic, apic_id, i);
+
+		apic_id = i;
+	}
+
+	tmp = apicid_to_cpu_present(apic_id);
+	physids_or(apic_id_map, apic_id_map, tmp);
+
+	if (reg_00.bits.ID != apic_id) {
+		reg_00.bits.ID = apic_id;
+
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(ioapic, 0, reg_00.raw);
+		reg_00.raw = io_apic_read(ioapic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		/* Sanity check */
+		if (reg_00.bits.ID != apic_id) {
+			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+			return -1;
+		}
+	}
+
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+
+	return apic_id;
+}
+
+int __init io_apic_get_version(int ioapic)
+{
+	union IO_APIC_reg_01	reg_01;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_01.raw = io_apic_read(ioapic, 1);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return reg_01.bits.version;
+}
+#endif
+
+int __init io_apic_get_redir_entries (int ioapic)
+{
+	union IO_APIC_reg_01	reg_01;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_01.raw = io_apic_read(ioapic, 1);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return reg_01.bits.entries;
+}
+
+
+int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+{
+	if (!IO_APIC_IRQ(irq)) {
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+			ioapic);
+		return -EINVAL;
+	}
+
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= 16)
+		add_pin_to_irq(irq, ioapic, pin);
+
+	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
+
+	return 0;
+}
+
+
+int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+{
+	int i;
+
+	if (skip_ioapic_setup)
+		return -1;
+
+	for (i = 0; i < mp_irq_entries; i++)
+		if (mp_irqs[i].mp_irqtype == mp_INT &&
+		    mp_irqs[i].mp_srcbusirq == bus_irq)
+			break;
+	if (i >= mp_irq_entries)
+		return -1;
+
+	*trigger = irq_trigger(i);
+	*polarity = irq_polarity(i);
+	return 0;
+}
+
+#endif /* CONFIG_ACPI */
+
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+#ifdef CONFIG_SMP
+void __init setup_ioapic_dest(void)
+{
+	int pin, ioapic, irq, irq_entry;
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+
+	if (skip_ioapic_setup == 1)
+		return;
+
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+			if (irq_entry == -1)
+				continue;
+			irq = pin_2_irq(irq_entry, ioapic, pin);
+
+			/* setup_IO_APIC_irqs could fail to get vector for some device
+			 * when you have too many devices, because at that time only boot
+			 * cpu is online.
+			 */
+			cfg = irq_cfg(irq);
+			if (!cfg->vector)
+				setup_IO_APIC_irq(ioapic, pin, irq,
+						  irq_trigger(irq_entry),
+						  irq_polarity(irq_entry));
+#ifdef CONFIG_INTR_REMAP
+			else if (intr_remapping_enabled) {
+				desc = irq_desc(irq);
+				set_ir_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
+			}
+#endif
+			else {
+				desc = irq_desc(irq);
+				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
+			}
+		}
+	}
+}
+#endif
+
+#ifdef CONFIG_X86_64
+#define IOAPIC_RESOURCE_NAME_SIZE 11
+
+static struct resource *ioapic_resources;
+
+static struct resource * __init ioapic_setup_resources(void)
+{
+	unsigned long n;
+	struct resource *res;
+	char *mem;
+	int i;
+
+	if (nr_ioapics <= 0)
+		return NULL;
+
+	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+	n *= nr_ioapics;
+
+	mem = alloc_bootmem(n);
+	res = (void *)mem;
+
+	if (mem != NULL) {
+		mem += sizeof(struct resource) * nr_ioapics;
+
+		for (i = 0; i < nr_ioapics; i++) {
+			res[i].name = mem;
+			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			sprintf(mem,  "IOAPIC %u", i);
+			mem += IOAPIC_RESOURCE_NAME_SIZE;
+		}
+	}
+
+	ioapic_resources = res;
+
+	return res;
+}
+#endif
+
+void __init ioapic_init_mappings(void)
+{
+	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+	int i;
+#ifdef CONFIG_X86_64
+	struct resource *ioapic_res;
+
+	ioapic_res = ioapic_setup_resources();
+#endif
+	for (i = 0; i < nr_ioapics; i++) {
+		if (smp_found_config) {
+			ioapic_phys = mp_ioapics[i].mp_apicaddr;
+#ifdef CONFIG_X86_32
+                        if (!ioapic_phys) {
+                                printk(KERN_ERR
+                                       "WARNING: bogus zero IO-APIC "
+                                       "address found in MPTABLE, "
+                                       "disabling IO/APIC support!\n");
+                                smp_found_config = 0;
+                                skip_ioapic_setup = 1;
+                                goto fake_ioapic_page;
+                        }
+#endif
+		} else {
+#ifdef CONFIG_X86_32
+fake_ioapic_page:
+#endif
+			ioapic_phys = (unsigned long)
+				alloc_bootmem_pages(PAGE_SIZE);
+			ioapic_phys = __pa(ioapic_phys);
+		}
+		set_fixmap_nocache(idx, ioapic_phys);
+		apic_printk(APIC_VERBOSE,
+			    "mapped IOAPIC to %08lx (%08lx)\n",
+			    __fix_to_virt(idx), ioapic_phys);
+		idx++;
+
+#ifdef CONFIG_X86_64
+		if (ioapic_res != NULL) {
+			ioapic_res->start = ioapic_phys;
+			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+			ioapic_res++;
+		}
+#endif
+	}
+}
+
+#ifdef CONFIG_X86_64
+static int __init ioapic_insert_resources(void)
+{
+	int i;
+	struct resource *r = ioapic_resources;
+
+	if (!r) {
+		printk(KERN_ERR
+		       "IO APIC resources could be not be allocated.\n");
+		return -1;
+	}
+
+	for (i = 0; i < nr_ioapics; i++) {
+		insert_resource(&iomem_resource, r);
+		r++;
+	}
+
+	return 0;
+}
+
+/* Insert the IO APIC resources after PCI initialization has occured to handle
+ * IO APICS that are mapped in on a BAR in PCI space. */
+late_initcall(ioapic_insert_resources);
+#endif
Index: linux-2.6/arch/x86/kernel/io_apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_32.c
+++ /dev/null
@@ -1,3220 +0,0 @@
-/*
- *	Intel IO-APIC support for multi-Pentium hosts.
- *
- *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
- *
- *	Many thanks to Stig Venaas for trying out countless experimental
- *	patches and reporting/debugging problems patiently!
- *
- *	(c) 1999, Multiple IO-APIC support, developed by
- *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
- *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
- *	further tested and cleaned up by Zach Brown <zab@redhat.com>
- *	and Ingo Molnar <mingo@redhat.com>
- *
- *	Fixes
- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
- *					thanks to Eric Gilmore
- *					and Rolf G. Tews
- *					for testing these extensively
- *	Paul Diefenbaugh	:	Added full ACPI support
- */
-
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/mc146818rtc.h>
-#include <linux/compiler.h>
-#include <linux/acpi.h>
-#include <linux/module.h>
-#include <linux/sysdev.h>
-#include <linux/msi.h>
-#include <linux/htirq.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
-#include <linux/jiffies.h>      /* time_after() */
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#endif
-#include <linux/bootmem.h>
-#include <linux/dmar.h>
-
-#include <asm/idle.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/desc.h>
-#include <asm/proto.h>
-#include <asm/acpi.h>
-#include <asm/dma.h>
-#include <asm/timer.h>
-#include <asm/i8259.h>
-#include <asm/nmi.h>
-#include <asm/msidef.h>
-#include <asm/hypertransport.h>
-#include <asm/setup.h>
-#include <asm/irq_remapping.h>
-
-#include <mach_ipi.h>
-#include <mach_apic.h>
-#include <mach_apicdef.h>
-
-#define __apicdebuginit(type) static type __init
-
-/*
- *	Is the SiS APIC rmw bug present ?
- *	-1 = don't know, 0 = no, 1 = yes
- */
-int sis_apic_bug = -1;
-
-static DEFINE_SPINLOCK(ioapic_lock);
-static DEFINE_SPINLOCK(vector_lock);
-
-int first_free_entry;
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-int pin_map_size;
-
-/*
- * # of IRQ routing registers
- */
-int nr_ioapic_registers[MAX_IO_APICS];
-
-/* I/O APIC entries */
-struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
-int nr_ioapics;
-
-/* MP IRQ source entries */
-struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-
-/* # of MP IRQ source entries */
-int mp_irq_entries;
-
-#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
-int mp_bus_id_to_type[MAX_MP_BUSSES];
-#endif
-
-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
-
-int skip_ioapic_setup;
-
-static int __init parse_noapic(char *arg)
-{
-	/* disable IO-APIC */
-	disable_ioapic_setup();
-	return 0;
-}
-early_param("noapic", parse_noapic);
-
-struct irq_cfg;
-struct irq_pin_list;
-struct irq_cfg {
-	unsigned int irq;
-	struct irq_cfg *next;
-	struct irq_pin_list *irq_2_pin;
-	cpumask_t domain;
-	cpumask_t old_domain;
-	unsigned move_cleanup_count;
-	u8 vector;
-	u8 move_in_progress : 1;
-};
-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfg_legacy[] __initdata = {
-	[0]  = { .irq =  0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
-	[1]  = { .irq =  1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
-	[2]  = { .irq =  2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
-	[3]  = { .irq =  3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR,  },
-	[4]  = { .irq =  4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR,  },
-	[5]  = { .irq =  5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR,  },
-	[6]  = { .irq =  6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR,  },
-	[7]  = { .irq =  7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR,  },
-	[8]  = { .irq =  8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR,  },
-	[9]  = { .irq =  9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR,  },
-	[10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
-	[11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
-	[12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
-	[13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
-	[14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
-	[15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
-};
-
-static struct irq_cfg irq_cfg_init = { .irq =  -1U, };
-/* need to be biger than size of irq_cfg_legacy */
-static int nr_irq_cfg = 32;
-
-static int __init parse_nr_irq_cfg(char *arg)
-{
-	if (arg) {
-		nr_irq_cfg = simple_strtoul(arg, NULL, 0);
-		if (nr_irq_cfg < 32)
-			nr_irq_cfg = 32;
-	}
-	return 0;
-}
-
-early_param("nr_irq_cfg", parse_nr_irq_cfg);
-
-static void init_one_irq_cfg(struct irq_cfg *cfg)
-{
-	memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
-}
-
-static struct irq_cfg *irq_cfgx;
-static struct irq_cfg *irq_cfgx_free;
-static void __init init_work(void *data)
-{
-	struct dyn_array *da = data;
-	struct irq_cfg *cfg;
-	int legacy_count;
-	int i;
-
-	cfg = *da->name;
-
-	memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
-
-	legacy_count = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
-	for (i = legacy_count; i < *da->nr; i++)
-		init_one_irq_cfg(&cfg[i]);
-
-	for (i = 1; i < *da->nr; i++)
-		cfg[i-1].next = &cfg[i];
-
-	irq_cfgx_free = &irq_cfgx[legacy_count];
-	irq_cfgx[legacy_count - 1].next = NULL;
-}
-
-#define for_each_irq_cfg(cfg)           \
-	for (cfg = irq_cfgx; cfg; cfg = cfg->next)
-
-DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
-
-static struct irq_cfg *irq_cfg(unsigned int irq)
-{
-	struct irq_cfg *cfg;
-
-	cfg = irq_cfgx;
-	while (cfg) {
-		if (cfg->irq == irq)
-			return cfg;
-
-		cfg = cfg->next;
-	}
-
-	return NULL;
-}
-
-static struct irq_cfg *irq_cfg_with_new(unsigned int irq)
-{
-	struct irq_cfg *cfg, *cfg_pri;
-	int i;
-	int count = 0;
-
-	cfg_pri = cfg = irq_cfgx;
-	while (cfg) {
-		if (cfg->irq == irq)
-			return cfg;
-
-		cfg_pri = cfg;
-		cfg = cfg->next;
-		count++;
-	}
-
-	if (!irq_cfgx_free) {
-		unsigned long phys;
-		unsigned long total_bytes;
-		/*
-		 *  we run out of pre-allocate ones, allocate more
-		 */
-		printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
-
-		total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
-		if (after_bootmem)
-			cfg = kzalloc(total_bytes, GFP_ATOMIC);
-		else
-			cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
-
-		if (!cfg)
-			panic("please boot with nr_irq_cfg= %d\n", count * 2);
-
-		phys = __pa(cfg);
-		printk(KERN_DEBUG "irq_irq ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
-
-		for (i = 0; i < nr_irq_cfg; i++)
-			init_one_irq_cfg(&cfg[i]);
-
-		for (i = 1; i < nr_irq_cfg; i++)
-			cfg[i-1].next = &cfg[i];
-
-		irq_cfgx_free = cfg;
-	}
-
-	cfg = irq_cfgx_free;
-	irq_cfgx_free = irq_cfgx_free->next;
-	cfg->next = NULL;
-	if (cfg_pri)
-		cfg_pri->next = cfg;
-	else
-		irq_cfgx = cfg;
-	cfg->irq = irq;
-	printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
-
-#ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
-	{
-		/* dump the results */
-		struct irq_cfg *cfg;
-		unsigned long phys;
-		unsigned long bytes = sizeof(struct irq_cfg);
-
-		printk(KERN_DEBUG "=========================== %d\n", irq);
-		printk(KERN_DEBUG "irq_cfg dump after get that for %d\n", irq);
-		for_each_irq_cfg(cfg) {
-			phys = __pa(cfg);
-			printk(KERN_DEBUG "irq_cfg %d ==> [%#lx - %#lx]\n", cfg->irq, phys, phys + bytes);
-		}
-		printk(KERN_DEBUG "===========================\n");
-	}
-#endif
-	return cfg;
-}
-
-/*
- * This is performance-critical, we want to do it O(1)
- *
- * the indexing order of this array favors 1:1 mappings
- * between pins and IRQs.
- */
-
-struct irq_pin_list {
-	int apic, pin;
-	struct irq_pin_list *next;
-};
-
-static struct irq_pin_list *irq_2_pin_head;
-/* fill one page ? */
-static int nr_irq_2_pin = 0x100;
-static struct irq_pin_list *irq_2_pin_ptr;
-static void __init irq_2_pin_init_work(void *data)
-{
-	struct dyn_array *da = data;
-	struct irq_pin_list *pin;
-	int i;
-
-	pin = *da->name;
-
-	for (i = 1; i < *da->nr; i++)
-		pin[i-1].next = &pin[i];
-
-	irq_2_pin_ptr = &pin[0];
-}
-DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
-
-static struct irq_pin_list *get_one_free_irq_2_pin(void)
-{
-	struct irq_pin_list *pin;
-	int i;
-
-	pin = irq_2_pin_ptr;
-
-	if (pin) {
-		irq_2_pin_ptr = pin->next;
-		pin->next = NULL;
-		return pin;
-	}
-
-	/*
-	 *  we run out of pre-allocate ones, allocate more
-	 */
-	printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
-
-	if (after_bootmem)
-		pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
-				 GFP_ATOMIC);
-	else
-		pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
-				nr_irq_2_pin, PAGE_SIZE, 0);
-
-	if (!pin)
-		panic("can not get more irq_2_pin\n");
-
-	for (i = 1; i < nr_irq_2_pin; i++)
-		pin[i-1].next = &pin[i];
-
-	irq_2_pin_ptr = pin->next;
-	pin->next = NULL;
-
-	return pin;
-}
-
-struct io_apic {
-	unsigned int index;
-	unsigned int unused[3];
-	unsigned int data;
-};
-
-static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
-{
-	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
-		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
-}
-
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	writel(reg, &io_apic->index);
-	return readl(&io_apic->data);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	writel(reg, &io_apic->index);
-	writel(value, &io_apic->data);
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- *
- * Older SiS APIC requires we rewrite the index register
- */
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
-{
-	volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
-	if (sis_apic_bug)
-		writel(reg, &io_apic->index);
-	writel(value, &io_apic->data);
-}
-
-#ifdef CONFIG_X86_64
-static bool io_apic_level_ack_pending(unsigned int irq)
-{
-	struct irq_pin_list *entry;
-	unsigned long flags;
-	struct irq_cfg *cfg = irq_cfg(irq);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		unsigned int reg;
-		int pin;
-
-		if (!entry)
-			break;
-		pin = entry->pin;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		/* Is the remote IRR bit set? */
-		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
-			spin_unlock_irqrestore(&ioapic_lock, flags);
-			return true;
-		}
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return false;
-}
-#endif
-
-union entry_union {
-	struct { u32 w1, w2; };
-	struct IO_APIC_route_entry entry;
-};
-
-static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
-{
-	union entry_union eu;
-	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-	return eu.entry;
-}
-
-/*
- * When we write a new IO APIC routing entry, we need to write the high
- * word first! If the mask bit in the low word is clear, we will enable
- * the interrupt, and we need to make sure the entry is fully populated
- * before that happens.
- */
-static void
-__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
-{
-	union entry_union eu;
-	eu.entry = e;
-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
-}
-
-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__ioapic_write_entry(apic, pin, e);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-/*
- * When we mask an IO APIC routing entry, we need to write the low
- * word first, in order to set the mask bit before we change the
- * high bits!
- */
-static void ioapic_mask_entry(int apic, int pin)
-{
-	unsigned long flags;
-	union entry_union eu = { .entry.mask = 1 };
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#ifdef CONFIG_SMP
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
-{
-	int apic, pin;
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-
-	cfg = irq_cfg(irq);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		unsigned int reg;
-
-		if (!entry)
-			break;
-
-		apic = entry->apic;
-		pin = entry->pin;
-		io_apic_write(apic, 0x11 + pin*2, dest);
-		reg = io_apic_read(apic, 0x10 + pin*2);
-		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
-		reg |= vector;
-		io_apic_modify(apic, 0x10 + pin *2, reg);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-}
-
-static int assign_irq_vector(int irq, cpumask_t mask);
-
-static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	cfg = irq_cfg(irq);
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-	/*
-	 * Only the high 8 bits are valid.
-	 */
-	dest = SET_APIC_LOGICAL_ID(dest);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__target_IO_APIC_irq(irq, dest, cfg->vector);
-	desc->affinity = mask;
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#endif /* CONFIG_SMP */
-
-/*
- * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
- * shared ISA-space IRQs, so we have to support them. We are super
- * fast in the common case, and fast for shared ISA-space IRQs.
- */
-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
-{
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-
-	/* first time to refer irq_cfg, so with new */
-	cfg = irq_cfg_with_new(irq);
-	entry = cfg->irq_2_pin;
-	if (!entry) {
-		entry = get_one_free_irq_2_pin();
-		cfg->irq_2_pin = entry;
-		entry->apic = apic;
-		entry->pin = pin;
-		printk(KERN_DEBUG " 0 add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
-		return;
-	}
-
-	while (entry->next) {
-		/* not again, please */
-		if (entry->apic == apic && entry->pin == pin)
-			return;
-
-		entry = entry->next;
-	}
-
-	entry->next = get_one_free_irq_2_pin();
-	entry = entry->next;
-	entry->apic = apic;
-	entry->pin = pin;
-	printk(KERN_DEBUG " x add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
-}
-
-/*
- * Reroute an IRQ to a different pin.
- */
-static void __init replace_pin_at_irq(unsigned int irq,
-				      int oldapic, int oldpin,
-				      int newapic, int newpin)
-{
-	struct irq_cfg *cfg = irq_cfg(irq);
-	struct irq_pin_list *entry = cfg->irq_2_pin;
-	int replaced = 0;
-
-	while (entry) {
-		if (entry->apic == oldapic && entry->pin == oldpin) {
-			entry->apic = newapic;
-			entry->pin = newpin;
-			replaced = 1;
-			/* every one is different, right? */
-			break;
-		}
-		entry = entry->next;
-	}
-
-	/* why? call replace before add? */
-	if (!replaced)
-		add_pin_to_irq(irq, newapic, newpin);
-}
-
-#ifdef CONFIG_X86_64
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	readl(&io_apic->data);
-}
-
-#define __DO_ACTION(R, ACTION, FINAL)					\
-									\
-{									\
-	int pin;							\
-	struct irq_cfg *cfg;						\
-	struct irq_pin_list *entry;					\
-									\
-	cfg = irq_cfg(irq);						\
-	entry = cfg->irq_2_pin;						\
-	for (;;) {							\
-		unsigned int reg;					\
-		if (!entry)						\
-			break;						\
-		pin = entry->pin;					\
-		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
-		reg ACTION;						\
-		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
-		FINAL;							\
-		if (!entry->next)					\
-			break;						\
-		entry = entry->next;					\
-	}								\
-}
-
-#define DO_ACTION(name,R,ACTION, FINAL)					\
-									\
-	static void name##_IO_APIC_irq (unsigned int irq)		\
-	__DO_ACTION(R, ACTION, FINAL)
-
-/* mask = 1 */
-DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
-
-/* mask = 0 */
-DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
-
-#else
-
-static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
-{
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-	unsigned int pin, reg;
-
-	cfg = irq_cfg(irq);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		if (!entry)
-			break;
-		pin = entry->pin;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		reg &= ~disable;
-		reg |= enable;
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-}
-
-/* mask = 1 */
-static void __mask_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
-}
-
-/* mask = 0 */
-static void __unmask_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
-}
-
-/* mask = 1, trigger = 0 */
-static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
-				IO_APIC_REDIR_LEVEL_TRIGGER);
-}
-
-/* mask = 0, trigger = 1 */
-static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
-				IO_APIC_REDIR_MASKED);
-}
-
-#endif
-
-static void mask_IO_APIC_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__mask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void unmask_IO_APIC_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__unmask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
-{
-	struct IO_APIC_route_entry entry;
-
-	/* Check delivery_mode to be sure we're not clearing an SMI pin */
-	entry = ioapic_read_entry(apic, pin);
-	if (entry.delivery_mode == dest_SMI)
-		return;
-
-	/*
-	 * Disable it in the IO-APIC irq-routing table:
-	 */
-	ioapic_mask_entry(apic, pin);
-}
-
-static void clear_IO_APIC(void)
-{
-	int apic, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
-			clear_IO_APIC_pin(apic, pin);
-}
-
-#ifndef CONFIG_SMP
-void send_IPI_self(int vector)
-{
-	unsigned int cfg;
-
-	/*
-	 * Wait for idle.
-	 */
-	apic_wait_icr_idle();
-	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
-	/*
-	 * Send the IPI. The write to APIC_ICR fires this off.
-	 */
-	apic_write(APIC_ICR, cfg);
-}
-#endif /* !CONFIG_SMP */
-
-
-/*
- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
- * specific CPU-side IRQs.
- */
-
-#define MAX_PIRQS 8
-static int pirq_entries [MAX_PIRQS];
-static int pirqs_enabled;
-
-static int __init ioapic_pirq_setup(char *str)
-{
-	int i, max;
-	int ints[MAX_PIRQS+1];
-
-	get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0; i < MAX_PIRQS; i++)
-		pirq_entries[i] = -1;
-
-	pirqs_enabled = 1;
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"PIRQ redirection, working around broken MP-BIOS.\n");
-	max = MAX_PIRQS;
-	if (ints[0] < MAX_PIRQS)
-		max = ints[0];
-
-	for (i = 0; i < max; i++) {
-		apic_printk(APIC_VERBOSE, KERN_DEBUG
-				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
-		/*
-		 * PIRQs are mapped upside down, usually.
-		 */
-		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
-	}
-	return 1;
-}
-
-__setup("pirq=", ioapic_pirq_setup);
-
-/*
- * Find the IRQ entry number of a certain pin.
- */
-static int find_irq_entry(int apic, int pin, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++)
-		if (mp_irqs[i].mp_irqtype == type &&
-		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
-		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
-		    mp_irqs[i].mp_dstirq == pin)
-			return i;
-
-	return -1;
-}
-
-/*
- * Find the pin to which IRQ[irq] (ISA) is connected
- */
-static int __init find_isa_irq_pin(int irq, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		if (test_bit(lbus, mp_bus_not_pci) &&
-		    (mp_irqs[i].mp_irqtype == type) &&
-		    (mp_irqs[i].mp_srcbusirq == irq))
-
-			return mp_irqs[i].mp_dstirq;
-	}
-	return -1;
-}
-
-static int __init find_isa_irq_apic(int irq, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		if (test_bit(lbus, mp_bus_not_pci) &&
-		    (mp_irqs[i].mp_irqtype == type) &&
-		    (mp_irqs[i].mp_srcbusirq == irq))
-			break;
-	}
-	if (i < mp_irq_entries) {
-		int apic;
-		for (apic = 0; apic < nr_ioapics; apic++) {
-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
-				return apic;
-		}
-	}
-
-	return -1;
-}
-
-/*
- * Find a specific PCI IRQ entry.
- * Not an __init, possibly needed by modules
- */
-static int pin_2_irq(int idx, int apic, int pin);
-
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
-{
-	int apic, i, best_guess = -1;
-
-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
-		"slot:%d, pin:%d.\n", bus, slot, pin);
-	if (test_bit(bus, mp_bus_not_pci)) {
-		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
-		return -1;
-	}
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		for (apic = 0; apic < nr_ioapics; apic++)
-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
-			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
-				break;
-
-		if (!test_bit(lbus, mp_bus_not_pci) &&
-		    !mp_irqs[i].mp_irqtype &&
-		    (bus == lbus) &&
-		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, apic, mp_irqs[i].mp_dstirq);
-
-			if (!(apic || IO_APIC_IRQ(irq)))
-				continue;
-
-			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
-				return irq;
-			/*
-			 * Use the first all-but-pin matching entry as a
-			 * best-guess fuzzy result for broken mptables.
-			 */
-			if (best_guess < 0)
-				best_guess = irq;
-		}
-	}
-	return best_guess;
-}
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
-/*
- * EISA Edge/Level control register, ELCR
- */
-static int EISA_ELCR(unsigned int irq)
-{
-	if (irq < 16) {
-		unsigned int port = 0x4d0 + (irq >> 3);
-		return (inb(port) >> (irq & 7)) & 1;
-	}
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"Broken MPtable reports ISA irq %d\n", irq);
-	return 0;
-}
-#endif
-
-/* ISA interrupts are always polarity zero edge triggered,
- * when listed as conforming in the MP table. */
-
-#define default_ISA_trigger(idx)	(0)
-#define default_ISA_polarity(idx)	(0)
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value.  If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
-#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
-
-/* PCI interrupts are always polarity one level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_PCI_trigger(idx)	(1)
-#define default_PCI_polarity(idx)	(1)
-
-/* MCA interrupts are always polarity zero level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_MCA_trigger(idx)	(1)
-#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
-
-static int MPBIOS_polarity(int idx)
-{
-	int bus = mp_irqs[idx].mp_srcbus;
-	int polarity;
-
-	/*
-	 * Determine IRQ line polarity (high active or low active):
-	 */
-	switch (mp_irqs[idx].mp_irqflag & 3) {
-	case 0: /* conforms, ie. bus-type dependent polarity */
-	{
-		polarity = test_bit(bus, mp_bus_not_pci)?
-			default_ISA_polarity(idx):
-			default_PCI_polarity(idx);
-		break;
-	}
-	case 1: /* high active */
-	{
-		polarity = 0;
-		break;
-	}
-	case 2: /* reserved */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		polarity = 1;
-		break;
-	}
-	case 3: /* low active */
-	{
-		polarity = 1;
-		break;
-	}
-	default: /* invalid */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		polarity = 1;
-		break;
-	}
-	}
-	return polarity;
-}
-
-static int MPBIOS_trigger(int idx)
-{
-	int bus = mp_irqs[idx].mp_srcbus;
-	int trigger;
-
-	/*
-	 * Determine IRQ trigger mode (edge or level sensitive):
-	 */
-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3) {
-	case 0: /* conforms, ie. bus-type dependent */
-	{
-		trigger = test_bit(bus, mp_bus_not_pci)?
-				default_ISA_trigger(idx):
-				default_PCI_trigger(idx);
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
-		switch (mp_bus_id_to_type[bus]) {
-		case MP_BUS_ISA: /* ISA pin */
-		{
-			/* set before the switch */
-			break;
-		}
-		case MP_BUS_EISA: /* EISA pin */
-		{
-			trigger = default_EISA_trigger(idx);
-			break;
-		}
-		case MP_BUS_PCI: /* PCI pin */
-		{
-			/* set before the switch */
-			break;
-		}
-		case MP_BUS_MCA: /* MCA pin */
-		{
-			trigger = default_MCA_trigger(idx);
-			break;
-		}
-		default:
-		{
-			printk(KERN_WARNING "broken BIOS!!\n");
-			trigger = 1;
-			break;
-		}
-	}
-#endif
-		break;
-	}
-	case 1: /* edge */
-	{
-		trigger = 0;
-		break;
-	}
-	case 2: /* reserved */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		trigger = 1;
-		break;
-	}
-	case 3: /* level */
-	{
-		trigger = 1;
-		break;
-	}
-	default: /* invalid */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		trigger = 0;
-		break;
-	}
-	}
-	return trigger;
-}
-
-static inline int irq_polarity(int idx)
-{
-	return MPBIOS_polarity(idx);
-}
-
-static inline int irq_trigger(int idx)
-{
-	return MPBIOS_trigger(idx);
-}
-
-int (*ioapic_renumber_irq)(int ioapic, int irq);
-static int pin_2_irq(int idx, int apic, int pin)
-{
-	int irq, i;
-	int bus = mp_irqs[idx].mp_srcbus;
-
-	/*
-	 * Debugging check, we are in big trouble if this message pops up!
-	 */
-	if (mp_irqs[idx].mp_dstirq != pin)
-		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
-
-	if (test_bit(bus, mp_bus_not_pci))
-		irq = mp_irqs[idx].mp_srcbusirq;
-	else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
-
-		/*
-		 * For MPS mode, so far only needed by ES7000 platform
-		 */
-		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
-	}
-
-	/*
-	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
-	 */
-	if ((pin >= 16) && (pin <= 23)) {
-		if (pirq_entries[pin-16] != -1) {
-			if (!pirq_entries[pin-16]) {
-				apic_printk(APIC_VERBOSE, KERN_DEBUG
-						"disabling PIRQ%d\n", pin-16);
-			} else {
-				irq = pirq_entries[pin-16];
-				apic_printk(APIC_VERBOSE, KERN_DEBUG
-						"using PIRQ%d -> IRQ %d\n",
-						pin-16, irq);
-			}
-		}
-	}
-	return irq;
-}
-
-void lock_vector_lock(void)
-{
-	/* Used to the online set of cpus does not change
-	 * during assign_irq_vector.
-	 */
-	spin_lock(&vector_lock);
-}
-
-void unlock_vector_lock(void)
-{
-	spin_unlock(&vector_lock);
-}
-
-static int __assign_irq_vector(int irq, cpumask_t mask)
-{
-	/*
-	 * NOTE! The local APIC isn't very good at handling
-	 * multiple interrupts at the same interrupt level.
-	 * As the interrupt level is determined by taking the
-	 * vector number and shifting that right by 4, we
-	 * want to spread these out a bit so that they don't
-	 * all fall in the same interrupt level.
-	 *
-	 * Also, we've got to be careful not to trash gate
-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
-	 */
-        static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
-        unsigned int old_vector;
-        int cpu;
-        struct irq_cfg *cfg;
-
-        cfg = irq_cfg(irq);
-
-        /* Only try and allocate irqs on cpus that are present */
-        cpus_and(mask, mask, cpu_online_map);
-
-        if ((cfg->move_in_progress) || cfg->move_cleanup_count)
-                return -EBUSY;
-
-        old_vector = cfg->vector;
-        if (old_vector) {
-                cpumask_t tmp;
-                cpus_and(tmp, cfg->domain, mask);
-                if (!cpus_empty(tmp))
-                        return 0;
-        }
-
-        for_each_cpu_mask_nr(cpu, mask) {
-                cpumask_t domain, new_mask;
-                int new_cpu;
-                int vector, offset;
-
-                domain = vector_allocation_domain(cpu);
-                cpus_and(new_mask, domain, cpu_online_map);
-
-                vector = current_vector;
-                offset = current_offset;
-next:
-                vector += 8;
-                if (vector >= first_system_vector) {
-                        /* If we run out of vectors on large boxen, must share them. */
-                        offset = (offset + 1) % 8;
-                        vector = FIRST_DEVICE_VECTOR + offset;
-                }
-                if (unlikely(current_vector == vector))
-                        continue;
-#ifdef CONFIG_X86_64
-                if (vector == IA32_SYSCALL_VECTOR)
-                        goto next;
-#else
-                if (vector == SYSCALL_VECTOR)
-                        goto next;
-#endif
-                for_each_cpu_mask_nr(new_cpu, new_mask)
-                        if (per_cpu(vector_irq, new_cpu)[vector] != -1)
-                                goto next;
-                /* Found one! */
-                current_vector = vector;
-                current_offset = offset;
-                if (old_vector) {
-                        cfg->move_in_progress = 1;
-                        cfg->old_domain = cfg->domain;
-                }
-		printk(KERN_DEBUG "assign_irq_vector: irq %d vector %#x cpu ", irq, vector);
-		for_each_cpu_mask_nr(new_cpu, new_mask) {
-			per_cpu(vector_irq, new_cpu)[vector] = irq;
-			printk(KERN_CONT " %d ", new_cpu);
-		}
-		printk(KERN_CONT "\n");
-                cfg->vector = vector;
-                cfg->domain = domain;
-                return 0;
-        }
-        return -ENOSPC;
-}
-
-static int assign_irq_vector(int irq, cpumask_t mask)
-{
-	int err;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vector_lock, flags);
-	err = __assign_irq_vector(irq, mask);
-	spin_unlock_irqrestore(&vector_lock, flags);
-
-	return err;
-}
-
-static void __clear_irq_vector(int irq)
-{
-	struct irq_cfg *cfg;
-	cpumask_t mask;
-	int cpu, vector;
-
-	cfg = irq_cfg(irq);
-	BUG_ON(!cfg->vector);
-
-	vector = cfg->vector;
-	cpus_and(mask, cfg->domain, cpu_online_map);
-	for_each_cpu_mask_nr(cpu, mask)
-		per_cpu(vector_irq, cpu)[vector] = -1;
-
-	cfg->vector = 0;
-	cpus_clear(cfg->domain);
-}
-
-void __setup_vector_irq(int cpu)
-{
-	/* Initialize vector_irq on a new cpu */
-	/* This function must be called with vector_lock held */
-	int irq, vector;
-	struct irq_cfg *cfg;
-
-	/* Mark the inuse vectors */
-	for_each_irq_cfg(cfg) {
-		if (!cpu_isset(cpu, cfg->domain))
-			continue;
-		vector = cfg->vector;
-		irq = cfg->irq;
-		per_cpu(vector_irq, cpu)[vector] = irq;
-	}
-	/* Mark the free vectors */
-	for (vector = 0; vector < NR_VECTORS; ++vector) {
-		irq = per_cpu(vector_irq, cpu)[vector];
-		if (irq < 0)
-			continue;
-
-		cfg = irq_cfg(irq);
-		if (!cpu_isset(cpu, cfg->domain))
-			per_cpu(vector_irq, cpu)[vector] = -1;
-        }
-}
-
-static struct irq_chip ioapic_chip;
-
-#define IOAPIC_AUTO	-1
-#define IOAPIC_EDGE	0
-#define IOAPIC_LEVEL	1
-
-#ifdef CONFIG_X86_32
-static inline int IO_APIC_irq_trigger(int irq)
-{
-	int apic, idx, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			idx = find_irq_entry(apic, pin, mp_INT);
-			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-				return irq_trigger(idx);
-		}
-	}
-	/*
-	 * nonexistent IRQs are edge default
-	 */
-	return 0;
-}
-#else
-static inline int IO_APIC_irq_trigger(int irq)
-{
-        return 1;
-}
-#endif
-
-static void ioapic_register_intr(int irq, unsigned long trigger)
-{
-	struct irq_desc *desc;
-
-	/* first time to use this irq_desc */
-	if (irq < 16)
-		desc = irq_desc(irq);
-	else
-		desc = irq_desc_with_new(irq);
-
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		desc->status |= IRQ_LEVEL;
-	else
-		desc->status &= ~IRQ_LEVEL;
-
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					 handle_fasteoi_irq, "fasteoi");
-	else
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					 handle_edge_irq, "edge");
-}
-
-static int setup_ioapic_entry(int apic, int irq,
-			      struct IO_APIC_route_entry *entry,
-			      unsigned int destination, int trigger,
-			      int polarity, int vector)
-{
-	/*
-	 * add it to the IO-APIC irq-routing table:
-	 */
-	memset(entry,0,sizeof(*entry));
-
-	entry->delivery_mode = INT_DELIVERY_MODE;
-	entry->dest_mode = INT_DEST_MODE;
-	entry->dest = destination;
-
-	entry->mask = 0;                                /* enable IRQ */
-	entry->trigger = trigger;
-	entry->polarity = polarity;
-	entry->vector = vector;
-
-	/* Mask level triggered irqs.
-	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
-	 */
-	if (trigger)
-		entry->mask = 1;
-
-	return 0;
-}
-
-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
-                              int trigger, int polarity)
-{
-	struct irq_cfg *cfg;
-	struct IO_APIC_route_entry entry;
-	cpumask_t mask;
-
-	if (!IO_APIC_IRQ(irq))
-		return;
-
-	cfg = irq_cfg(irq);
-
-	mask = TARGET_CPUS;
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cpus_and(mask, cfg->domain, mask);
-
-	apic_printk(APIC_VERBOSE,KERN_DEBUG
-		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
-		    "IRQ %d Mode:%i Active:%i)\n",
-		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
-		    irq, trigger, polarity);
-
-
-	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
-			       cpu_mask_to_apicid(mask), trigger, polarity,
-			       cfg->vector)) {
-		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
-		       mp_ioapics[apic].mp_apicid, pin);
-		__clear_irq_vector(irq);
-		return;
-	}
-
-	ioapic_register_intr(irq, trigger);
-	if (irq < 16)
-		disable_8259A_irq(irq);
-
-	ioapic_write_entry(apic, pin, entry);
-}
-
-static void __init setup_IO_APIC_irqs(void)
-{
-	int apic, pin, idx, irq, first_notcon = 1;
-
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-
-		idx = find_irq_entry(apic,pin,mp_INT);
-		if (idx == -1) {
-			if (first_notcon) {
-				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
-				first_notcon = 0;
-			} else
-				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
-			continue;
-		}
-		if (!first_notcon) {
-			apic_printk(APIC_VERBOSE, " not connected.\n");
-			first_notcon = 1;
-		}
-
-		irq = pin_2_irq(idx, apic, pin);
-
-                if (multi_timer_check(apic, irq))
-                        continue;
-
-		add_pin_to_irq(irq, apic, pin);
-
-		setup_IO_APIC_irq(apic, pin, irq,
-				  irq_trigger(idx), irq_polarity(idx));
-	}
-	}
-
-	if (!first_notcon)
-		apic_printk(APIC_VERBOSE, " not connected.\n");
-}
-
-/*
- * Set up the timer pin, possibly with the 8259A-master behind.
- */
-static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
-					int vector)
-{
-	struct IO_APIC_route_entry entry;
-
-	memset(&entry, 0, sizeof(entry));
-
-	/*
-	 * We use logical delivery to get the timer IRQ
-	 * to the first CPU.
-	 */
-	entry.dest_mode = INT_DEST_MODE;
-	entry.mask = 1;					/* mask IRQ now */
-	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
-	entry.delivery_mode = INT_DELIVERY_MODE;
-	entry.polarity = 0;
-	entry.trigger = 0;
-	entry.vector = vector;
-
-	/*
-	 * The timer IRQ doesn't have to know that behind the
-	 * scene we may have a 8259A-master in AEOI mode ...
-	 */
-	ioapic_register_intr(0, IOAPIC_EDGE);
-
-	/*
-	 * Add it to the IO-APIC irq-routing table:
-	 */
-	ioapic_write_entry(apic, pin, entry);
-}
-
-
-__apicdebuginit(void) print_IO_APIC(void)
-{
-	int apic, i;
-	union IO_APIC_reg_00 reg_00;
-	union IO_APIC_reg_01 reg_01;
-	union IO_APIC_reg_02 reg_02;
-	union IO_APIC_reg_03 reg_03;
-	unsigned long flags;
-	struct irq_cfg *cfg;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
-	for (i = 0; i < nr_ioapics; i++)
-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
-		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
-
-	/*
-	 * We are a bit conservative about what we expect.  We have to
-	 * know about every hardware change ASAP.
-	 */
-	printk(KERN_INFO "testing the IO APIC.......................\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(apic, 0);
-	reg_01.raw = io_apic_read(apic, 1);
-	if (reg_01.bits.version >= 0x10)
-		reg_02.raw = io_apic_read(apic, 2);
-	if (reg_01.bits.version >= 0x20)
-		reg_03.raw = io_apic_read(apic, 3);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
-	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
-	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
-	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
-	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
-
-	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
-
-	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
-
-	/*
-	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
-	 * but the value of reg_02 is read as the previous read register
-	 * value, so ignore it if reg_02 == reg_01.
-	 */
-	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
-		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
-		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
-	}
-
-	/*
-	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
-	 * or reg_03, but the value of reg_0[23] is read as the previous read
-	 * register value, so ignore it if reg_03 == reg_0[12].
-	 */
-	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
-	    reg_03.raw != reg_01.raw) {
-		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
-		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
-	}
-
-	printk(KERN_DEBUG ".... IRQ redirection table:\n");
-
-	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
-			  " Stat Dmod Deli Vect:   \n");
-
-	for (i = 0; i <= reg_01.bits.entries; i++) {
-		struct IO_APIC_route_entry entry;
-
-		entry = ioapic_read_entry(apic, i);
-
-		printk(KERN_DEBUG " %02x %02X  ", i, entry.dest);
-
-		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
-			entry.mask,
-			entry.trigger,
-			entry.irr,
-			entry.polarity,
-			entry.delivery_status,
-			entry.dest_mode,
-			entry.delivery_mode,
-			entry.vector
-		);
-	}
-	}
-	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for_each_irq_cfg(cfg) {
-		struct irq_pin_list *entry = cfg->irq_2_pin;
-		if (!entry)
-			continue;
-		printk(KERN_DEBUG "IRQ%d ", i);
-		for (;;) {
-			printk("-> %d:%d", entry->apic, entry->pin);
-			if (!entry->next)
-				break;
-			entry = entry->next;
-		}
-		printk("\n");
-	}
-
-	printk(KERN_INFO ".................................... done.\n");
-
-	return;
-}
-
-__apicdebuginit(void) print_APIC_bitfield(int base)
-{
-	unsigned int v;
-	int i, j;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
-	for (i = 0; i < 8; i++) {
-		v = apic_read(base + i*0x10);
-		for (j = 0; j < 32; j++) {
-			if (v & (1<<j))
-				printk("1");
-			else
-				printk("0");
-		}
-		printk("\n");
-	}
-}
-
-__apicdebuginit(void) print_local_APIC(void *dummy)
-{
-	unsigned int v, ver, maxlvt;
-	u64 icr;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
-		smp_processor_id(), hard_smp_processor_id());
-	v = apic_read(APIC_ID);
-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
-			GET_APIC_ID(v));
-	v = apic_read(APIC_LVR);
-	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
-	ver = GET_APIC_VERSION(v);
-	maxlvt = lapic_get_maxlvt();
-
-	v = apic_read(APIC_TASKPRI);
-	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
-
-	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
-		v = apic_read(APIC_ARBPRI);
-		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-			v & APIC_ARBPRI_MASK);
-		v = apic_read(APIC_PROCPRI);
-		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
-	}
-
-	v = apic_read(APIC_EOI);
-	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
-	v = apic_read(APIC_RRR);
-	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
-	v = apic_read(APIC_LDR);
-	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
-	v = apic_read(APIC_DFR);
-	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
-	v = apic_read(APIC_SPIV);
-	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
-
-	printk(KERN_DEBUG "... APIC ISR field:\n");
-	print_APIC_bitfield(APIC_ISR);
-	printk(KERN_DEBUG "... APIC TMR field:\n");
-	print_APIC_bitfield(APIC_TMR);
-	printk(KERN_DEBUG "... APIC IRR field:\n");
-	print_APIC_bitfield(APIC_IRR);
-
-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
-			apic_write(APIC_ESR, 0);
-		v = apic_read(APIC_ESR);
-		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
-	}
-
-	icr = apic_icr_read();
-	printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
-	printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
-
-	v = apic_read(APIC_LVTT);
-	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
-
-	if (maxlvt > 3) {                       /* PC is LVT#4. */
-		v = apic_read(APIC_LVTPC);
-		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
-	}
-	v = apic_read(APIC_LVT0);
-	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
-	v = apic_read(APIC_LVT1);
-	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
-
-	if (maxlvt > 2) {			/* ERR is LVT#3. */
-		v = apic_read(APIC_LVTERR);
-		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
-	}
-
-	v = apic_read(APIC_TMICT);
-	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
-	v = apic_read(APIC_TMCCT);
-	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
-	v = apic_read(APIC_TDCR);
-	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
-	printk("\n");
-}
-
-__apicdebuginit(void) print_all_local_APICs(void)
-{
-	on_each_cpu(print_local_APIC, NULL, 1);
-}
-
-__apicdebuginit(void) print_PIC(void)
-{
-	unsigned int v;
-	unsigned long flags;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "\nprinting PIC contents\n");
-
-	spin_lock_irqsave(&i8259A_lock, flags);
-
-	v = inb(0xa1) << 8 | inb(0x21);
-	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
-
-	v = inb(0xa0) << 8 | inb(0x20);
-	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
-
-	outb(0x0b, 0xa0);
-	outb(0x0b, 0x20);
-	v = inb(0xa0) << 8 | inb(0x20);
-	outb(0x0a, 0xa0);
-	outb(0x0a, 0x20);
-
-	spin_unlock_irqrestore(&i8259A_lock, flags);
-
-	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
-
-	v = inb(0x4d1) << 8 | inb(0x4d0);
-	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
-}
-
-__apicdebuginit(int) print_all_ICs(void)
-{
-	print_PIC();
-	print_all_local_APICs();
-	print_IO_APIC();
-
-	return 0;
-}
-
-fs_initcall(print_all_ICs);
-
-
-/* Where if anywhere is the i8259 connect in external int mode */
-static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
-
-static void __init enable_IO_APIC(void)
-{
-	union IO_APIC_reg_01 reg_01;
-	int i8259_apic, i8259_pin;
-	int i, apic;
-	unsigned long flags;
-
-	if (!pirqs_enabled)
-		for (i = 0; i < MAX_PIRQS; i++)
-			pirq_entries[i] = -1;
-
-	/*
-	 * The number of IO-APIC IRQ registers (== #pins):
-	 */
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_01.raw = io_apic_read(apic, 1);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
-	}
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		int pin;
-		/* See if any of the pins is in ExtINT mode */
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			struct IO_APIC_route_entry entry;
-			entry = ioapic_read_entry(apic, pin);
-
-			/* If the interrupt line is enabled and in ExtInt mode
-			 * I have found the pin where the i8259 is connected.
-			 */
-			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
-				ioapic_i8259.apic = apic;
-				ioapic_i8259.pin  = pin;
-				goto found_i8259;
-			}
-		}
-	}
- found_i8259:
-	/* Look to see what if the MP table has reported the ExtINT */
-	/* If we could not find the appropriate pin by looking at the ioapic
-	 * the i8259 probably is not connected the ioapic but give the
-	 * mptable a chance anyway.
-	 */
-	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
-	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
-	/* Trust the MP table if nothing is setup in the hardware */
-	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
-		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
-		ioapic_i8259.pin  = i8259_pin;
-		ioapic_i8259.apic = i8259_apic;
-	}
-	/* Complain if the MP table and the hardware disagree */
-	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
-		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
-	{
-		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
-	}
-
-	/*
-	 * Do not trust the IO-APIC being empty at bootup
-	 */
-	clear_IO_APIC();
-}
-
-/*
- * Not an __init, needed by the reboot code
- */
-void disable_IO_APIC(void)
-{
-	/*
-	 * Clear the IO-APIC before rebooting:
-	 */
-	clear_IO_APIC();
-
-	/*
-	 * If the i8259 is routed through an IOAPIC
-	 * Put that IOAPIC in virtual wire mode
-	 * so legacy interrupts can be delivered.
-	 */
-	if (ioapic_i8259.pin != -1) {
-		struct IO_APIC_route_entry entry;
-
-		memset(&entry, 0, sizeof(entry));
-		entry.mask            = 0; /* Enabled */
-		entry.trigger         = 0; /* Edge */
-		entry.irr             = 0;
-		entry.polarity        = 0; /* High */
-		entry.delivery_status = 0;
-		entry.dest_mode       = 0; /* Physical */
-		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
-		entry.vector          = 0;
-		entry.dest	      = read_apic_id();
-
-		/*
-		 * Add it to the IO-APIC irq-routing table:
-		 */
-		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
-	}
-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
-}
-
-/*
- * function to set the IO-APIC physical IDs based on the
- * values stored in the MPC table.
- *
- * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
- */
-
-static void __init setup_ioapic_ids_from_mpc(void)
-{
-	union IO_APIC_reg_00 reg_00;
-	physid_mask_t phys_id_present_map;
-	int apic;
-	int i;
-	unsigned char old_id;
-	unsigned long flags;
-
-	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
-		return;
-
-	/*
-	 * Don't check I/O APIC IDs for xAPIC systems.  They have
-	 * no meaning without the serial APIC bus.
-	 */
-	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return;
-	/*
-	 * This is broken; anything with a real cpu count has to
-	 * circumvent this idiocy regardless.
-	 */
-	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
-
-	/*
-	 * Set the IOAPIC ID to the value stored in the MPC table.
-	 */
-	for (apic = 0; apic < nr_ioapics; apic++) {
-
-		/* Read the register 0 value */
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-
-		old_id = mp_ioapics[apic].mp_apicid;
-
-		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
-				apic, mp_ioapics[apic].mp_apicid);
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				reg_00.bits.ID);
-			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
-		}
-
-		/*
-		 * Sanity check, is the ID really free? Every APIC in a
-		 * system must have a unique ID or we get lots of nice
-		 * 'stuck on smp_invalidate_needed IPI wait' messages.
-		 */
-		if (check_apicid_used(phys_id_present_map,
-					mp_ioapics[apic].mp_apicid)) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-				apic, mp_ioapics[apic].mp_apicid);
-			for (i = 0; i < get_physical_broadcast(); i++)
-				if (!physid_isset(i, phys_id_present_map))
-					break;
-			if (i >= get_physical_broadcast())
-				panic("Max APIC ID exceeded!\n");
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				i);
-			physid_set(i, phys_id_present_map);
-			mp_ioapics[apic].mp_apicid = i;
-		} else {
-			physid_mask_t tmp;
-			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
-			apic_printk(APIC_VERBOSE, "Setting %d in the "
-					"phys_id_present_map\n",
-					mp_ioapics[apic].mp_apicid);
-			physids_or(phys_id_present_map, phys_id_present_map, tmp);
-		}
-
-
-		/*
-		 * We need to adjust the IRQ routing table
-		 * if the ID changed.
-		 */
-		if (old_id != mp_ioapics[apic].mp_apicid)
-			for (i = 0; i < mp_irq_entries; i++)
-				if (mp_irqs[i].mp_dstapic == old_id)
-					mp_irqs[i].mp_dstapic
-						= mp_ioapics[apic].mp_apicid;
-
-		/*
-		 * Read the right value from the MPC table and
-		 * write it into the ID register.
-		 */
-		apic_printk(APIC_VERBOSE, KERN_INFO
-			"...changing IO-APIC physical APIC ID to %d ...",
-			mp_ioapics[apic].mp_apicid);
-
-		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
-		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(apic, 0, reg_00.raw);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-
-		/*
-		 * Sanity check
-		 */
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
-			printk("could not set ID!\n");
-		else
-			apic_printk(APIC_VERBOSE, " ok.\n");
-	}
-}
-
-int no_timer_check __initdata;
-
-static int __init notimercheck(char *s)
-{
-	no_timer_check = 1;
-	return 1;
-}
-__setup("no_timer_check", notimercheck);
-
-/*
- * There is a nasty bug in some older SMP boards, their mptable lies
- * about the timer IRQ. We do the following to work around the situation:
- *
- *	- timer IRQ defaults to IO-APIC IRQ
- *	- if this function detects that timer IRQs are defunct, then we fall
- *	  back to ISA timer IRQs
- */
-static int __init timer_irq_works(void)
-{
-	unsigned long t1 = jiffies;
-	unsigned long flags;
-
-	if (no_timer_check)
-		return 1;
-
-	local_save_flags(flags);
-	local_irq_enable();
-	/* Let ten ticks pass... */
-	mdelay((10 * 1000) / HZ);
-	local_irq_restore(flags);
-
-	/*
-	 * Expect a few ticks at least, to be sure some possible
-	 * glue logic does not lock up after one or two first
-	 * ticks in a non-ExtINT mode.  Also the local APIC
-	 * might have cached one ExtINT interrupt.  Finally, at
-	 * least one tick may be lost due to delays.
-	 */
-	if (time_after(jiffies, t1 + 4))
-		return 1;
-
-	return 0;
-}
-
-/*
- * In the SMP+IOAPIC case it might happen that there are an unspecified
- * number of pending IRQ events unhandled. These cases are very rare,
- * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
- * better to do it this way as thus we do not have to be aware of
- * 'pending' interrupts in the IRQ path, except at this point.
- */
-/*
- * Edge triggered needs to resend any interrupt
- * that was delayed but this is now handled in the device
- * independent code.
- */
-
-/*
- * Startup quirk:
- *
- * Starting up a edge-triggered IO-APIC interrupt is
- * nasty - we need to make sure that we get the edge.
- * If it is already asserted for some reason, we need
- * return 1 to indicate that is was pending.
- *
- * This is not complete - we should be able to fake
- * an edge even if it isn't on the 8259A...
- *
- * (We do this for level-triggered IRQs too - it cannot hurt.)
- */
-static unsigned int startup_ioapic_irq(unsigned int irq)
-{
-	int was_pending = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	if (irq < 16) {
-		disable_8259A_irq(irq);
-		if (i8259A_irq_pending(irq))
-			was_pending = 1;
-	}
-	__unmask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return was_pending;
-}
-
-static int ioapic_retrigger_irq(unsigned int irq)
-{
-	send_IPI_self(irq_cfg(irq)->vector);
-
-	return 1;
-}
-
-#ifdef CONFIG_SMP
-asmlinkage void smp_irq_move_cleanup_interrupt(void)
-{
-	unsigned vector, me;
-	ack_APIC_irq();
-	irq_enter();
-
-	me = smp_processor_id();
-	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
-		unsigned int irq;
-		struct irq_desc *desc;
-		struct irq_cfg *cfg;
-		irq = __get_cpu_var(vector_irq)[vector];
-
-		desc = irq_desc(irq);
-		if (!desc)
-			continue;
-
-		cfg = irq_cfg(irq);
-		spin_lock(&desc->lock);
-		if (!cfg->move_cleanup_count)
-			goto unlock;
-
-		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
-			goto unlock;
-
-		__get_cpu_var(vector_irq)[vector] = -1;
-		cfg->move_cleanup_count--;
-unlock:
-		spin_unlock(&desc->lock);
-	}
-
-	irq_exit();
-}
-
-static void irq_complete_move(unsigned int irq)
-{
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned vector, me;
-
-	if (likely(!cfg->move_in_progress))
-		return;
-
-	vector = ~get_irq_regs()->orig_ax;
-	me = smp_processor_id();
-	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
-		cpumask_t cleanup_mask;
-
-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
-		cfg->move_in_progress = 0;
-	}
-}
-#else
-static inline void irq_complete_move(unsigned int irq) {}
-#endif
-
-static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
-{
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-	ack_APIC_irq();
-}
-
-#ifdef CONFIG_X86_64
-static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
-{
-        int do_unmask_irq = 0;
-
-        irq_complete_move(irq);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-        /* If we are moving the irq we need to mask it */
-        if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
-                do_unmask_irq = 1;
-                mask_IO_APIC_irq(irq);
-        }
-#endif
-
-        /*
-         * We must acknowledge the irq before we move it or the acknowledge will
-         * not propagate properly.
-         */
-        ack_APIC_irq();
-
-        /* Now we can move and renable the irq */
-        if (unlikely(do_unmask_irq)) {
-                /* Only migrate the irq if the ack has been received.
-                 *
-                 * On rare occasions the broadcast level triggered ack gets
-                 * delayed going to ioapics, and if we reprogram the
-                 * vector while Remote IRR is still set the irq will never
-                 * fire again.
-                 *
-                 * To prevent this scenario we read the Remote IRR bit
-                 * of the ioapic.  This has two effects.
-                 * - On any sane system the read of the ioapic will
-                 *   flush writes (and acks) going to the ioapic from
-                 *   this cpu.
-                 * - We get to see if the ACK has actually been delivered.
-                 *
-                 * Based on failed experiments of reprogramming the
-                 * ioapic entry from outside of irq context starting
-                 * with masking the ioapic entry and then polling until
-                 * Remote IRR was clear before reprogramming the
-                 * ioapic I don't trust the Remote IRR bit to be
-                 * completey accurate.
-                 *
-                 * However there appears to be no other way to plug
-                 * this race, so if the Remote IRR bit is not
-                 * accurate and is causing problems then it is a hardware bug
-                 * and you can go talk to the chipset vendor about it.
-                 */
-                if (!io_apic_level_ack_pending(irq))
-                        move_masked_irq(irq, desc);
-                unmask_IO_APIC_irq(irq);
-        }
-}
-#else
-atomic_t irq_mis_count;
-static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned long v;
-	int i;
-
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-/*
- * It appears there is an erratum which affects at least version 0x11
- * of I/O APIC (that's the 82093AA and cores integrated into various
- * chipsets).  Under certain conditions a level-triggered interrupt is
- * erroneously delivered as edge-triggered one but the respective IRR
- * bit gets set nevertheless.  As a result the I/O unit expects an EOI
- * message but it will never arrive and further interrupts are blocked
- * from the source.  The exact reason is so far unknown, but the
- * phenomenon was observed when two consecutive interrupt requests
- * from a given source get delivered to the same CPU and the source is
- * temporarily disabled in between.
- *
- * A workaround is to simulate an EOI message manually.  We achieve it
- * by setting the trigger mode to edge and then to level when the edge
- * trigger mode gets detected in the TMR of a local APIC for a
- * level-triggered interrupt.  We mask the source for the time of the
- * operation to prevent an edge-triggered interrupt escaping meanwhile.
- * The idea is from Manfred Spraul.  --macro
- */
-	i = irq_cfg(irq)->vector;
-
-	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
-
-	ack_APIC_irq();
-
-	if (!(v & (1 << (i & 0x1f)))) {
-		atomic_inc(&irq_mis_count);
-		spin_lock(&ioapic_lock);
-		__mask_and_edge_IO_APIC_irq(irq);
-		__unmask_and_level_IO_APIC_irq(irq);
-		spin_unlock(&ioapic_lock);
-	}
-}
-#endif
-
-static struct irq_chip ioapic_chip __read_mostly = {
-	.name 		= "IO-APIC",
-	.startup 	= startup_ioapic_irq,
-	.mask	 	= mask_IO_APIC_irq,
-	.unmask	 	= unmask_IO_APIC_irq,
-	.ack 		= ack_apic_edge,
-	.eoi 		= ack_apic_level,
-#ifdef CONFIG_SMP
-	.set_affinity 	= set_ioapic_affinity_irq,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-
-static inline void init_IO_APIC_traps(void)
-{
-	int irq;
-	struct irq_desc *desc;
-	struct irq_cfg *cfg;
-
-	/*
-	 * NOTE! The local APIC isn't very good at handling
-	 * multiple interrupts at the same interrupt level.
-	 * As the interrupt level is determined by taking the
-	 * vector number and shifting that right by 4, we
-	 * want to spread these out a bit so that they don't
-	 * all fall in the same interrupt level.
-	 *
-	 * Also, we've got to be careful not to trash gate
-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
-	 */
-	for_each_irq_cfg(cfg) {
-		irq = cfg->irq;
-		if (IO_APIC_IRQ(irq) && !cfg->vector) {
-			/*
-			 * Hmm.. We don't have an entry for this,
-			 * so default to an old-fashioned 8259
-			 * interrupt if we can..
-			 */
-			if (irq < 16)
-				make_8259A_irq(irq);
-			else {
-				desc = irq_desc(irq);
-				/* Strange. Oh, well.. */
-				desc->chip = &no_irq_chip;
-			}
-		}
-	}
-}
-
-/*
- * The local APIC irq-chip implementation:
- */
-
-static void mask_lapic_irq(unsigned int irq)
-{
-	unsigned long v;
-
-	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
-}
-
-static void unmask_lapic_irq(unsigned int irq)
-{
-	unsigned long v;
-
-	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
-}
-
-static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
-{
-	ack_APIC_irq();
-}
-
-static struct irq_chip lapic_chip __read_mostly = {
-	.name		= "local-APIC",
-	.mask		= mask_lapic_irq,
-	.unmask		= unmask_lapic_irq,
-	.ack		= ack_lapic_irq,
-};
-
-static void lapic_register_intr(int irq)
-{
-	struct irq_desc *desc;
-
-	desc = irq_desc(irq);
-	desc->status &= ~IRQ_LEVEL;
-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
-				      "edge");
-}
-
-static void __init setup_nmi(void)
-{
-	/*
-	 * Dirty trick to enable the NMI watchdog ...
-	 * We put the 8259A master into AEOI mode and
-	 * unmask on all local APICs LVT0 as NMI.
-	 *
-	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
-	 * is from Maciej W. Rozycki - so we do not have to EOI from
-	 * the NMI handler or the timer interrupt.
-	 */
-	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
-
-	enable_NMI_through_LVT0();
-
-	apic_printk(APIC_VERBOSE, " done.\n");
-}
-
-/*
- * This looks a bit hackish but it's about the only one way of sending
- * a few INTA cycles to 8259As and any associated glue logic.  ICR does
- * not support the ExtINT mode, unfortunately.  We need to send these
- * cycles as some i82489DX-based boards have glue logic that keeps the
- * 8259A interrupt line asserted until INTA.  --macro
- */
-static inline void __init unlock_ExtINT_logic(void)
-{
-	int apic, pin, i;
-	struct IO_APIC_route_entry entry0, entry1;
-	unsigned char save_control, save_freq_select;
-
-	pin  = find_isa_irq_pin(8, mp_INT);
-	if (pin == -1) {
-		WARN_ON_ONCE(1);
-		return;
-	}
-	apic = find_isa_irq_apic(8, mp_INT);
-	if (apic == -1) {
-		WARN_ON_ONCE(1);
-		return;
-	}
-
-	entry0 = ioapic_read_entry(apic, pin);
-	clear_IO_APIC_pin(apic, pin);
-
-	memset(&entry1, 0, sizeof(entry1));
-
-	entry1.dest_mode = 0;			/* physical delivery */
-	entry1.mask = 0;			/* unmask IRQ now */
-	entry1.dest = hard_smp_processor_id();
-	entry1.delivery_mode = dest_ExtINT;
-	entry1.polarity = entry0.polarity;
-	entry1.trigger = 0;
-	entry1.vector = 0;
-
-	ioapic_write_entry(apic, pin, entry1);
-
-	save_control = CMOS_READ(RTC_CONTROL);
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
-		   RTC_FREQ_SELECT);
-	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
-
-	i = 100;
-	while (i-- > 0) {
-		mdelay(10);
-		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
-			i -= 10;
-	}
-
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-	clear_IO_APIC_pin(apic, pin);
-
-	ioapic_write_entry(apic, pin, entry0);
-}
-
-static int disable_timer_pin_1 __initdata;
-/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
-static int __init parse_disable_timer_pin_1(char *arg)
-{
-	disable_timer_pin_1 = 1;
-	return 0;
-}
-early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
-
-int timer_through_8259 __initdata;
-
-/*
- * This code may look a bit paranoid, but it's supposed to cooperate with
- * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
- * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
- * fanatically on his truly buggy board.
- */
-static inline void __init check_timer(void)
-{
-	struct irq_cfg *cfg = irq_cfg(0);
-	int apic1, pin1, apic2, pin2;
-	unsigned long flags;
-	unsigned int ver;
-	int no_pin1 = 0;
-
-	local_irq_save(flags);
-
-	ver = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(ver);
-
-	/*
-	 * get/set the timer IRQ vector:
-	 */
-	disable_8259A_irq(0);
-	assign_irq_vector(0, TARGET_CPUS);
-
-	/*
-	 * As IRQ0 is to be enabled in the 8259A, the virtual
-	 * wire has to be disabled in the local APIC.  Also
-	 * timer interrupts need to be acknowledged manually in
-	 * the 8259A for the i82489DX when using the NMI
-	 * watchdog as that APIC treats NMIs as level-triggered.
-	 * The AEOI mode will finish them in the 8259A
-	 * automatically.
-	 */
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
-	init_8259A(1);
-	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
-
-	pin1  = find_isa_irq_pin(0, mp_INT);
-	apic1 = find_isa_irq_apic(0, mp_INT);
-	pin2  = ioapic_i8259.pin;
-	apic2 = ioapic_i8259.apic;
-
-	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
-		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		    cfg->vector, apic1, pin1, apic2, pin2);
-
-	/*
-	 * Some BIOS writers are clueless and report the ExtINTA
-	 * I/O APIC input from the cascaded 8259A as the timer
-	 * interrupt input.  So just in case, if only one pin
-	 * was found above, try it both directly and through the
-	 * 8259A.
-	 */
-	if (pin1 == -1) {
-		pin1 = pin2;
-		apic1 = apic2;
-		no_pin1 = 1;
-	} else if (pin2 == -1) {
-		pin2 = pin1;
-		apic2 = apic1;
-	}
-
-	if (pin1 != -1) {
-		/*
-		 * Ok, does IRQ0 through the IOAPIC work?
-		 */
-		if (no_pin1) {
-			add_pin_to_irq(0, apic1, pin1);
-			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
-		}
-		unmask_IO_APIC_irq(0);
-		if (timer_irq_works()) {
-			if (nmi_watchdog == NMI_IO_APIC) {
-				setup_nmi();
-				enable_8259A_irq(0);
-			}
-			if (disable_timer_pin_1 > 0)
-				clear_IO_APIC_pin(0, pin1);
-			goto out;
-		}
-		clear_IO_APIC_pin(apic1, pin1);
-		if (!no_pin1)
-			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
-				    "8254 timer not connected to IO-APIC\n");
-
-		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
-			    "(IRQ0) through the 8259A ...\n");
-		apic_printk(APIC_QUIET, KERN_INFO
-			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
-		/*
-		 * legacy devices should be connected to IO APIC #0
-		 */
-		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
-		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-		unmask_IO_APIC_irq(0);
-		enable_8259A_irq(0);
-		if (timer_irq_works()) {
-			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
-			timer_through_8259 = 1;
-			if (nmi_watchdog == NMI_IO_APIC) {
-				disable_8259A_irq(0);
-				setup_nmi();
-				enable_8259A_irq(0);
-			}
-			goto out;
-		}
-		/*
-		 * Cleanup, just in case ...
-		 */
-		disable_8259A_irq(0);
-		clear_IO_APIC_pin(apic2, pin2);
-		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
-	}
-
-	if (nmi_watchdog == NMI_IO_APIC) {
-		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
-			    "through the IO-APIC - disabling NMI Watchdog!\n");
-		nmi_watchdog = NMI_NONE;
-	}
-	timer_ack = 0;
-
-	apic_printk(APIC_QUIET, KERN_INFO
-		    "...trying to set up timer as Virtual Wire IRQ...\n");
-
-	lapic_register_intr(0);
-	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
-	enable_8259A_irq(0);
-
-	if (timer_irq_works()) {
-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
-		goto out;
-	}
-	disable_8259A_irq(0);
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
-	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
-
-	apic_printk(APIC_QUIET, KERN_INFO
-		    "...trying to set up timer as ExtINT IRQ...\n");
-
-	init_8259A(0);
-	make_8259A_irq(0);
-	apic_write(APIC_LVT0, APIC_DM_EXTINT);
-
-	unlock_ExtINT_logic();
-
-	if (timer_irq_works()) {
-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
-		goto out;
-	}
-	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
-	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
-		"report.  Then try booting with the 'noapic' option.\n");
-out:
-	local_irq_restore(flags);
-}
-
-/*
- * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
- * to devices.  However there may be an I/O APIC pin available for
- * this interrupt regardless.  The pin may be left unconnected, but
- * typically it will be reused as an ExtINT cascade interrupt for
- * the master 8259A.  In the MPS case such a pin will normally be
- * reported as an ExtINT interrupt in the MP table.  With ACPI
- * there is no provision for ExtINT interrupts, and in the absence
- * of an override it would be treated as an ordinary ISA I/O APIC
- * interrupt, that is edge-triggered and unmasked by default.  We
- * used to do this, but it caused problems on some systems because
- * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
- * the same ExtINT cascade interrupt to drive the local APIC of the
- * bootstrap processor.  Therefore we refrain from routing IRQ2 to
- * the I/O APIC in all cases now.  No actual device should request
- * it anyway.  --macro
- */
-#define PIC_IRQS	(1 << PIC_CASCADE_IR)
-
-void __init setup_IO_APIC(void)
-{
-	enable_IO_APIC();
-
-	io_apic_irqs = ~PIC_IRQS;
-
-	printk("ENABLING IO-APIC IRQs\n");
-
-	/*
-	 * Set up IO-APIC IRQ routing.
-	 */
-	if (!acpi_ioapic)
-		setup_ioapic_ids_from_mpc();
-	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
-	init_IO_APIC_traps();
-	check_timer();
-}
-
-/*
- *	Called after all the initialization is done. If we didnt find any
- *	APIC bugs then we can allow the modify fast path
- */
-
-static int __init io_apic_bug_finalize(void)
-{
-	if (sis_apic_bug == -1)
-		sis_apic_bug = 0;
-	return 0;
-}
-
-late_initcall(io_apic_bug_finalize);
-
-struct sysfs_ioapic_data {
-	struct sys_device dev;
-	struct IO_APIC_route_entry entry[0];
-};
-static struct sysfs_ioapic_data *mp_ioapic_data[MAX_IO_APICS];
-
-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
-	int i;
-
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-		entry[i] = ioapic_read_entry(dev->id, i);
-
-	return 0;
-}
-
-static int ioapic_resume(struct sys_device *dev)
-{
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
-	unsigned long flags;
-	union IO_APIC_reg_00 reg_00;
-	int i;
-
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(dev->id, 0);
-	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
-		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
-		io_apic_write(dev->id, 0, reg_00.raw);
-	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-		ioapic_write_entry(dev->id, i, entry[i]);
-
-	return 0;
-}
-
-static struct sysdev_class ioapic_sysdev_class = {
-	.name = "ioapic",
-	.suspend = ioapic_suspend,
-	.resume = ioapic_resume,
-};
-
-static int __init ioapic_init_sysfs(void)
-{
-	struct sys_device *dev;
-	int i, size, error = 0;
-
-	error = sysdev_class_register(&ioapic_sysdev_class);
-	if (error)
-		return error;
-
-	for (i = 0; i < nr_ioapics; i++) {
-		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
-			* sizeof(struct IO_APIC_route_entry);
-		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
-		if (!mp_ioapic_data[i]) {
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
-		dev = &mp_ioapic_data[i]->dev;
-		dev->id = i;
-		dev->cls = &ioapic_sysdev_class;
-		error = sysdev_register(dev);
-		if (error) {
-			kfree(mp_ioapic_data[i]);
-			mp_ioapic_data[i] = NULL;
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
-	}
-
-	return 0;
-}
-
-device_initcall(ioapic_init_sysfs);
-
-/*
- * Dynamic irq allocate and deallocation
- */
-unsigned int create_irq(unsigned int irq_want)
-{
-	/* Allocate an unused irq */
-	unsigned int irq, new;
-	unsigned long flags;
-	struct irq_cfg *cfg_new;
-
-#ifndef CONFIG_HAVE_SPARSE_IRQ
-	/* only can use bus/dev/fn.. when per_cpu vector is used */
-	irq_want = nr_irqs - 1;
-#endif
-
-	irq = 0;
-	spin_lock_irqsave(&vector_lock, flags);
-	for (new = irq_want; new > 0; new--) {
-		if (platform_legacy_irq(new))
-			continue;
-		cfg_new = irq_cfg(new);
-		if (cfg_new && cfg_new->vector != 0)
-			continue;
-		/* check if need to create one */
-		if (!cfg_new)
-			cfg_new = irq_cfg_with_new(new);
-		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
-			irq = new;
-		break;
-	}
-	spin_unlock_irqrestore(&vector_lock, flags);
-
-	if (irq > 0) {
-		dynamic_irq_init(irq);
-	}
-	return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	dynamic_irq_cleanup(irq);
-
-	spin_lock_irqsave(&vector_lock, flags);
-	__clear_irq_vector(irq);
-	spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-/*
- * MSI message composition
- */
-#ifdef CONFIG_PCI_MSI
-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
-{
-	struct irq_cfg *cfg;
-	int err;
-	unsigned dest;
-	cpumask_t tmp;
-
-	tmp = TARGET_CPUS;
-	err = assign_irq_vector(irq, tmp);
-	if (err)
-		return err;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, tmp);
-	dest = cpu_mask_to_apicid(tmp);
-
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->address_lo =
-		MSI_ADDR_BASE_LO |
-		((INT_DEST_MODE == 0) ?
-			MSI_ADDR_DEST_MODE_PHYSICAL:
-			MSI_ADDR_DEST_MODE_LOGICAL) |
-		((INT_DELIVERY_MODE != dest_LowestPrio) ?
-			MSI_ADDR_REDIRECTION_CPU:
-			MSI_ADDR_REDIRECTION_LOWPRI) |
-		MSI_ADDR_DEST_ID(dest);
-
-	msg->data =
-		MSI_DATA_TRIGGER_EDGE |
-		MSI_DATA_LEVEL_ASSERT |
-		((INT_DELIVERY_MODE != dest_LowestPrio) ?
-			MSI_DATA_DELIVERY_FIXED:
-			MSI_DATA_DELIVERY_LOWPRI) |
-		MSI_DATA_VECTOR(cfg->vector);
-
-	return err;
-}
-
-#ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	struct msi_msg msg;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	read_msi_msg(irq, &msg);
-
-	msg.data &= ~MSI_DATA_VECTOR_MASK;
-	msg.data |= MSI_DATA_VECTOR(cfg->vector);
-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
-
-	write_msi_msg(irq, &msg);
-	desc->affinity = mask;
-}
-#endif /* CONFIG_SMP */
-
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
- */
-static struct irq_chip msi_chip = {
-	.name		= "PCI-MSI",
-	.unmask		= unmask_msi_irq,
-	.mask		= mask_msi_irq,
-	.ack		= ack_apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity	= set_msi_irq_affinity,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
-{
-	int ret;
-	struct msi_msg msg;
-
-	ret = msi_compose_msg(dev, irq, &msg);
-	if (ret < 0)
-		return ret;
-
-	set_irq_msi(irq, desc);
-	write_msi_msg(irq, &msg);
-
-	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
-
-	return 0;
-}
-
-static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
-{
-	unsigned int irq;
-
-	irq = dev->bus->number;
-	irq <<= 8;
-	irq |= dev->devfn;
-	irq <<= 12;
-
-	return irq;
-}
-
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
-{
-	int irq, ret;
-        unsigned int irq_want;
-
-        irq_want = build_irq_for_pci_dev(dev) + 0x100;
-
-        irq = create_irq(irq_want);
-
-	if (irq == 0)
-		return -1;
-
-	ret = setup_msi_irq(dev, desc, irq);
-	if (ret < 0) {
-		destroy_irq(irq);
-		return ret;
-        }
-
-	return 0;
-}
-
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-        unsigned int irq;
-        int ret, sub_handle;
-        struct msi_desc *desc;
-        unsigned int irq_want;
-
-        irq_want = build_irq_for_pci_dev(dev) + 0x100;
-        sub_handle = 0;
-        list_for_each_entry(desc, &dev->msi_list, list) {
-                irq = create_irq(irq_want--);
-                if (irq == 0)
-                        return -1;
-                ret = setup_msi_irq(dev, desc, irq);
-                if (ret < 0)
-                        goto error;
-                sub_handle++;
-        }
-        return 0;
-
-error:
-        destroy_irq(irq);
-        return ret;
-}
-
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
-	destroy_irq(irq);
-}
-
-#endif /* CONFIG_PCI_MSI */
-
-/*
- * Hypertransport interrupt support
- */
-#ifdef CONFIG_HT_IRQ
-
-#ifdef CONFIG_SMP
-
-static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
-{
-	struct ht_irq_msg msg;
-	fetch_ht_irq_msg(irq, &msg);
-
-	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
-	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
-
-	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
-	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
-
-	write_ht_irq_msg(irq, &msg);
-}
-
-static void set_ht_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	target_ht_irq(irq, dest, cfg->vector);
-	desc->affinity = mask;
-}
-#endif
-
-static struct irq_chip ht_irq_chip = {
-	.name		= "PCI-HT",
-	.mask		= mask_ht_irq,
-	.unmask		= unmask_ht_irq,
-	.ack		= ack_apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity	= set_ht_irq_affinity,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
-{
-	struct irq_cfg *cfg;
-	int err;
-	cpumask_t tmp;
-
-	tmp = TARGET_CPUS;
-	err = assign_irq_vector(irq, tmp);
-	if ( !err) {
-		struct ht_irq_msg msg;
-		unsigned dest;
-
-		cfg = irq_cfg(irq);
-		cpus_and(tmp, cfg->domain, tmp);
-		dest = cpu_mask_to_apicid(tmp);
-
-		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
-
-		msg.address_lo =
-			HT_IRQ_LOW_BASE |
-			HT_IRQ_LOW_DEST_ID(dest) |
-			HT_IRQ_LOW_VECTOR(cfg->vector) |
-			((INT_DEST_MODE == 0) ?
-				HT_IRQ_LOW_DM_PHYSICAL :
-				HT_IRQ_LOW_DM_LOGICAL) |
-			HT_IRQ_LOW_RQEOI_EDGE |
-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
-				HT_IRQ_LOW_MT_FIXED :
-				HT_IRQ_LOW_MT_ARBITRATED) |
-			HT_IRQ_LOW_IRQ_MASKED;
-
-		write_ht_irq_msg(irq, &msg);
-
-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
-					      handle_edge_irq, "edge");
-	}
-	return err;
-}
-#endif /* CONFIG_HT_IRQ */
-
-/* --------------------------------------------------------------------------
-			ACPI-based IOAPIC Configuration
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI
-
-int __init io_apic_get_unique_id(int ioapic, int apic_id)
-{
-	union IO_APIC_reg_00 reg_00;
-	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
-	physid_mask_t tmp;
-	unsigned long flags;
-	int i = 0;
-
-	/*
-	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
-	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
-	 * supports up to 16 on one shared APIC bus.
-	 *
-	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
-	 *      advantage of new APIC bus architecture.
-	 */
-
-	if (physids_empty(apic_id_map))
-		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(ioapic, 0);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	if (apic_id >= get_physical_broadcast()) {
-		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
-			"%d\n", ioapic, apic_id, reg_00.bits.ID);
-		apic_id = reg_00.bits.ID;
-	}
-
-	/*
-	 * Every APIC in a system must have a unique ID or we get lots of nice
-	 * 'stuck on smp_invalidate_needed IPI wait' messages.
-	 */
-	if (check_apicid_used(apic_id_map, apic_id)) {
-
-		for (i = 0; i < get_physical_broadcast(); i++) {
-			if (!check_apicid_used(apic_id_map, i))
-				break;
-		}
-
-		if (i == get_physical_broadcast())
-			panic("Max apic_id exceeded!\n");
-
-		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
-			"trying %d\n", ioapic, apic_id, i);
-
-		apic_id = i;
-	}
-
-	tmp = apicid_to_cpu_present(apic_id);
-	physids_or(apic_id_map, apic_id_map, tmp);
-
-	if (reg_00.bits.ID != apic_id) {
-		reg_00.bits.ID = apic_id;
-
-		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(ioapic, 0, reg_00.raw);
-		reg_00.raw = io_apic_read(ioapic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-
-		/* Sanity check */
-		if (reg_00.bits.ID != apic_id) {
-			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
-			return -1;
-		}
-	}
-
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
-
-	return apic_id;
-}
-
-
-int __init io_apic_get_version(int ioapic)
-{
-	union IO_APIC_reg_01	reg_01;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return reg_01.bits.version;
-}
-
-
-int __init io_apic_get_redir_entries(int ioapic)
-{
-	union IO_APIC_reg_01	reg_01;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return reg_01.bits.entries;
-}
-
-
-int io_apic_set_pci_routing(int ioapic, int pin, int irq, int triggering, int polarity)
-{
-	if (!IO_APIC_IRQ(irq)) {
-		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
-			ioapic);
-		return -EINVAL;
-	}
-
-	/*
-	 * IRQs < 16 are already in the irq_2_pin[] map
-	 */
-	if (irq >= 16)
-		add_pin_to_irq(irq, ioapic, pin);
-
-	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
-
-	return 0;
-}
-
-int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
-{
-	int i;
-
-	if (skip_ioapic_setup)
-		return -1;
-
-	for (i = 0; i < mp_irq_entries; i++)
-		if (mp_irqs[i].mp_irqtype == mp_INT &&
-		    mp_irqs[i].mp_srcbusirq == bus_irq)
-			break;
-	if (i >= mp_irq_entries)
-		return -1;
-
-	*trigger = irq_trigger(i);
-	*polarity = irq_polarity(i);
-	return 0;
-}
-
-#endif /* CONFIG_ACPI */
-
-/*
- * This function currently is only a helper for the i386 smp boot process where
- * we need to reprogram the ioredtbls to cater for the cpus which have come online
- * so mask in all cases should simply be TARGET_CPUS
- */
-#ifdef CONFIG_SMP
-void __init setup_ioapic_dest(void)
-{
-	int pin, ioapic, irq, irq_entry;
-	struct irq_cfg *cfg;
-	struct irq_desc *desc;
-
-	if (skip_ioapic_setup == 1)
-		return;
-
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
-			if (irq_entry == -1)
-				continue;
-			irq = pin_2_irq(irq_entry, ioapic, pin);
-
-			/* setup_IO_APIC_irqs could fail to get vector for some device
-			 * when you have too many devices, because at that time only boot
-			 * cpu is online.
-			 */
-			cfg = irq_cfg(irq);
-			if (!cfg->vector)
-				setup_IO_APIC_irq(ioapic, pin, irq,
-						  irq_trigger(irq_entry),
-						  irq_polarity(irq_entry));
-			else {
-				desc = irq_desc(irq);
-				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-			}
-		}
-
-	}
-}
-#endif
-
-void __init ioapic_init_mappings(void)
-{
-	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-	int i;
-
-	for (i = 0; i < nr_ioapics; i++) {
-		if (smp_found_config) {
-			ioapic_phys = mp_ioapics[i].mp_apicaddr;
-			if (!ioapic_phys) {
-				printk(KERN_ERR
-				       "WARNING: bogus zero IO-APIC "
-				       "address found in MPTABLE, "
-				       "disabling IO/APIC support!\n");
-				smp_found_config = 0;
-				skip_ioapic_setup = 1;
-				goto fake_ioapic_page;
-			}
-		} else {
-fake_ioapic_page:
-			ioapic_phys = (unsigned long)
-				      alloc_bootmem_pages(PAGE_SIZE);
-			ioapic_phys = __pa(ioapic_phys);
-		}
-		set_fixmap_nocache(idx, ioapic_phys);
-		printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
-		       __fix_to_virt(idx), ioapic_phys);
-		idx++;
-	}
-}
-
Index: linux-2.6/arch/x86/kernel/io_apic_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic_64.c
+++ /dev/null
@@ -1,3896 +0,0 @@
-/*
- *	Intel IO-APIC support for multi-Pentium hosts.
- *
- *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
- *
- *	Many thanks to Stig Venaas for trying out countless experimental
- *	patches and reporting/debugging problems patiently!
- *
- *	(c) 1999, Multiple IO-APIC support, developed by
- *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
- *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
- *	further tested and cleaned up by Zach Brown <zab@redhat.com>
- *	and Ingo Molnar <mingo@redhat.com>
- *
- *	Fixes
- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
- *					thanks to Eric Gilmore
- *					and Rolf G. Tews
- *					for testing these extensively
- *	Paul Diefenbaugh	:	Added full ACPI support
- */
-
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/mc146818rtc.h>
-#include <linux/compiler.h>
-#include <linux/acpi.h>
-#include <linux/module.h>
-#include <linux/sysdev.h>
-#include <linux/msi.h>
-#include <linux/htirq.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
-#include <linux/jiffies.h>	/* time_after() */
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#endif
-#include <linux/bootmem.h>
-#include <linux/dmar.h>
-
-#include <asm/idle.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/desc.h>
-#include <asm/proto.h>
-#include <asm/acpi.h>
-#include <asm/dma.h>
-#include <asm/timer.h>
-#include <asm/i8259.h>
-#include <asm/nmi.h>
-#include <asm/msidef.h>
-#include <asm/hypertransport.h>
-#include <asm/setup.h>
-#include <asm/irq_remapping.h>
-
-#include <mach_ipi.h>
-#include <mach_apic.h>
-#include <mach_apicdef.h>
-
-#define __apicdebuginit(type) static type __init
-
-/*
- *      Is the SiS APIC rmw bug present ?
- *      -1 = don't know, 0 = no, 1 = yes
- */
-int sis_apic_bug = -1;
-
-static DEFINE_SPINLOCK(ioapic_lock);
-static DEFINE_SPINLOCK(vector_lock);
-
-int first_free_entry;
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-int pin_map_size;
-
-/*
- * # of IRQ routing registers
- */
-int nr_ioapic_registers[MAX_IO_APICS];
-
-/* I/O APIC entries */
-struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
-int nr_ioapics;
-
-/* MP IRQ source entries */
-struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-
-/* # of MP IRQ source entries */
-int mp_irq_entries;
-
-#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
-int mp_bus_id_to_type[MAX_MP_BUSSES];
-#endif
-
-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
-
-int skip_ioapic_setup;
-
-static int __init parse_noapic(char *str)
-{
-	/* disable IO-APIC */
-	disable_ioapic_setup();
-	return 0;
-}
-early_param("noapic", parse_noapic);
-
-struct irq_cfg;
-struct irq_pin_list;
-struct irq_cfg {
-	unsigned int irq;
-	struct irq_cfg *next;
-	struct irq_pin_list *irq_2_pin;
-	cpumask_t domain;
-	cpumask_t old_domain;
-	unsigned move_cleanup_count;
-	u8 vector;
-	u8 move_in_progress : 1;
-};
-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfg_legacy[] __initdata = {
-	[0]  = { .irq =  0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
-	[1]  = { .irq =  1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
-	[2]  = { .irq =  2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
-	[3]  = { .irq =  3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR,  },
-	[4]  = { .irq =  4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR,  },
-	[5]  = { .irq =  5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR,  },
-	[6]  = { .irq =  6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR,  },
-	[7]  = { .irq =  7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR,  },
-	[8]  = { .irq =  8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR,  },
-	[9]  = { .irq =  9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR,  },
-	[10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
-	[11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
-	[12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
-	[13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
-	[14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
-	[15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
-};
-
-static struct irq_cfg irq_cfg_init = { .irq =  -1U, };
-/* need to be biger than size of irq_cfg_legacy */
-static int nr_irq_cfg = 32;
-
-static int __init parse_nr_irq_cfg(char *arg)
-{
-	if (arg) {
-		nr_irq_cfg = simple_strtoul(arg, NULL, 0);
-		if (nr_irq_cfg < 32)
-			nr_irq_cfg = 32;
-	}
-	return 0;
-}
-
-early_param("nr_irq_cfg", parse_nr_irq_cfg);
-
-static void init_one_irq_cfg(struct irq_cfg *cfg)
-{
-	memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
-}
-
-static struct irq_cfg *irq_cfgx;
-static struct irq_cfg *irq_cfgx_free;
-static void __init init_work(void *data)
-{
-	struct dyn_array *da = data;
-	struct irq_cfg *cfg;
-	int legacy_count;
-	int i;
-
-	cfg = *da->name;
-
-	memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
-
-	legacy_count = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
-	for (i = legacy_count; i < *da->nr; i++)
-		init_one_irq_cfg(&cfg[i]);
-
-	for (i = 1; i < *da->nr; i++)
-		cfg[i-1].next = &cfg[i];
-
-	irq_cfgx_free = &irq_cfgx[legacy_count];
-	irq_cfgx[legacy_count - 1].next = NULL;
-}
-
-#define for_each_irq_cfg(cfg)		\
-	for (cfg = irq_cfgx; cfg; cfg = cfg->next)
-
-DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
-
-static struct irq_cfg *irq_cfg(unsigned int irq)
-{
-	struct irq_cfg *cfg;
-
-	cfg = irq_cfgx;
-	while (cfg) {
-		if (cfg->irq == irq)
-			return cfg;
-
-		cfg = cfg->next;
-	}
-
-	return NULL;
-}
-
-static struct irq_cfg *irq_cfg_with_new(unsigned int irq)
-{
-	struct irq_cfg *cfg, *cfg_pri;
-	int i;
-	int count = 0;
-
-	cfg_pri = cfg = irq_cfgx;
-	while (cfg) {
-		if (cfg->irq == irq)
-			return cfg;
-
-		cfg_pri = cfg;
-		cfg = cfg->next;
-		count++;
-	}
-
-	if (!irq_cfgx_free) {
-		unsigned long phys;
-		unsigned long total_bytes;
-		/*
-		 *  we run out of pre-allocate ones, allocate more
-		 */
-		printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
-
-		total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
-		if (after_bootmem)
-			cfg = kzalloc(total_bytes, GFP_ATOMIC);
-		else
-			cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
-
-		if (!cfg)
-			panic("please boot with nr_irq_cfg= %d\n", count * 2);
-
-		phys = __pa(cfg);
-		printk(KERN_DEBUG "irq_irq ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
-
-		for (i = 0; i < nr_irq_cfg; i++)
-			init_one_irq_cfg(&cfg[i]);
-
-		for (i = 1; i < nr_irq_cfg; i++)
-			cfg[i-1].next = &cfg[i];
-
-		irq_cfgx_free = cfg;
-	}
-
-	cfg = irq_cfgx_free;
-	irq_cfgx_free = irq_cfgx_free->next;
-	cfg->next = NULL;
-	if (cfg_pri)
-		cfg_pri->next = cfg;
-	else
-		irq_cfgx = cfg;
-	cfg->irq = irq;
-	printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
-#ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
-	{
-		/* dump the results */
-		struct irq_cfg *cfg;
-		unsigned long phys;
-		unsigned long bytes = sizeof(struct irq_cfg);
-
-		printk(KERN_DEBUG "=========================== %d\n", irq);
-		printk(KERN_DEBUG "irq_cfg dump after get that for %d\n", irq);
-		for_each_irq_cfg(cfg) {
-			phys = __pa(cfg);
-			printk(KERN_DEBUG "irq_cfg %d ==> [%#lx - %#lx]\n", cfg->irq, phys, phys + bytes);
-		}
-		printk(KERN_DEBUG "===========================\n");
-	}
-#endif
-	return cfg;
-}
-
-/*
- * This is performance-critical, we want to do it O(1)
- *
- * the indexing order of this array favors 1:1 mappings
- * between pins and IRQs.
- */
-
-struct irq_pin_list {
-	int apic, pin;
-	struct irq_pin_list *next;
-};
-
-static struct irq_pin_list *irq_2_pin_head;
-/* fill one page ? */
-static int nr_irq_2_pin = 0x100;
-static struct irq_pin_list *irq_2_pin_ptr;
-static void __init irq_2_pin_init_work(void *data)
-{
-	struct dyn_array *da = data;
-	struct irq_pin_list *pin;
-	int i;
-
-	pin = *da->name;
-
-	for (i = 1; i < *da->nr; i++)
-		pin[i-1].next = &pin[i];
-
-	irq_2_pin_ptr = &pin[0];
-}
-DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
-
-static struct irq_pin_list *get_one_free_irq_2_pin(void)
-{
-	struct irq_pin_list *pin;
-	int i;
-
-	pin = irq_2_pin_ptr;
-
-	if (pin) {
-		irq_2_pin_ptr = pin->next;
-		pin->next = NULL;
-		return pin;
-	}
-
-	/*
-	 *  we run out of pre-allocate ones, allocate more
-	 */
-	printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
-
-	if (after_bootmem)
-		pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
-				 GFP_ATOMIC);
-	else
-		pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
-				nr_irq_2_pin, PAGE_SIZE, 0);
-
-	if (!pin)
-		panic("can not get more irq_2_pin\n");
-
-	for (i = 1; i < nr_irq_2_pin; i++)
-		pin[i-1].next = &pin[i];
-
-	irq_2_pin_ptr = pin->next;
-	pin->next = NULL;
-
-	return pin;
-}
-
-struct io_apic {
-	unsigned int index;
-	unsigned int unused[3];
-	unsigned int data;
-};
-
-static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
-{
-	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
-		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
-}
-
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	writel(reg, &io_apic->index);
-	return readl(&io_apic->data);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	writel(reg, &io_apic->index);
-	writel(value, &io_apic->data);
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- *
- * Older SiS APIC requires we rewrite the index register
- */
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-        if (sis_apic_bug)
-                writel(reg, &io_apic->index);
-	writel(value, &io_apic->data);
-}
-
-#ifdef CONFIG_X86_64
-static bool io_apic_level_ack_pending(unsigned int irq)
-{
-	struct irq_pin_list *entry;
-	unsigned long flags;
-	struct irq_cfg *cfg = irq_cfg(irq);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		unsigned int reg;
-		int pin;
-
-		if (!entry)
-			break;
-		pin = entry->pin;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		/* Is the remote IRR bit set? */
-		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
-			spin_unlock_irqrestore(&ioapic_lock, flags);
-			return true;
-		}
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return false;
-}
-#endif
-
-union entry_union {
-	struct { u32 w1, w2; };
-	struct IO_APIC_route_entry entry;
-};
-
-static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
-{
-	union entry_union eu;
-	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-	return eu.entry;
-}
-
-/*
- * When we write a new IO APIC routing entry, we need to write the high
- * word first! If the mask bit in the low word is clear, we will enable
- * the interrupt, and we need to make sure the entry is fully populated
- * before that happens.
- */
-static void
-__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
-{
-	union entry_union eu;
-	eu.entry = e;
-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
-}
-
-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__ioapic_write_entry(apic, pin, e);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-/*
- * When we mask an IO APIC routing entry, we need to write the low
- * word first, in order to set the mask bit before we change the
- * high bits!
- */
-static void ioapic_mask_entry(int apic, int pin)
-{
-	unsigned long flags;
-	union entry_union eu = { .entry.mask = 1 };
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-#ifdef CONFIG_SMP
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
-{
-	int apic, pin;
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-
-	cfg = irq_cfg(irq);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		unsigned int reg;
-
-		if (!entry)
-			break;
-
-		apic = entry->apic;
-		pin = entry->pin;
-#ifdef CONFIG_INTR_REMAP
-		/*
-		 * With interrupt-remapping, destination information comes
-		 * from interrupt-remapping table entry.
-		 */
-		if (!irq_remapped(irq))
-			io_apic_write(apic, 0x11 + pin*2, dest);
-#else
-		io_apic_write(apic, 0x11 + pin*2, dest);
-#endif
-		reg = io_apic_read(apic, 0x10 + pin*2);
-		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
-		reg |= vector;
-		io_apic_modify(apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-}
-
-static int assign_irq_vector(int irq, cpumask_t mask);
-
-static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	unsigned long flags;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	cfg = irq_cfg(irq);
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-	/*
-	 * Only the high 8 bits are valid.
-	 */
-	dest = SET_APIC_LOGICAL_ID(dest);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__target_IO_APIC_irq(irq, dest, cfg->vector);
-	desc->affinity = mask;
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-#endif /* CONFIG_SMP */
-
-/*
- * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
- * shared ISA-space IRQs, so we have to support them. We are super
- * fast in the common case, and fast for shared ISA-space IRQs.
- */
-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
-{
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-
-	/* first time to refer irq_cfg, so with new */
-	cfg = irq_cfg_with_new(irq);
-	entry = cfg->irq_2_pin;
-	if (!entry) {
-		entry = get_one_free_irq_2_pin();
-		cfg->irq_2_pin = entry;
-		entry->apic = apic;
-		entry->pin = pin;
-		printk(KERN_DEBUG " 0 add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
-		return;
-	}
-
-	while (entry->next) {
-		/* not again, please */
-		if (entry->apic == apic && entry->pin == pin)
-			return;
-
-		entry = entry->next;
-	}
-
-	entry->next = get_one_free_irq_2_pin();
-	entry = entry->next;
-	entry->apic = apic;
-	entry->pin = pin;
-	printk(KERN_DEBUG " x add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
-}
-
-/*
- * Reroute an IRQ to a different pin.
- */
-static void __init replace_pin_at_irq(unsigned int irq,
-				      int oldapic, int oldpin,
-				      int newapic, int newpin)
-{
-	struct irq_cfg *cfg = irq_cfg(irq);
-	struct irq_pin_list *entry = cfg->irq_2_pin;
-	int replaced = 0;
-
-	while (entry) {
-		if (entry->apic == oldapic && entry->pin == oldpin) {
-			entry->apic = newapic;
-			entry->pin = newpin;
-			replaced = 1;
-			/* every one is different, right? */
-			break;
-		}
-		entry = entry->next;
-	}
-
-	/* why? call replace before add? */
-	if (!replaced)
-		add_pin_to_irq(irq, newapic, newpin);
-}
-
-#ifdef CONFIG_X86_64
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
-	struct io_apic __iomem *io_apic = io_apic_base(apic);
-	readl(&io_apic->data);
-}
-
-#define __DO_ACTION(R, ACTION, FINAL)					\
-									\
-{									\
-	int pin;							\
-	struct irq_cfg *cfg;						\
-	struct irq_pin_list *entry;					\
-									\
-	cfg = irq_cfg(irq);						\
-	entry = cfg->irq_2_pin;						\
-	for (;;) {							\
-		unsigned int reg;					\
-		if (!entry)						\
-			break;						\
-		pin = entry->pin;					\
-		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
-		reg ACTION;						\
-		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
-		FINAL;							\
-		if (!entry->next)					\
-			break;						\
-		entry = entry->next;					\
-	}								\
-}
-
-#define DO_ACTION(name,R,ACTION, FINAL)					\
-									\
-	static void name##_IO_APIC_irq (unsigned int irq)		\
-	__DO_ACTION(R, ACTION, FINAL)
-
-/* mask = 1 */
-DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
-
-/* mask = 0 */
-DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
-
-#else
-
-static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
-{
-	struct irq_cfg *cfg;
-	struct irq_pin_list *entry;
-	unsigned int pin, reg;
-
-	cfg = irq_cfg(irq);
-	entry = cfg->irq_2_pin;
-	for (;;) {
-		if (!entry)
-			break;
-		pin = entry->pin;
-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
-		reg &= ~disable;
-		reg |= enable;
-		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
-		if (!entry->next)
-			break;
-		entry = entry->next;
-	}
-}
-
-/* mask = 1 */
-static void __mask_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
-}
-
-/* mask = 0 */
-static void __unmask_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
-}
-
-/* mask = 1, trigger = 0 */
-static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
-				IO_APIC_REDIR_LEVEL_TRIGGER);
-}
-
-/* mask = 0, trigger = 1 */
-static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
-{
-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
-				IO_APIC_REDIR_MASKED);
-}
-
-#endif
-
-static void mask_IO_APIC_irq (unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__mask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void unmask_IO_APIC_irq (unsigned int irq)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	__unmask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-}
-
-static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
-{
-	struct IO_APIC_route_entry entry;
-
-	/* Check delivery_mode to be sure we're not clearing an SMI pin */
-	entry = ioapic_read_entry(apic, pin);
-	if (entry.delivery_mode == dest_SMI)
-		return;
-	/*
-	 * Disable it in the IO-APIC irq-routing table:
-	 */
-	ioapic_mask_entry(apic, pin);
-}
-
-static void clear_IO_APIC (void)
-{
-	int apic, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
-			clear_IO_APIC_pin(apic, pin);
-}
-
-#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
-void send_IPI_self(int vector)
-{
-	unsigned int cfg;
-
-	/*
-	 * Wait for idle.
-	 */
-	apic_wait_icr_idle();
-	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
-	/*
-	 * Send the IPI. The write to APIC_ICR fires this off.
-	 */
-	apic_write(APIC_ICR, cfg);
-}
-#endif /* !CONFIG_SMP && CONFIG_X86_32*/
-
-#ifdef CONFIG_X86_32
-/*
- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
- * specific CPU-side IRQs.
- */
-
-#define MAX_PIRQS 8
-static int pirq_entries [MAX_PIRQS];
-static int pirqs_enabled;
-
-static int __init ioapic_pirq_setup(char *str)
-{
-	int i, max;
-	int ints[MAX_PIRQS+1];
-
-	get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0; i < MAX_PIRQS; i++)
-		pirq_entries[i] = -1;
-
-	pirqs_enabled = 1;
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"PIRQ redirection, working around broken MP-BIOS.\n");
-	max = MAX_PIRQS;
-	if (ints[0] < MAX_PIRQS)
-		max = ints[0];
-
-	for (i = 0; i < max; i++) {
-		apic_printk(APIC_VERBOSE, KERN_DEBUG
-				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
-		/*
-		 * PIRQs are mapped upside down, usually.
-		 */
-		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
-	}
-	return 1;
-}
-
-__setup("pirq=", ioapic_pirq_setup);
-#endif /* CONFIG_X86_32 */
-
-#ifdef CONFIG_INTR_REMAP
-/* I/O APIC RTE contents at the OS boot up */
-static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
-
-/*
- * Saves and masks all the unmasked IO-APIC RTE's
- */
-int save_mask_IO_APIC_setup(void)
-{
-	union IO_APIC_reg_01 reg_01;
-	unsigned long flags;
-	int apic, pin;
-
-	/*
-	 * The number of IO-APIC IRQ registers (== #pins):
-	 */
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_01.raw = io_apic_read(apic, 1);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
-	}
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		early_ioapic_entries[apic] =
-			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				nr_ioapic_registers[apic], GFP_KERNEL);
-		if (!early_ioapic_entries[apic])
-			return -ENOMEM;
-	}
-
-	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			struct IO_APIC_route_entry entry;
-
-			entry = early_ioapic_entries[apic][pin] =
-				ioapic_read_entry(apic, pin);
-			if (!entry.mask) {
-				entry.mask = 1;
-				ioapic_write_entry(apic, pin, entry);
-			}
-		}
-	return 0;
-}
-
-void restore_IO_APIC_setup(void)
-{
-	int apic, pin;
-
-	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
-			ioapic_write_entry(apic, pin,
-					   early_ioapic_entries[apic][pin]);
-}
-
-void reinit_intr_remapped_IO_APIC(int intr_remapping)
-{
-	/*
-	 * for now plain restore of previous settings.
-	 * TBD: In the case of OS enabling interrupt-remapping,
-	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
-	 * table entries. for now, do a plain restore, and wait for
-	 * the setup_IO_APIC_irqs() to do proper initialization.
-	 */
-	restore_IO_APIC_setup();
-}
-#endif
-
-/*
- * Find the IRQ entry number of a certain pin.
- */
-static int find_irq_entry(int apic, int pin, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++)
-		if (mp_irqs[i].mp_irqtype == type &&
-		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
-		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
-		    mp_irqs[i].mp_dstirq == pin)
-			return i;
-
-	return -1;
-}
-
-/*
- * Find the pin to which IRQ[irq] (ISA) is connected
- */
-static int __init find_isa_irq_pin(int irq, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		if (test_bit(lbus, mp_bus_not_pci) &&
-		    (mp_irqs[i].mp_irqtype == type) &&
-		    (mp_irqs[i].mp_srcbusirq == irq))
-
-			return mp_irqs[i].mp_dstirq;
-	}
-	return -1;
-}
-
-static int __init find_isa_irq_apic(int irq, int type)
-{
-	int i;
-
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		if (test_bit(lbus, mp_bus_not_pci) &&
-		    (mp_irqs[i].mp_irqtype == type) &&
-		    (mp_irqs[i].mp_srcbusirq == irq))
-			break;
-	}
-	if (i < mp_irq_entries) {
-		int apic;
-		for(apic = 0; apic < nr_ioapics; apic++) {
-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
-				return apic;
-		}
-	}
-
-	return -1;
-}
-
-/*
- * Find a specific PCI IRQ entry.
- * Not an __init, possibly needed by modules
- */
-static int pin_2_irq(int idx, int apic, int pin);
-
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
-{
-	int apic, i, best_guess = -1;
-
-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
-		bus, slot, pin);
-	if (test_bit(bus, mp_bus_not_pci)) {
-		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
-		return -1;
-	}
-	for (i = 0; i < mp_irq_entries; i++) {
-		int lbus = mp_irqs[i].mp_srcbus;
-
-		for (apic = 0; apic < nr_ioapics; apic++)
-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
-			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
-				break;
-
-		if (!test_bit(lbus, mp_bus_not_pci) &&
-		    !mp_irqs[i].mp_irqtype &&
-		    (bus == lbus) &&
-		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
-
-			if (!(apic || IO_APIC_IRQ(irq)))
-				continue;
-
-			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
-				return irq;
-			/*
-			 * Use the first all-but-pin matching entry as a
-			 * best-guess fuzzy result for broken mptables.
-			 */
-			if (best_guess < 0)
-				best_guess = irq;
-		}
-	}
-	return best_guess;
-}
-
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
-/*
- * EISA Edge/Level control register, ELCR
- */
-static int EISA_ELCR(unsigned int irq)
-{
-	if (irq < 16) {
-		unsigned int port = 0x4d0 + (irq >> 3);
-		return (inb(port) >> (irq & 7)) & 1;
-	}
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"Broken MPtable reports ISA irq %d\n", irq);
-	return 0;
-}
-
-#endif
-
-/* ISA interrupts are always polarity zero edge triggered,
- * when listed as conforming in the MP table. */
-
-#define default_ISA_trigger(idx)	(0)
-#define default_ISA_polarity(idx)	(0)
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value.  If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
-#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
-
-/* PCI interrupts are always polarity one level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_PCI_trigger(idx)	(1)
-#define default_PCI_polarity(idx)	(1)
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value.  If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
-#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
-
-
-static int MPBIOS_polarity(int idx)
-{
-	int bus = mp_irqs[idx].mp_srcbus;
-	int polarity;
-
-	/*
-	 * Determine IRQ line polarity (high active or low active):
-	 */
-	switch (mp_irqs[idx].mp_irqflag & 3)
-	{
-		case 0: /* conforms, ie. bus-type dependent polarity */
-			if (test_bit(bus, mp_bus_not_pci))
-				polarity = default_ISA_polarity(idx);
-			else
-				polarity = default_PCI_polarity(idx);
-			break;
-		case 1: /* high active */
-		{
-			polarity = 0;
-			break;
-		}
-		case 2: /* reserved */
-		{
-			printk(KERN_WARNING "broken BIOS!!\n");
-			polarity = 1;
-			break;
-		}
-		case 3: /* low active */
-		{
-			polarity = 1;
-			break;
-		}
-		default: /* invalid */
-		{
-			printk(KERN_WARNING "broken BIOS!!\n");
-			polarity = 1;
-			break;
-		}
-	}
-	return polarity;
-}
-
-static int MPBIOS_trigger(int idx)
-{
-	int bus = mp_irqs[idx].mp_srcbus;
-	int trigger;
-
-	/*
-	 * Determine IRQ trigger mode (edge or level sensitive):
-	 */
-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
-	{
-		case 0: /* conforms, ie. bus-type dependent */
-			if (test_bit(bus, mp_bus_not_pci))
-				trigger = default_ISA_trigger(idx);
-			else
-				trigger = default_PCI_trigger(idx);
-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
-			switch (mp_bus_id_to_type[bus]) {
-				case MP_BUS_ISA: /* ISA pin */
-				{
-					/* set before the switch */
-					break;
-				}
-				case MP_BUS_EISA: /* EISA pin */
-				{
-					trigger = default_EISA_trigger(idx);
-					break;
-				}
-				case MP_BUS_PCI: /* PCI pin */
-				{
-					/* set before the switch */
-					break;
-				}
-				case MP_BUS_MCA: /* MCA pin */
-				{
-					trigger = default_MCA_trigger(idx);
-					break;
-				}
-				default:
-				{
-					printk(KERN_WARNING "broken BIOS!!\n");
-					trigger = 1;
-					break;
-				}
-			}
-#endif
-			break;
-		case 1: /* edge */
-		{
-			trigger = 0;
-			break;
-		}
-		case 2: /* reserved */
-		{
-			printk(KERN_WARNING "broken BIOS!!\n");
-			trigger = 1;
-			break;
-		}
-		case 3: /* level */
-		{
-			trigger = 1;
-			break;
-		}
-		default: /* invalid */
-		{
-			printk(KERN_WARNING "broken BIOS!!\n");
-			trigger = 0;
-			break;
-		}
-	}
-	return trigger;
-}
-
-static inline int irq_polarity(int idx)
-{
-	return MPBIOS_polarity(idx);
-}
-
-static inline int irq_trigger(int idx)
-{
-	return MPBIOS_trigger(idx);
-}
-
-int (*ioapic_renumber_irq)(int ioapic, int irq);
-static int pin_2_irq(int idx, int apic, int pin)
-{
-	int irq, i;
-	int bus = mp_irqs[idx].mp_srcbus;
-
-	/*
-	 * Debugging check, we are in big trouble if this message pops up!
-	 */
-	if (mp_irqs[idx].mp_dstirq != pin)
-		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
-
-	if (test_bit(bus, mp_bus_not_pci)) {
-		irq = mp_irqs[idx].mp_srcbusirq;
-	} else {
-		/*
-		 * PCI IRQs are mapped in order
-		 */
-		i = irq = 0;
-		while (i < apic)
-			irq += nr_ioapic_registers[i++];
-		irq += pin;
-                /*
-                 * For MPS mode, so far only needed by ES7000 platform
-                 */
-                if (ioapic_renumber_irq)
-                        irq = ioapic_renumber_irq(apic, irq);
-	}
-
-#ifdef CONFIG_X86_32
-	/*
-	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
-	 */
-	if ((pin >= 16) && (pin <= 23)) {
-		if (pirq_entries[pin-16] != -1) {
-			if (!pirq_entries[pin-16]) {
-				apic_printk(APIC_VERBOSE, KERN_DEBUG
-						"disabling PIRQ%d\n", pin-16);
-			} else {
-				irq = pirq_entries[pin-16];
-				apic_printk(APIC_VERBOSE, KERN_DEBUG
-						"using PIRQ%d -> IRQ %d\n",
-						pin-16, irq);
-			}
-		}
-	}
-#endif
-
-	return irq;
-}
-
-void lock_vector_lock(void)
-{
-	/* Used to the online set of cpus does not change
-	 * during assign_irq_vector.
-	 */
-	spin_lock(&vector_lock);
-}
-
-void unlock_vector_lock(void)
-{
-	spin_unlock(&vector_lock);
-}
-
-static int __assign_irq_vector(int irq, cpumask_t mask)
-{
-	/*
-	 * NOTE! The local APIC isn't very good at handling
-	 * multiple interrupts at the same interrupt level.
-	 * As the interrupt level is determined by taking the
-	 * vector number and shifting that right by 4, we
-	 * want to spread these out a bit so that they don't
-	 * all fall in the same interrupt level.
-	 *
-	 * Also, we've got to be careful not to trash gate
-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
-	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
-	unsigned int old_vector;
-	int cpu;
-	struct irq_cfg *cfg;
-
-	cfg = irq_cfg(irq);
-
-	/* Only try and allocate irqs on cpus that are present */
-	cpus_and(mask, mask, cpu_online_map);
-
-	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
-		return -EBUSY;
-
-	old_vector = cfg->vector;
-	if (old_vector) {
-		cpumask_t tmp;
-		cpus_and(tmp, cfg->domain, mask);
-		if (!cpus_empty(tmp))
-			return 0;
-	}
-
-	for_each_cpu_mask_nr(cpu, mask) {
-		cpumask_t domain, new_mask;
-		int new_cpu;
-		int vector, offset;
-
-		domain = vector_allocation_domain(cpu);
-		cpus_and(new_mask, domain, cpu_online_map);
-
-		vector = current_vector;
-		offset = current_offset;
-next:
-		vector += 8;
-		if (vector >= first_system_vector) {
-			/* If we run out of vectors on large boxen, must share them. */
-			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
-		}
-		if (unlikely(current_vector == vector))
-			continue;
-#ifdef CONFIG_X86_64
-		if (vector == IA32_SYSCALL_VECTOR)
-			goto next;
-#else
-		if (vector == SYSCALL_VECTOR)
-			goto next;
-#endif
-		for_each_cpu_mask_nr(new_cpu, new_mask)
-			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
-				goto next;
-		/* Found one! */
-		current_vector = vector;
-		current_offset = offset;
-		if (old_vector) {
-			cfg->move_in_progress = 1;
-			cfg->old_domain = cfg->domain;
-		}
-		for_each_cpu_mask_nr(new_cpu, new_mask)
-			per_cpu(vector_irq, new_cpu)[vector] = irq;
-		cfg->vector = vector;
-		cfg->domain = domain;
-		return 0;
-	}
-	return -ENOSPC;
-}
-
-static int assign_irq_vector(int irq, cpumask_t mask)
-{
-	int err;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vector_lock, flags);
-	err = __assign_irq_vector(irq, mask);
-	spin_unlock_irqrestore(&vector_lock, flags);
-	return err;
-}
-
-static void __clear_irq_vector(int irq)
-{
-	struct irq_cfg *cfg;
-	cpumask_t mask;
-	int cpu, vector;
-
-	cfg = irq_cfg(irq);
-	BUG_ON(!cfg->vector);
-
-	vector = cfg->vector;
-	cpus_and(mask, cfg->domain, cpu_online_map);
-	for_each_cpu_mask_nr(cpu, mask)
-		per_cpu(vector_irq, cpu)[vector] = -1;
-
-	cfg->vector = 0;
-	cpus_clear(cfg->domain);
-}
-
-void __setup_vector_irq(int cpu)
-{
-	/* Initialize vector_irq on a new cpu */
-	/* This function must be called with vector_lock held */
-	int irq, vector;
-	struct irq_cfg *cfg;
-
-	/* Mark the inuse vectors */
-	for_each_irq_cfg(cfg) {
-		if (!cpu_isset(cpu, cfg->domain))
-			continue;
-		vector = cfg->vector;
-		irq = cfg->irq;
-		per_cpu(vector_irq, cpu)[vector] = irq;
-	}
-	/* Mark the free vectors */
-	for (vector = 0; vector < NR_VECTORS; ++vector) {
-		irq = per_cpu(vector_irq, cpu)[vector];
-		if (irq < 0)
-			continue;
-
-		cfg = irq_cfg(irq);
-		if (!cpu_isset(cpu, cfg->domain))
-			per_cpu(vector_irq, cpu)[vector] = -1;
-	}
-}
-
-static struct irq_chip ioapic_chip;
-#ifdef CONFIG_INTR_REMAP
-static struct irq_chip ir_ioapic_chip;
-#endif
-
-#define IOAPIC_AUTO     -1
-#define IOAPIC_EDGE     0
-#define IOAPIC_LEVEL    1
-
-#ifdef CONFIG_X86_32
-static inline int IO_APIC_irq_trigger(int irq)
-{
-        int apic, idx, pin;
-
-        for (apic = 0; apic < nr_ioapics; apic++) {
-                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-                        idx = find_irq_entry(apic, pin, mp_INT);
-                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-                                return irq_trigger(idx);
-                }
-        }
-        /*
-         * nonexistent IRQs are edge default
-         */
-        return 0;
-}
-#else
-static inline int IO_APIC_irq_trigger(int irq)
-{
-	return 1;
-}
-#endif
-
-static void ioapic_register_intr(int irq, unsigned long trigger)
-{
-	struct irq_desc *desc;
-
-	/* first time to use this irq_desc */
-	if (irq < 16)
-		desc = irq_desc(irq);
-	else
-		desc = irq_desc_with_new(irq);
-
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		desc->status |= IRQ_LEVEL;
-	else
-		desc->status &= ~IRQ_LEVEL;
-
-#ifdef CONFIG_INTR_REMAP
-	if (irq_remapped(irq)) {
-		desc->status |= IRQ_MOVE_PCNTXT;
-		if (trigger)
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_fasteoi_irq,
-						     "fasteoi");
-		else
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_edge_irq, "edge");
-		return;
-	}
-#endif
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_fasteoi_irq,
-					      "fasteoi");
-	else
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_edge_irq, "edge");
-}
-
-static int setup_ioapic_entry(int apic, int irq,
-			      struct IO_APIC_route_entry *entry,
-			      unsigned int destination, int trigger,
-			      int polarity, int vector)
-{
-	/*
-	 * add it to the IO-APIC irq-routing table:
-	 */
-	memset(entry,0,sizeof(*entry));
-
-#ifdef CONFIG_INTR_REMAP
-	if (intr_remapping_enabled) {
-		struct intel_iommu *iommu = map_ioapic_to_ir(apic);
-		struct irte irte;
-		struct IR_IO_APIC_route_entry *ir_entry =
-			(struct IR_IO_APIC_route_entry *) entry;
-		int index;
-
-		if (!iommu)
-			panic("No mapping iommu for ioapic %d\n", apic);
-
-		index = alloc_irte(iommu, irq, 1);
-		if (index < 0)
-			panic("Failed to allocate IRTE for ioapic %d\n", apic);
-
-		memset(&irte, 0, sizeof(irte));
-
-		irte.present = 1;
-		irte.dst_mode = INT_DEST_MODE;
-		irte.trigger_mode = trigger;
-		irte.dlvry_mode = INT_DELIVERY_MODE;
-		irte.vector = vector;
-		irte.dest_id = IRTE_DEST(destination);
-
-		modify_irte(irq, &irte);
-
-		ir_entry->index2 = (index >> 15) & 0x1;
-		ir_entry->zero = 0;
-		ir_entry->format = 1;
-		ir_entry->index = (index & 0x7fff);
-	} else
-#endif
-	{
-		entry->delivery_mode = INT_DELIVERY_MODE;
-		entry->dest_mode = INT_DEST_MODE;
-		entry->dest = destination;
-	}
-
-	entry->mask = 0;				/* enable IRQ */
-	entry->trigger = trigger;
-	entry->polarity = polarity;
-	entry->vector = vector;
-
-	/* Mask level triggered irqs.
-	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
-	 */
-	if (trigger)
-		entry->mask = 1;
-	return 0;
-}
-
-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
-			      int trigger, int polarity)
-{
-	struct irq_cfg *cfg;
-	struct IO_APIC_route_entry entry;
-	cpumask_t mask;
-
-	if (!IO_APIC_IRQ(irq))
-		return;
-
-	cfg = irq_cfg(irq);
-
-	mask = TARGET_CPUS;
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cpus_and(mask, cfg->domain, mask);
-
-	apic_printk(APIC_VERBOSE,KERN_DEBUG
-		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
-		    "IRQ %d Mode:%i Active:%i)\n",
-		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
-		    irq, trigger, polarity);
-
-
-	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
-			       cpu_mask_to_apicid(mask), trigger, polarity,
-			       cfg->vector)) {
-		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
-		       mp_ioapics[apic].mp_apicid, pin);
-		__clear_irq_vector(irq);
-		return;
-	}
-
-	ioapic_register_intr(irq, trigger);
-	if (irq < 16)
-		disable_8259A_irq(irq);
-
-	ioapic_write_entry(apic, pin, entry);
-}
-
-static void __init setup_IO_APIC_irqs(void)
-{
-	int apic, pin, idx, irq, first_notcon = 1;
-
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-
-		idx = find_irq_entry(apic,pin,mp_INT);
-		if (idx == -1) {
-			if (first_notcon) {
-				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
-				first_notcon = 0;
-			} else
-				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
-			continue;
-		}
-		if (!first_notcon) {
-			apic_printk(APIC_VERBOSE, " not connected.\n");
-			first_notcon = 1;
-		}
-
-		irq = pin_2_irq(idx, apic, pin);
-#ifdef CONFIG_X86_32
-                if (multi_timer_check(apic, irq))
-                        continue;
-#endif
-		add_pin_to_irq(irq, apic, pin);
-
-		setup_IO_APIC_irq(apic, pin, irq,
-				  irq_trigger(idx), irq_polarity(idx));
-	}
-	}
-
-	if (!first_notcon)
-		apic_printk(APIC_VERBOSE, " not connected.\n");
-}
-
-/*
- * Set up the timer pin, possibly with the 8259A-master behind.
- */
-static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
-					int vector)
-{
-	struct IO_APIC_route_entry entry;
-
-#ifdef CONFIG_INTR_REMAP
-	if (intr_remapping_enabled)
-		return;
-#endif
-
-	memset(&entry, 0, sizeof(entry));
-
-	/*
-	 * We use logical delivery to get the timer IRQ
-	 * to the first CPU.
-	 */
-	entry.dest_mode = INT_DEST_MODE;
-	entry.mask = 1;					/* mask IRQ now */
-	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
-	entry.delivery_mode = INT_DELIVERY_MODE;
-	entry.polarity = 0;
-	entry.trigger = 0;
-	entry.vector = vector;
-
-	/*
-	 * The timer IRQ doesn't have to know that behind the
-	 * scene we may have a 8259A-master in AEOI mode ...
-	 */
-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
-
-	/*
-	 * Add it to the IO-APIC irq-routing table:
-	 */
-	ioapic_write_entry(apic, pin, entry);
-}
-
-
-__apicdebuginit(void) print_IO_APIC(void)
-{
-	int apic, i;
-	union IO_APIC_reg_00 reg_00;
-	union IO_APIC_reg_01 reg_01;
-	union IO_APIC_reg_02 reg_02;
-	union IO_APIC_reg_03 reg_03;
-	unsigned long flags;
-	struct irq_cfg *cfg;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
-	for (i = 0; i < nr_ioapics; i++)
-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
-		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
-
-	/*
-	 * We are a bit conservative about what we expect.  We have to
-	 * know about every hardware change ASAP.
-	 */
-	printk(KERN_INFO "testing the IO APIC.......................\n");
-
-	for (apic = 0; apic < nr_ioapics; apic++) {
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(apic, 0);
-	reg_01.raw = io_apic_read(apic, 1);
-	if (reg_01.bits.version >= 0x10)
-		reg_02.raw = io_apic_read(apic, 2);
-        if (reg_01.bits.version >= 0x20)
-                reg_03.raw = io_apic_read(apic, 3);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	printk("\n");
-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
-	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
-	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
-	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
-	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
-
-	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
-
-	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
-
-	/*
-	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
-	 * but the value of reg_02 is read as the previous read register
-	 * value, so ignore it if reg_02 == reg_01.
-	 */
-	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
-		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
-		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
-	}
-
-	/*
-	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
-	 * or reg_03, but the value of reg_0[23] is read as the previous read
-	 * register value, so ignore it if reg_03 == reg_0[12].
-	 */
-	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
-	    reg_03.raw != reg_01.raw) {
-		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
-		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
-	}
-
-	printk(KERN_DEBUG ".... IRQ redirection table:\n");
-
-	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
-			  " Stat Dmod Deli Vect:   \n");
-
-	for (i = 0; i <= reg_01.bits.entries; i++) {
-		struct IO_APIC_route_entry entry;
-
-		entry = ioapic_read_entry(apic, i);
-
-		printk(KERN_DEBUG " %02x %03X ",
-			i,
-			entry.dest
-		);
-
-		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
-			entry.mask,
-			entry.trigger,
-			entry.irr,
-			entry.polarity,
-			entry.delivery_status,
-			entry.dest_mode,
-			entry.delivery_mode,
-			entry.vector
-		);
-	}
-	}
-	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for_each_irq_cfg(cfg) {
-		struct irq_pin_list *entry = cfg->irq_2_pin;
-		if (!entry)
-			continue;
-		printk(KERN_DEBUG "IRQ%d ", cfg->irq);
-		for (;;) {
-			printk("-> %d:%d", entry->apic, entry->pin);
-			if (!entry->next)
-				break;
-			entry = entry->next;
-		}
-		printk("\n");
-	}
-
-	printk(KERN_INFO ".................................... done.\n");
-
-	return;
-}
-
-__apicdebuginit(void) print_APIC_bitfield(int base)
-{
-	unsigned int v;
-	int i, j;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
-	for (i = 0; i < 8; i++) {
-		v = apic_read(base + i*0x10);
-		for (j = 0; j < 32; j++) {
-			if (v & (1<<j))
-				printk("1");
-			else
-				printk("0");
-		}
-		printk("\n");
-	}
-}
-
-__apicdebuginit(void) print_local_APIC(void *dummy)
-{
-	unsigned int v, ver, maxlvt;
-	u64 icr;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
-		smp_processor_id(), hard_smp_processor_id());
-	v = apic_read(APIC_ID);
-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
-	v = apic_read(APIC_LVR);
-	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
-	ver = GET_APIC_VERSION(v);
-	maxlvt = lapic_get_maxlvt();
-
-	v = apic_read(APIC_TASKPRI);
-	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
-
-	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
-		v = apic_read(APIC_ARBPRI);
-		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-			v & APIC_ARBPRI_MASK);
-		v = apic_read(APIC_PROCPRI);
-		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
-	}
-
-	v = apic_read(APIC_EOI);
-	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
-	v = apic_read(APIC_RRR);
-	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
-	v = apic_read(APIC_LDR);
-	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
-	v = apic_read(APIC_DFR);
-	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
-	v = apic_read(APIC_SPIV);
-	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
-
-	printk(KERN_DEBUG "... APIC ISR field:\n");
-	print_APIC_bitfield(APIC_ISR);
-	printk(KERN_DEBUG "... APIC TMR field:\n");
-	print_APIC_bitfield(APIC_TMR);
-	printk(KERN_DEBUG "... APIC IRR field:\n");
-	print_APIC_bitfield(APIC_IRR);
-
-	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
-		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
-			apic_write(APIC_ESR, 0);
-
-		v = apic_read(APIC_ESR);
-		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
-	}
-
-	icr = apic_icr_read();
-	printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
-	printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
-
-	v = apic_read(APIC_LVTT);
-	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
-
-	if (maxlvt > 3) {                       /* PC is LVT#4. */
-		v = apic_read(APIC_LVTPC);
-		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
-	}
-	v = apic_read(APIC_LVT0);
-	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
-	v = apic_read(APIC_LVT1);
-	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
-
-	if (maxlvt > 2) {			/* ERR is LVT#3. */
-		v = apic_read(APIC_LVTERR);
-		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
-	}
-
-	v = apic_read(APIC_TMICT);
-	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
-	v = apic_read(APIC_TMCCT);
-	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
-	v = apic_read(APIC_TDCR);
-	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
-	printk("\n");
-}
-
-__apicdebuginit(void) print_all_local_APICs(void)
-{
-	on_each_cpu(print_local_APIC, NULL, 1);
-}
-
-__apicdebuginit(void) print_PIC(void)
-{
-	unsigned int v;
-	unsigned long flags;
-
-	if (apic_verbosity == APIC_QUIET)
-		return;
-
-	printk(KERN_DEBUG "\nprinting PIC contents\n");
-
-	spin_lock_irqsave(&i8259A_lock, flags);
-
-	v = inb(0xa1) << 8 | inb(0x21);
-	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
-
-	v = inb(0xa0) << 8 | inb(0x20);
-	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
-
-	outb(0x0b,0xa0);
-	outb(0x0b,0x20);
-	v = inb(0xa0) << 8 | inb(0x20);
-	outb(0x0a,0xa0);
-	outb(0x0a,0x20);
-
-	spin_unlock_irqrestore(&i8259A_lock, flags);
-
-	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
-
-	v = inb(0x4d1) << 8 | inb(0x4d0);
-	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
-}
-
-__apicdebuginit(int) print_all_ICs(void)
-{
-	print_PIC();
-	print_all_local_APICs();
-	print_IO_APIC();
-
-	return 0;
-}
-
-fs_initcall(print_all_ICs);
-
-
-/* Where if anywhere is the i8259 connect in external int mode */
-static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
-
-void __init enable_IO_APIC(void)
-{
-	union IO_APIC_reg_01 reg_01;
-	int i8259_apic, i8259_pin;
-	int apic;
-	unsigned long flags;
-
-#ifdef CONFIG_X86_32
-	int i;
-	if (!pirqs_enabled)
-		for (i = 0; i < MAX_PIRQS; i++)
-			pirq_entries[i] = -1;
-#endif
-
-	/*
-	 * The number of IO-APIC IRQ registers (== #pins):
-	 */
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_01.raw = io_apic_read(apic, 1);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
-	}
-	for(apic = 0; apic < nr_ioapics; apic++) {
-		int pin;
-		/* See if any of the pins is in ExtINT mode */
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			struct IO_APIC_route_entry entry;
-			entry = ioapic_read_entry(apic, pin);
-
-			/* If the interrupt line is enabled and in ExtInt mode
-			 * I have found the pin where the i8259 is connected.
-			 */
-			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
-				ioapic_i8259.apic = apic;
-				ioapic_i8259.pin  = pin;
-				goto found_i8259;
-			}
-		}
-	}
- found_i8259:
-	/* Look to see what if the MP table has reported the ExtINT */
-	/* If we could not find the appropriate pin by looking at the ioapic
-	 * the i8259 probably is not connected the ioapic but give the
-	 * mptable a chance anyway.
-	 */
-	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
-	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
-	/* Trust the MP table if nothing is setup in the hardware */
-	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
-		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
-		ioapic_i8259.pin  = i8259_pin;
-		ioapic_i8259.apic = i8259_apic;
-	}
-	/* Complain if the MP table and the hardware disagree */
-	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
-		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
-	{
-		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
-	}
-
-	/*
-	 * Do not trust the IO-APIC being empty at bootup
-	 */
-	clear_IO_APIC();
-}
-
-/*
- * Not an __init, needed by the reboot code
- */
-void disable_IO_APIC(void)
-{
-	/*
-	 * Clear the IO-APIC before rebooting:
-	 */
-	clear_IO_APIC();
-
-	/*
-	 * If the i8259 is routed through an IOAPIC
-	 * Put that IOAPIC in virtual wire mode
-	 * so legacy interrupts can be delivered.
-	 */
-	if (ioapic_i8259.pin != -1) {
-		struct IO_APIC_route_entry entry;
-
-		memset(&entry, 0, sizeof(entry));
-		entry.mask            = 0; /* Enabled */
-		entry.trigger         = 0; /* Edge */
-		entry.irr             = 0;
-		entry.polarity        = 0; /* High */
-		entry.delivery_status = 0;
-		entry.dest_mode       = 0; /* Physical */
-		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
-		entry.vector          = 0;
-		entry.dest            = read_apic_id();
-
-		/*
-		 * Add it to the IO-APIC irq-routing table:
-		 */
-		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
-	}
-
-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
-}
-
-#ifdef CONFIG_X86_32
-/*
- * function to set the IO-APIC physical IDs based on the
- * values stored in the MPC table.
- *
- * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
- */
-
-static void __init setup_ioapic_ids_from_mpc(void)
-{
-	union IO_APIC_reg_00 reg_00;
-	physid_mask_t phys_id_present_map;
-	int apic;
-	int i;
-	unsigned char old_id;
-	unsigned long flags;
-
-	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
-		return;
-
-	/*
-	 * Don't check I/O APIC IDs for xAPIC systems.  They have
-	 * no meaning without the serial APIC bus.
-	 */
-	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return;
-	/*
-	 * This is broken; anything with a real cpu count has to
-	 * circumvent this idiocy regardless.
-	 */
-	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
-
-	/*
-	 * Set the IOAPIC ID to the value stored in the MPC table.
-	 */
-	for (apic = 0; apic < nr_ioapics; apic++) {
-
-		/* Read the register 0 value */
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-
-		old_id = mp_ioapics[apic].mp_apicid;
-
-		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
-				apic, mp_ioapics[apic].mp_apicid);
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				reg_00.bits.ID);
-			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
-		}
-
-		/*
-		 * Sanity check, is the ID really free? Every APIC in a
-		 * system must have a unique ID or we get lots of nice
-		 * 'stuck on smp_invalidate_needed IPI wait' messages.
-		 */
-		if (check_apicid_used(phys_id_present_map,
-					mp_ioapics[apic].mp_apicid)) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-				apic, mp_ioapics[apic].mp_apicid);
-			for (i = 0; i < get_physical_broadcast(); i++)
-				if (!physid_isset(i, phys_id_present_map))
-					break;
-			if (i >= get_physical_broadcast())
-				panic("Max APIC ID exceeded!\n");
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				i);
-			physid_set(i, phys_id_present_map);
-			mp_ioapics[apic].mp_apicid = i;
-		} else {
-			physid_mask_t tmp;
-			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
-			apic_printk(APIC_VERBOSE, "Setting %d in the "
-					"phys_id_present_map\n",
-					mp_ioapics[apic].mp_apicid);
-			physids_or(phys_id_present_map, phys_id_present_map, tmp);
-		}
-
-
-		/*
-		 * We need to adjust the IRQ routing table
-		 * if the ID changed.
-		 */
-		if (old_id != mp_ioapics[apic].mp_apicid)
-			for (i = 0; i < mp_irq_entries; i++)
-				if (mp_irqs[i].mp_dstapic == old_id)
-					mp_irqs[i].mp_dstapic
-						= mp_ioapics[apic].mp_apicid;
-
-		/*
-		 * Read the right value from the MPC table and
-		 * write it into the ID register.
-		 */
-		apic_printk(APIC_VERBOSE, KERN_INFO
-			"...changing IO-APIC physical APIC ID to %d ...",
-			mp_ioapics[apic].mp_apicid);
-
-		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
-		spin_lock_irqsave(&ioapic_lock, flags);
-
-		/*
-		 * Sanity check
-		 */
-		spin_lock_irqsave(&ioapic_lock, flags);
-		reg_00.raw = io_apic_read(apic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
-			printk("could not set ID!\n");
-		else
-			apic_printk(APIC_VERBOSE, " ok.\n");
-	}
-}
-#endif
-
-int no_timer_check __initdata;
-
-static int __init notimercheck(char *s)
-{
-	no_timer_check = 1;
-	return 1;
-}
-__setup("no_timer_check", notimercheck);
-
-/*
- * There is a nasty bug in some older SMP boards, their mptable lies
- * about the timer IRQ. We do the following to work around the situation:
- *
- *	- timer IRQ defaults to IO-APIC IRQ
- *	- if this function detects that timer IRQs are defunct, then we fall
- *	  back to ISA timer IRQs
- */
-static int __init timer_irq_works(void)
-{
-	unsigned long t1 = jiffies;
-	unsigned long flags;
-
-	if (no_timer_check)
-		return 1;
-
-	local_save_flags(flags);
-	local_irq_enable();
-	/* Let ten ticks pass... */
-	mdelay((10 * 1000) / HZ);
-	local_irq_restore(flags);
-
-	/*
-	 * Expect a few ticks at least, to be sure some possible
-	 * glue logic does not lock up after one or two first
-	 * ticks in a non-ExtINT mode.  Also the local APIC
-	 * might have cached one ExtINT interrupt.  Finally, at
-	 * least one tick may be lost due to delays.
-	 */
-
-	/* jiffies wrap? */
-	if (time_after(jiffies, t1 + 4))
-		return 1;
-	return 0;
-}
-
-/*
- * In the SMP+IOAPIC case it might happen that there are an unspecified
- * number of pending IRQ events unhandled. These cases are very rare,
- * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
- * better to do it this way as thus we do not have to be aware of
- * 'pending' interrupts in the IRQ path, except at this point.
- */
-/*
- * Edge triggered needs to resend any interrupt
- * that was delayed but this is now handled in the device
- * independent code.
- */
-
-/*
- * Starting up a edge-triggered IO-APIC interrupt is
- * nasty - we need to make sure that we get the edge.
- * If it is already asserted for some reason, we need
- * return 1 to indicate that is was pending.
- *
- * This is not complete - we should be able to fake
- * an edge even if it isn't on the 8259A...
- */
-
-static unsigned int startup_ioapic_irq(unsigned int irq)
-{
-	int was_pending = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	if (irq < 16) {
-		disable_8259A_irq(irq);
-		if (i8259A_irq_pending(irq))
-			was_pending = 1;
-	}
-	__unmask_IO_APIC_irq(irq);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return was_pending;
-}
-
-#ifdef CONFIG_X86_64
-static int ioapic_retrigger_irq(unsigned int irq)
-{
-
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned long flags;
-
-	spin_lock_irqsave(&vector_lock, flags);
-	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
-	spin_unlock_irqrestore(&vector_lock, flags);
-
-	return 1;
-}
-#else
-static int ioapic_retrigger_irq(unsigned int irq)
-{
-        send_IPI_self(irq_cfg(irq)->vector);
-
-        return 1;
-}
-#endif
-
-/*
- * Level and edge triggered IO-APIC interrupts need different handling,
- * so we use two separate IRQ descriptors. Edge triggered IRQs can be
- * handled with the level-triggered descriptor, but that one has slightly
- * more overhead. Level-triggered interrupts cannot be handled with the
- * edge-triggered handler, without risking IRQ storms and other ugly
- * races.
- */
-
-#ifdef CONFIG_SMP
-
-#ifdef CONFIG_INTR_REMAP
-static void ir_irq_migration(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
-
-/*
- * Migrate the IO-APIC irq in the presence of intr-remapping.
- *
- * For edge triggered, irq migration is a simple atomic update(of vector
- * and cpu destination) of IRTE and flush the hardware cache.
- *
- * For level triggered, we need to modify the io-apic RTE aswell with the update
- * vector information, along with modifying IRTE with vector and destination.
- * So irq migration for level triggered is little  bit more complex compared to
- * edge triggered migration. But the good news is, we use the same algorithm
- * for level triggered migration as we have today, only difference being,
- * we now initiate the irq migration from process context instead of the
- * interrupt context.
- *
- * In future, when we do a directed EOI (combined with cpu EOI broadcast
- * suppression) to the IO-APIC, level triggered irq migration will also be
- * as simple as edge triggered migration and we can do the irq migration
- * with a simple atomic update to IO-APIC RTE.
- */
-static void migrate_ioapic_irq(int irq, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	struct irq_desc *desc;
-	cpumask_t tmp, cleanup_mask;
-	struct irte irte;
-	int modify_ioapic_rte;
-	unsigned int dest;
-	unsigned long flags;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (get_irte(irq, &irte))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	desc = irq_desc(irq);
-	modify_ioapic_rte = desc->status & IRQ_LEVEL;
-	if (modify_ioapic_rte) {
-		spin_lock_irqsave(&ioapic_lock, flags);
-		__target_IO_APIC_irq(irq, dest, cfg->vector);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-	}
-
-	irte.vector = cfg->vector;
-	irte.dest_id = IRTE_DEST(dest);
-
-	/*
-	 * Modified the IRTE and flushes the Interrupt entry cache.
-	 */
-	modify_irte(irq, &irte);
-
-	if (cfg->move_in_progress) {
-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
-		cfg->move_in_progress = 0;
-	}
-
-	desc->affinity = mask;
-}
-
-static int migrate_irq_remapped_level(int irq)
-{
-	int ret = -1;
-	struct irq_desc *desc = irq_desc(irq);
-
-	mask_IO_APIC_irq(irq);
-
-	if (io_apic_level_ack_pending(irq)) {
-		/*
-	 	 * Interrupt in progress. Migrating irq now will change the
-		 * vector information in the IO-APIC RTE and that will confuse
-		 * the EOI broadcast performed by cpu.
-		 * So, delay the irq migration to the next instance.
-		 */
-		schedule_delayed_work(&ir_migration_work, 1);
-		goto unmask;
-	}
-
-	/* everthing is clear. we have right of way */
-	migrate_ioapic_irq(irq, desc->pending_mask);
-
-	ret = 0;
-	desc->status &= ~IRQ_MOVE_PENDING;
-	cpus_clear(desc->pending_mask);
-
-unmask:
-	unmask_IO_APIC_irq(irq);
-	return ret;
-}
-
-static void ir_irq_migration(struct work_struct *work)
-{
-	unsigned int irq;
-	struct irq_desc *desc;
-
-	for_each_irq_desc(irq, desc) {
-		if (desc->status & IRQ_MOVE_PENDING) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&desc->lock, flags);
-			if (!desc->chip->set_affinity ||
-			    !(desc->status & IRQ_MOVE_PENDING)) {
-				desc->status &= ~IRQ_MOVE_PENDING;
-				spin_unlock_irqrestore(&desc->lock, flags);
-				continue;
-			}
-
-			desc->chip->set_affinity(irq, desc, desc->pending_mask);
-			spin_unlock_irqrestore(&desc->lock, flags);
-		}
-	}
-}
-
-/*
- * Migrates the IRQ destination in the process context.
- */
-static void set_ir_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	if (desc->status & IRQ_LEVEL) {
-		desc->status |= IRQ_MOVE_PENDING;
-		desc->pending_mask = mask;
-		migrate_irq_remapped_level(irq);
-		return;
-	}
-
-	migrate_ioapic_irq(irq, mask);
-}
-#endif
-
-asmlinkage void smp_irq_move_cleanup_interrupt(void)
-{
-	unsigned vector, me;
-	ack_APIC_irq();
-#ifdef CONFIG_X86_64
-	exit_idle();
-#endif
-	irq_enter();
-
-	me = smp_processor_id();
-	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
-		unsigned int irq;
-		struct irq_desc *desc;
-		struct irq_cfg *cfg;
-		irq = __get_cpu_var(vector_irq)[vector];
-
-		desc = irq_desc(irq);
-		if (!desc)
-			continue;
-
-		cfg = irq_cfg(irq);
-		spin_lock(&desc->lock);
-		if (!cfg->move_cleanup_count)
-			goto unlock;
-
-		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
-			goto unlock;
-
-		__get_cpu_var(vector_irq)[vector] = -1;
-		cfg->move_cleanup_count--;
-unlock:
-		spin_unlock(&desc->lock);
-	}
-
-	irq_exit();
-}
-
-static void irq_complete_move(unsigned int irq)
-{
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned vector, me;
-
-	if (likely(!cfg->move_in_progress))
-		return;
-
-	vector = ~get_irq_regs()->orig_ax;
-	me = smp_processor_id();
-	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
-		cpumask_t cleanup_mask;
-
-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
-		cfg->move_in_progress = 0;
-	}
-}
-#else
-static inline void irq_complete_move(unsigned int irq) {}
-#endif
-#ifdef CONFIG_INTR_REMAP
-static void ack_x2apic_level(unsigned int irq, struct irq_desc *desc)
-{
-	ack_x2APIC_irq();
-}
-
-static void ack_x2apic_edge(unsigned int irq, struct irq_desc *desc)
-{
-	ack_x2APIC_irq();
-}
-#endif
-
-static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
-{
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-	ack_APIC_irq();
-}
-
-#ifdef CONFIG_X86_64
-static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
-{
-	int do_unmask_irq = 0;
-
-	irq_complete_move(irq);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	/* If we are moving the irq we need to mask it */
-	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
-		do_unmask_irq = 1;
-		mask_IO_APIC_irq(irq);
-	}
-#endif
-
-	/*
-	 * We must acknowledge the irq before we move it or the acknowledge will
-	 * not propagate properly.
-	 */
-	ack_APIC_irq();
-
-	/* Now we can move and renable the irq */
-	if (unlikely(do_unmask_irq)) {
-		/* Only migrate the irq if the ack has been received.
-		 *
-		 * On rare occasions the broadcast level triggered ack gets
-		 * delayed going to ioapics, and if we reprogram the
-		 * vector while Remote IRR is still set the irq will never
-		 * fire again.
-		 *
-		 * To prevent this scenario we read the Remote IRR bit
-		 * of the ioapic.  This has two effects.
-		 * - On any sane system the read of the ioapic will
-		 *   flush writes (and acks) going to the ioapic from
-		 *   this cpu.
-		 * - We get to see if the ACK has actually been delivered.
-		 *
-		 * Based on failed experiments of reprogramming the
-		 * ioapic entry from outside of irq context starting
-		 * with masking the ioapic entry and then polling until
-		 * Remote IRR was clear before reprogramming the
-		 * ioapic I don't trust the Remote IRR bit to be
-		 * completey accurate.
-		 *
-		 * However there appears to be no other way to plug
-		 * this race, so if the Remote IRR bit is not
-		 * accurate and is causing problems then it is a hardware bug
-		 * and you can go talk to the chipset vendor about it.
-		 */
-		if (!io_apic_level_ack_pending(irq))
-			move_masked_irq(irq, desc);
-		unmask_IO_APIC_irq(irq);
-	}
-}
-#else
-atomic_t irq_mis_count;
-static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned long v;
-	int i;
-
-	irq_complete_move(irq);
-	move_native_irq(irq, desc);
-	/*
-	* It appears there is an erratum which affects at least version 0x11
-	* of I/O APIC (that's the 82093AA and cores integrated into various
-	* chipsets).  Under certain conditions a level-triggered interrupt is
-	* erroneously delivered as edge-triggered one but the respective IRR
-	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
-	* message but it will never arrive and further interrupts are blocked
-	* from the source.  The exact reason is so far unknown, but the
-	* phenomenon was observed when two consecutive interrupt requests
-	* from a given source get delivered to the same CPU and the source is
-	* temporarily disabled in between.
-	*
-	* A workaround is to simulate an EOI message manually.  We achieve it
-	* by setting the trigger mode to edge and then to level when the edge
-	* trigger mode gets detected in the TMR of a local APIC for a
-	* level-triggered interrupt.  We mask the source for the time of the
-	* operation to prevent an edge-triggered interrupt escaping meanwhile.
-	* The idea is from Manfred Spraul.  --macro
-	*/
-	i = irq_cfg(irq)->vector;
-
-	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
-
-	ack_APIC_irq();
-
-	if (!(v & (1 << (i & 0x1f)))) {
-		atomic_inc(&irq_mis_count);
-		spin_lock(&ioapic_lock);
-		__mask_and_edge_IO_APIC_irq(irq);
-		__unmask_and_level_IO_APIC_irq(irq);
-		spin_unlock(&ioapic_lock);
-	}
-}
-#endif
-
-static struct irq_chip ioapic_chip __read_mostly = {
-	.name 		= "IO-APIC",
-	.startup 	= startup_ioapic_irq,
-	.mask	 	= mask_IO_APIC_irq,
-	.unmask	 	= unmask_IO_APIC_irq,
-	.ack 		= ack_apic_edge,
-	.eoi 		= ack_apic_level,
-#ifdef CONFIG_SMP
-	.set_affinity 	= set_ioapic_affinity_irq,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-#ifdef CONFIG_INTR_REMAP
-static struct irq_chip ir_ioapic_chip __read_mostly = {
-	.name 		= "IR-IO-APIC",
-	.startup 	= startup_ioapic_irq,
-	.mask	 	= mask_IO_APIC_irq,
-	.unmask	 	= unmask_IO_APIC_irq,
-	.ack 		= ack_x2apic_edge,
-	.eoi 		= ack_x2apic_level,
-#ifdef CONFIG_SMP
-	.set_affinity 	= set_ir_ioapic_affinity_irq,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-#endif
-
-static inline void init_IO_APIC_traps(void)
-{
-	int irq;
-	struct irq_desc *desc;
-	struct irq_cfg *cfg;
-
-	/*
-	 * NOTE! The local APIC isn't very good at handling
-	 * multiple interrupts at the same interrupt level.
-	 * As the interrupt level is determined by taking the
-	 * vector number and shifting that right by 4, we
-	 * want to spread these out a bit so that they don't
-	 * all fall in the same interrupt level.
-	 *
-	 * Also, we've got to be careful not to trash gate
-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
-	 */
-	for_each_irq_cfg(cfg) {
-		irq = cfg->irq;
-		if (IO_APIC_IRQ(irq) && !cfg->vector) {
-			/*
-			 * Hmm.. We don't have an entry for this,
-			 * so default to an old-fashioned 8259
-			 * interrupt if we can..
-			 */
-			if (irq < 16)
-				make_8259A_irq(irq);
-			else {
-				desc = irq_desc(irq);
-				/* Strange. Oh, well.. */
-				desc->chip = &no_irq_chip;
-			}
-		}
-	}
-}
-
-/*
- * The local APIC irq-chip implementation:
- */
-
-static void mask_lapic_irq(unsigned int irq)
-{
-	unsigned long v;
-
-	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
-}
-
-static void unmask_lapic_irq(unsigned int irq)
-{
-	unsigned long v;
-
-	v = apic_read(APIC_LVT0);
-	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
-}
-
-static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
-{
-	ack_APIC_irq();
-}
-
-static struct irq_chip lapic_chip __read_mostly = {
-	.name		= "local-APIC",
-	.mask		= mask_lapic_irq,
-	.unmask		= unmask_lapic_irq,
-	.ack		= ack_lapic_irq,
-};
-
-static void lapic_register_intr(int irq)
-{
-	struct irq_desc *desc;
-
-	desc = irq_desc(irq);
-	desc->status &= ~IRQ_LEVEL;
-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
-				      "edge");
-}
-
-static void __init setup_nmi(void)
-{
-	/*
-	 * Dirty trick to enable the NMI watchdog ...
-	 * We put the 8259A master into AEOI mode and
-	 * unmask on all local APICs LVT0 as NMI.
-	 *
-	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
-	 * is from Maciej W. Rozycki - so we do not have to EOI from
-	 * the NMI handler or the timer interrupt.
-	 */
-	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
-
-	enable_NMI_through_LVT0();
-
-	apic_printk(APIC_VERBOSE, " done.\n");
-}
-
-/*
- * This looks a bit hackish but it's about the only one way of sending
- * a few INTA cycles to 8259As and any associated glue logic.  ICR does
- * not support the ExtINT mode, unfortunately.  We need to send these
- * cycles as some i82489DX-based boards have glue logic that keeps the
- * 8259A interrupt line asserted until INTA.  --macro
- */
-static inline void __init unlock_ExtINT_logic(void)
-{
-	int apic, pin, i;
-	struct IO_APIC_route_entry entry0, entry1;
-	unsigned char save_control, save_freq_select;
-
-	pin  = find_isa_irq_pin(8, mp_INT);
-	if (pin == -1) {
-		WARN_ON_ONCE(1);
-		return;
-	}
-	apic = find_isa_irq_apic(8, mp_INT);
-	if (apic == -1) {
-		WARN_ON_ONCE(1);
-		return;
-	}
-
-	entry0 = ioapic_read_entry(apic, pin);
-	clear_IO_APIC_pin(apic, pin);
-
-	memset(&entry1, 0, sizeof(entry1));
-
-	entry1.dest_mode = 0;			/* physical delivery */
-	entry1.mask = 0;			/* unmask IRQ now */
-	entry1.dest = hard_smp_processor_id();
-	entry1.delivery_mode = dest_ExtINT;
-	entry1.polarity = entry0.polarity;
-	entry1.trigger = 0;
-	entry1.vector = 0;
-
-	ioapic_write_entry(apic, pin, entry1);
-
-	save_control = CMOS_READ(RTC_CONTROL);
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
-		   RTC_FREQ_SELECT);
-	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
-
-	i = 100;
-	while (i-- > 0) {
-		mdelay(10);
-		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
-			i -= 10;
-	}
-
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-	clear_IO_APIC_pin(apic, pin);
-
-	ioapic_write_entry(apic, pin, entry0);
-}
-
-static int disable_timer_pin_1 __initdata;
-/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
-static int __init disable_timer_pin_setup(char *arg)
-{
-	disable_timer_pin_1 = 1;
-	return 0;
-}
-early_param("disable_timer_pin_1", disable_timer_pin_setup);
-
-int timer_through_8259 __initdata;
-
-/*
- * This code may look a bit paranoid, but it's supposed to cooperate with
- * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
- * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
- * fanatically on his truly buggy board.
- *
- * FIXME: really need to revamp this for all platforms.
- */
-static inline void __init check_timer(void)
-{
-	struct irq_cfg *cfg = irq_cfg(0);
-	int apic1, pin1, apic2, pin2;
-	unsigned long flags;
-	unsigned int ver;
-	int no_pin1 = 0;
-
-	local_irq_save(flags);
-
-        ver = apic_read(APIC_LVR);
-        ver = GET_APIC_VERSION(ver);
-
-	/*
-	 * get/set the timer IRQ vector:
-	 */
-	disable_8259A_irq(0);
-	assign_irq_vector(0, TARGET_CPUS);
-
-	/*
-	 * As IRQ0 is to be enabled in the 8259A, the virtual
-	 * wire has to be disabled in the local APIC.  Also
-	 * timer interrupts need to be acknowledged manually in
-	 * the 8259A for the i82489DX when using the NMI
-	 * watchdog as that APIC treats NMIs as level-triggered.
-	 * The AEOI mode will finish them in the 8259A
-	 * automatically.
-	 */
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
-	init_8259A(1);
-#ifdef CONFIG_X86_32
-	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
-#endif
-
-	pin1  = find_isa_irq_pin(0, mp_INT);
-	apic1 = find_isa_irq_apic(0, mp_INT);
-	pin2  = ioapic_i8259.pin;
-	apic2 = ioapic_i8259.apic;
-
-	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
-		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		    cfg->vector, apic1, pin1, apic2, pin2);
-
-	/*
-	 * Some BIOS writers are clueless and report the ExtINTA
-	 * I/O APIC input from the cascaded 8259A as the timer
-	 * interrupt input.  So just in case, if only one pin
-	 * was found above, try it both directly and through the
-	 * 8259A.
-	 */
-	if (pin1 == -1) {
-#ifdef CONFIG_INTR_REMAP
-		if (intr_remapping_enabled)
-			panic("BIOS bug: timer not connected to IO-APIC");
-#endif
-		pin1 = pin2;
-		apic1 = apic2;
-		no_pin1 = 1;
-	} else if (pin2 == -1) {
-		pin2 = pin1;
-		apic2 = apic1;
-	}
-
-	if (pin1 != -1) {
-		/*
-		 * Ok, does IRQ0 through the IOAPIC work?
-		 */
-		if (no_pin1) {
-			add_pin_to_irq(0, apic1, pin1);
-			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
-		}
-		unmask_IO_APIC_irq(0);
-		if (timer_irq_works()) {
-			if (nmi_watchdog == NMI_IO_APIC) {
-				setup_nmi();
-				enable_8259A_irq(0);
-			}
-			if (disable_timer_pin_1 > 0)
-				clear_IO_APIC_pin(0, pin1);
-			goto out;
-		}
-#ifdef CONFIG_INTR_REMAP
-		if (intr_remapping_enabled)
-			panic("timer doesn't work through Interrupt-remapped IO-APIC");
-#endif
-		clear_IO_APIC_pin(apic1, pin1);
-		if (!no_pin1)
-			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
-				    "8254 timer not connected to IO-APIC\n");
-
-		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
-			    "(IRQ0) through the 8259A ...\n");
-		apic_printk(APIC_QUIET, KERN_INFO
-			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
-		/*
-		 * legacy devices should be connected to IO APIC #0
-		 */
-		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
-		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-		unmask_IO_APIC_irq(0);
-		enable_8259A_irq(0);
-		if (timer_irq_works()) {
-			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
-			timer_through_8259 = 1;
-			if (nmi_watchdog == NMI_IO_APIC) {
-				disable_8259A_irq(0);
-				setup_nmi();
-				enable_8259A_irq(0);
-			}
-			goto out;
-		}
-		/*
-		 * Cleanup, just in case ...
-		 */
-		disable_8259A_irq(0);
-		clear_IO_APIC_pin(apic2, pin2);
-		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
-	}
-
-	if (nmi_watchdog == NMI_IO_APIC) {
-		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
-			    "through the IO-APIC - disabling NMI Watchdog!\n");
-		nmi_watchdog = NMI_NONE;
-	}
-#ifdef CONFIG_X86_32
-	timer_ack = 0;
-#endif
-
-	apic_printk(APIC_QUIET, KERN_INFO
-		    "...trying to set up timer as Virtual Wire IRQ...\n");
-
-	lapic_register_intr(0);
-	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
-	enable_8259A_irq(0);
-
-	if (timer_irq_works()) {
-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
-		goto out;
-	}
-	disable_8259A_irq(0);
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
-	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
-
-	apic_printk(APIC_QUIET, KERN_INFO
-		    "...trying to set up timer as ExtINT IRQ...\n");
-
-	init_8259A(0);
-	make_8259A_irq(0);
-	apic_write(APIC_LVT0, APIC_DM_EXTINT);
-
-	unlock_ExtINT_logic();
-
-	if (timer_irq_works()) {
-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
-		goto out;
-	}
-	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
-	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
-		"report.  Then try booting with the 'noapic' option.\n");
-out:
-	local_irq_restore(flags);
-}
-
-/*
- * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
- * to devices.  However there may be an I/O APIC pin available for
- * this interrupt regardless.  The pin may be left unconnected, but
- * typically it will be reused as an ExtINT cascade interrupt for
- * the master 8259A.  In the MPS case such a pin will normally be
- * reported as an ExtINT interrupt in the MP table.  With ACPI
- * there is no provision for ExtINT interrupts, and in the absence
- * of an override it would be treated as an ordinary ISA I/O APIC
- * interrupt, that is edge-triggered and unmasked by default.  We
- * used to do this, but it caused problems on some systems because
- * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
- * the same ExtINT cascade interrupt to drive the local APIC of the
- * bootstrap processor.  Therefore we refrain from routing IRQ2 to
- * the I/O APIC in all cases now.  No actual device should request
- * it anyway.  --macro
- */
-#define PIC_IRQS	(1 << PIC_CASCADE_IR)
-
-void __init setup_IO_APIC(void)
-{
-
-#ifdef CONFIG_X86_32
-	enable_IO_APIC();
-#else
-	/*
-	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
-	 */
-#endif
-
-	io_apic_irqs = ~PIC_IRQS;
-
-	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
-        /*
-         * Set up IO-APIC IRQ routing.
-         */
-#ifdef CONFIG_X86_32
-        if (!acpi_ioapic)
-                setup_ioapic_ids_from_mpc();
-#endif
-	sync_Arb_IDs();
-	setup_IO_APIC_irqs();
-	init_IO_APIC_traps();
-	check_timer();
-}
-
-/*
- *      Called after all the initialization is done. If we didnt find any
- *      APIC bugs then we can allow the modify fast path
- */
-
-static int __init io_apic_bug_finalize(void)
-{
-        if (sis_apic_bug == -1)
-                sis_apic_bug = 0;
-        return 0;
-}
-
-late_initcall(io_apic_bug_finalize);
-
-struct sysfs_ioapic_data {
-	struct sys_device dev;
-	struct IO_APIC_route_entry entry[0];
-};
-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
-
-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
-	int i;
-
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
-		*entry = ioapic_read_entry(dev->id, i);
-
-	return 0;
-}
-
-static int ioapic_resume(struct sys_device *dev)
-{
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
-	unsigned long flags;
-	union IO_APIC_reg_00 reg_00;
-	int i;
-
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(dev->id, 0);
-	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
-		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
-		io_apic_write(dev->id, 0, reg_00.raw);
-	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-		ioapic_write_entry(dev->id, i, entry[i]);
-
-	return 0;
-}
-
-static struct sysdev_class ioapic_sysdev_class = {
-	.name = "ioapic",
-	.suspend = ioapic_suspend,
-	.resume = ioapic_resume,
-};
-
-static int __init ioapic_init_sysfs(void)
-{
-	struct sys_device * dev;
-	int i, size, error;
-
-	error = sysdev_class_register(&ioapic_sysdev_class);
-	if (error)
-		return error;
-
-	for (i = 0; i < nr_ioapics; i++ ) {
-		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
-			* sizeof(struct IO_APIC_route_entry);
-		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
-		if (!mp_ioapic_data[i]) {
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
-		dev = &mp_ioapic_data[i]->dev;
-		dev->id = i;
-		dev->cls = &ioapic_sysdev_class;
-		error = sysdev_register(dev);
-		if (error) {
-			kfree(mp_ioapic_data[i]);
-			mp_ioapic_data[i] = NULL;
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
-	}
-
-	return 0;
-}
-
-device_initcall(ioapic_init_sysfs);
-
-/*
- * Dynamic irq allocate and deallocation
- */
-unsigned int create_irq(unsigned int irq_want)
-{
-	/* Allocate an unused irq */
-	unsigned int irq;
-	unsigned int new;
-	unsigned long flags;
-	struct irq_cfg *cfg_new;
-
-#ifndef CONFIG_HAVE_SPARSE_IRQ
-	irq_want = nr_irqs - 1;
-#endif
-
-	irq = 0;
-	spin_lock_irqsave(&vector_lock, flags);
-	for (new = irq_want; new > 0; new--) {
-		if (platform_legacy_irq(new))
-			continue;
-		cfg_new = irq_cfg(new);
-		if (cfg_new && cfg_new->vector != 0)
-			continue;
-		/* check if need to create one */
-		if (!cfg_new)
-			cfg_new = irq_cfg_with_new(new);
-		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
-			irq = new;
-		break;
-	}
-	spin_unlock_irqrestore(&vector_lock, flags);
-
-	if (irq > 0) {
-		dynamic_irq_init(irq);
-	}
-	return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
-	unsigned long flags;
-
-	dynamic_irq_cleanup(irq);
-
-#ifdef CONFIG_INTR_REMAP
-	free_irte(irq);
-#endif
-	spin_lock_irqsave(&vector_lock, flags);
-	__clear_irq_vector(irq);
-	spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-/*
- * MSI message composition
- */
-#ifdef CONFIG_PCI_MSI
-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
-{
-	struct irq_cfg *cfg;
-	int err;
-	unsigned dest;
-	cpumask_t tmp;
-
-	tmp = TARGET_CPUS;
-	err = assign_irq_vector(irq, tmp);
-	if (err)
-		return err;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, tmp);
-	dest = cpu_mask_to_apicid(tmp);
-
-#ifdef CONFIG_INTR_REMAP
-	if (irq_remapped(irq)) {
-		struct irte irte;
-		int ir_index;
-		u16 sub_handle;
-
-		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
-		BUG_ON(ir_index == -1);
-
-		memset (&irte, 0, sizeof(irte));
-
-		irte.present = 1;
-		irte.dst_mode = INT_DEST_MODE;
-		irte.trigger_mode = 0; /* edge */
-		irte.dlvry_mode = INT_DELIVERY_MODE;
-		irte.vector = cfg->vector;
-		irte.dest_id = IRTE_DEST(dest);
-
-		modify_irte(irq, &irte);
-
-		msg->address_hi = MSI_ADDR_BASE_HI;
-		msg->data = sub_handle;
-		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
-				  MSI_ADDR_IR_SHV |
-				  MSI_ADDR_IR_INDEX1(ir_index) |
-				  MSI_ADDR_IR_INDEX2(ir_index);
-	} else
-#endif
-	{
-		msg->address_hi = MSI_ADDR_BASE_HI;
-		msg->address_lo =
-			MSI_ADDR_BASE_LO |
-			((INT_DEST_MODE == 0) ?
-				MSI_ADDR_DEST_MODE_PHYSICAL:
-				MSI_ADDR_DEST_MODE_LOGICAL) |
-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
-				MSI_ADDR_REDIRECTION_CPU:
-				MSI_ADDR_REDIRECTION_LOWPRI) |
-			MSI_ADDR_DEST_ID(dest);
-
-		msg->data =
-			MSI_DATA_TRIGGER_EDGE |
-			MSI_DATA_LEVEL_ASSERT |
-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
-				MSI_DATA_DELIVERY_FIXED:
-				MSI_DATA_DELIVERY_LOWPRI) |
-			MSI_DATA_VECTOR(cfg->vector);
-	}
-	return err;
-}
-
-#ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	struct msi_msg msg;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	read_msi_msg(irq, &msg);
-
-	msg.data &= ~MSI_DATA_VECTOR_MASK;
-	msg.data |= MSI_DATA_VECTOR(cfg->vector);
-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
-
-	write_msi_msg(irq, &msg);
-	desc->affinity = mask;
-}
-
-#ifdef CONFIG_INTR_REMAP
-/*
- * Migrate the MSI irq to another cpumask. This migration is
- * done in the process context using interrupt-remapping hardware.
- */
-static void ir_set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	unsigned int dest;
-	cpumask_t tmp, cleanup_mask;
-	struct irte irte;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (get_irte(irq, &irte))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	irte.vector = cfg->vector;
-	irte.dest_id = IRTE_DEST(dest);
-
-	/*
-	 * atomically update the IRTE with the new destination and vector.
-	 */
-	modify_irte(irq, &irte);
-
-	/*
-	 * After this point, all the interrupts will start arriving
-	 * at the new destination. So, time to cleanup the previous
-	 * vector allocation.
-	 */
-	if (cfg->move_in_progress) {
-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
-		cfg->move_in_progress = 0;
-	}
-
-	desc->affinity = mask;
-}
-#endif
-#endif /* CONFIG_SMP */
-
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
- */
-static struct irq_chip msi_chip = {
-	.name		= "PCI-MSI",
-	.unmask		= unmask_msi_irq,
-	.mask		= mask_msi_irq,
-	.ack		= ack_apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity	= set_msi_irq_affinity,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-#ifdef CONFIG_INTR_REMAP
-static struct irq_chip msi_ir_chip = {
-	.name		= "IR-PCI-MSI",
-	.unmask		= unmask_msi_irq,
-	.mask		= mask_msi_irq,
-	.ack		= ack_x2apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity	= ir_set_msi_irq_affinity,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-/*
- * Map the PCI dev to the corresponding remapping hardware unit
- * and allocate 'nvec' consecutive interrupt-remapping table entries
- * in it.
- */
-static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
-{
-	struct intel_iommu *iommu;
-	int index;
-
-	iommu = map_dev_to_ir(dev);
-	if (!iommu) {
-		printk(KERN_ERR
-		       "Unable to map PCI %s to iommu\n", pci_name(dev));
-		return -ENOENT;
-	}
-
-	index = alloc_irte(iommu, irq, nvec);
-	if (index < 0) {
-		printk(KERN_ERR
-		       "Unable to allocate %d IRTE for PCI %s\n", nvec,
-		        pci_name(dev));
-		return -ENOSPC;
-	}
-	return index;
-}
-#endif
-
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
-{
-	int ret;
-	struct msi_msg msg;
-
-	ret = msi_compose_msg(dev, irq, &msg);
-	if (ret < 0)
-		return ret;
-
-	set_irq_msi(irq, desc);
-	write_msi_msg(irq, &msg);
-
-#ifdef CONFIG_INTR_REMAP
-	if (irq_remapped(irq)) {
-		struct irq_desc *desc = irq_desc(irq);
-		/*
-		 * irq migration in process context
-		 */
-		desc->status |= IRQ_MOVE_PCNTXT;
-		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
-	} else
-#endif
-		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
-
-	return 0;
-}
-
-static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
-{
-	unsigned int irq;
-
-	irq = dev->bus->number;
-	irq <<= 8;
-	irq |= dev->devfn;
-	irq <<= 12;
-
-	return irq;
-}
-
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
-{
-	unsigned int irq;
-	int ret;
-	unsigned int irq_want;
-
-	irq_want = build_irq_for_pci_dev(dev) + 0x100;
-
-	irq = create_irq(irq_want);
-	if (irq == 0)
-		return -1;
-
-#ifdef CONFIG_INTR_REMAP
-	if (!intr_remapping_enabled)
-		goto no_ir;
-
-	ret = msi_alloc_irte(dev, irq, 1);
-	if (ret < 0)
-		goto error;
-no_ir:
-#endif
-	ret = setup_msi_irq(dev, desc, irq);
-	if (ret < 0) {
-		destroy_irq(irq);
-		return ret;
-	}
-	return 0;
-
-#ifdef CONFIG_INTR_REMAP
-error:
-	destroy_irq(irq);
-	return ret;
-#endif
-}
-
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-	unsigned int irq;
-	int ret, sub_handle;
-	struct msi_desc *desc;
-	unsigned int irq_want;
-
-#ifdef CONFIG_INTR_REMAP
-	struct intel_iommu *iommu = 0;
-	int index = 0;
-#endif
-
-	irq_want = build_irq_for_pci_dev(dev) + 0x100;
-	sub_handle = 0;
-	list_for_each_entry(desc, &dev->msi_list, list) {
-		irq = create_irq(irq_want--);
-		if (irq == 0)
-			return -1;
-#ifdef CONFIG_INTR_REMAP
-		if (!intr_remapping_enabled)
-			goto no_ir;
-
-		if (!sub_handle) {
-			/*
-			 * allocate the consecutive block of IRTE's
-			 * for 'nvec'
-			 */
-			index = msi_alloc_irte(dev, irq, nvec);
-			if (index < 0) {
-				ret = index;
-				goto error;
-			}
-		} else {
-			iommu = map_dev_to_ir(dev);
-			if (!iommu) {
-				ret = -ENOENT;
-				goto error;
-			}
-			/*
-			 * setup the mapping between the irq and the IRTE
-			 * base index, the sub_handle pointing to the
-			 * appropriate interrupt remap table entry.
-			 */
-			set_irte_irq(irq, iommu, index, sub_handle);
-		}
-no_ir:
-#endif
-		ret = setup_msi_irq(dev, desc, irq);
-		if (ret < 0)
-			goto error;
-		sub_handle++;
-	}
-	return 0;
-
-error:
-	destroy_irq(irq);
-	return ret;
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
-	destroy_irq(irq);
-}
-
-#ifdef CONFIG_DMAR
-#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	struct msi_msg msg;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	dmar_msi_read(irq, &msg);
-
-	msg.data &= ~MSI_DATA_VECTOR_MASK;
-	msg.data |= MSI_DATA_VECTOR(cfg->vector);
-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
-
-	dmar_msi_write(irq, &msg);
-	desc->affinity = mask;
-}
-#endif /* CONFIG_SMP */
-
-struct irq_chip dmar_msi_type = {
-	.name = "DMAR_MSI",
-	.unmask = dmar_msi_unmask,
-	.mask = dmar_msi_mask,
-	.ack = ack_apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity = dmar_msi_set_affinity,
-#endif
-	.retrigger = ioapic_retrigger_irq,
-};
-
-int arch_setup_dmar_msi(unsigned int irq)
-{
-	int ret;
-	struct msi_msg msg;
-
-	ret = msi_compose_msg(NULL, irq, &msg);
-	if (ret < 0)
-		return ret;
-	dmar_msi_write(irq, &msg);
-	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-		"edge");
-	return 0;
-}
-#endif
-
-#endif /* CONFIG_PCI_MSI */
-/*
- * Hypertransport interrupt support
- */
-#ifdef CONFIG_HT_IRQ
-
-#ifdef CONFIG_SMP
-
-static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
-{
-	struct ht_irq_msg msg;
-	fetch_ht_irq_msg(irq, &msg);
-
-	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
-	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
-
-	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
-	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
-
-	write_ht_irq_msg(irq, &msg);
-}
-
-static void set_ht_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
-{
-	struct irq_cfg *cfg;
-	unsigned int dest;
-	cpumask_t tmp;
-
-	cpus_and(tmp, mask, cpu_online_map);
-	if (cpus_empty(tmp))
-		return;
-
-	if (assign_irq_vector(irq, mask))
-		return;
-
-	cfg = irq_cfg(irq);
-	cpus_and(tmp, cfg->domain, mask);
-	dest = cpu_mask_to_apicid(tmp);
-
-	target_ht_irq(irq, dest, cfg->vector);
-	desc->affinity = mask;
-}
-#endif
-
-static struct irq_chip ht_irq_chip = {
-	.name		= "PCI-HT",
-	.mask		= mask_ht_irq,
-	.unmask		= unmask_ht_irq,
-	.ack		= ack_apic_edge,
-#ifdef CONFIG_SMP
-	.set_affinity	= set_ht_irq_affinity,
-#endif
-	.retrigger	= ioapic_retrigger_irq,
-};
-
-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
-{
-	struct irq_cfg *cfg;
-	int err;
-	cpumask_t tmp;
-
-	tmp = TARGET_CPUS;
-	err = assign_irq_vector(irq, tmp);
-	if (!err) {
-		struct ht_irq_msg msg;
-		unsigned dest;
-
-		cfg = irq_cfg(irq);
-		cpus_and(tmp, cfg->domain, tmp);
-		dest = cpu_mask_to_apicid(tmp);
-
-		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
-
-		msg.address_lo =
-			HT_IRQ_LOW_BASE |
-			HT_IRQ_LOW_DEST_ID(dest) |
-			HT_IRQ_LOW_VECTOR(cfg->vector) |
-			((INT_DEST_MODE == 0) ?
-				HT_IRQ_LOW_DM_PHYSICAL :
-				HT_IRQ_LOW_DM_LOGICAL) |
-			HT_IRQ_LOW_RQEOI_EDGE |
-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
-				HT_IRQ_LOW_MT_FIXED :
-				HT_IRQ_LOW_MT_ARBITRATED) |
-			HT_IRQ_LOW_IRQ_MASKED;
-
-		write_ht_irq_msg(irq, &msg);
-
-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
-					      handle_edge_irq, "edge");
-	}
-	return err;
-}
-#endif /* CONFIG_HT_IRQ */
-
-/* --------------------------------------------------------------------------
-                          ACPI-based IOAPIC Configuration
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI
-
-#ifdef CONFIG_X86_32
-int __init io_apic_get_unique_id(int ioapic, int apic_id)
-{
-	union IO_APIC_reg_00 reg_00;
-	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
-	physid_mask_t tmp;
-	unsigned long flags;
-	int i = 0;
-
-	/*
-	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
-	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
-	 * supports up to 16 on one shared APIC bus.
-	 *
-	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
-	 *      advantage of new APIC bus architecture.
-	 */
-
-	if (physids_empty(apic_id_map))
-		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(ioapic, 0);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	if (apic_id >= get_physical_broadcast()) {
-		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
-			"%d\n", ioapic, apic_id, reg_00.bits.ID);
-		apic_id = reg_00.bits.ID;
-	}
-
-	/*
-	 * Every APIC in a system must have a unique ID or we get lots of nice
-	 * 'stuck on smp_invalidate_needed IPI wait' messages.
-	 */
-	if (check_apicid_used(apic_id_map, apic_id)) {
-
-		for (i = 0; i < get_physical_broadcast(); i++) {
-			if (!check_apicid_used(apic_id_map, i))
-				break;
-		}
-
-		if (i == get_physical_broadcast())
-			panic("Max apic_id exceeded!\n");
-
-		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
-			"trying %d\n", ioapic, apic_id, i);
-
-		apic_id = i;
-	}
-
-	tmp = apicid_to_cpu_present(apic_id);
-	physids_or(apic_id_map, apic_id_map, tmp);
-
-	if (reg_00.bits.ID != apic_id) {
-		reg_00.bits.ID = apic_id;
-
-		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(ioapic, 0, reg_00.raw);
-		reg_00.raw = io_apic_read(ioapic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-
-		/* Sanity check */
-		if (reg_00.bits.ID != apic_id) {
-			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
-			return -1;
-		}
-	}
-
-	apic_printk(APIC_VERBOSE, KERN_INFO
-			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
-
-	return apic_id;
-}
-
-int __init io_apic_get_version(int ioapic)
-{
-	union IO_APIC_reg_01	reg_01;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return reg_01.bits.version;
-}
-#endif
-
-int __init io_apic_get_redir_entries (int ioapic)
-{
-	union IO_APIC_reg_01	reg_01;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ioapic_lock, flags);
-	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
-
-	return reg_01.bits.entries;
-}
-
-
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
-{
-	if (!IO_APIC_IRQ(irq)) {
-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
-			ioapic);
-		return -EINVAL;
-	}
-
-	/*
-	 * IRQs < 16 are already in the irq_2_pin[] map
-	 */
-	if (irq >= 16)
-		add_pin_to_irq(irq, ioapic, pin);
-
-	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
-
-	return 0;
-}
-
-
-int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
-{
-	int i;
-
-	if (skip_ioapic_setup)
-		return -1;
-
-	for (i = 0; i < mp_irq_entries; i++)
-		if (mp_irqs[i].mp_irqtype == mp_INT &&
-		    mp_irqs[i].mp_srcbusirq == bus_irq)
-			break;
-	if (i >= mp_irq_entries)
-		return -1;
-
-	*trigger = irq_trigger(i);
-	*polarity = irq_polarity(i);
-	return 0;
-}
-
-#endif /* CONFIG_ACPI */
-
-/*
- * This function currently is only a helper for the i386 smp boot process where
- * we need to reprogram the ioredtbls to cater for the cpus which have come online
- * so mask in all cases should simply be TARGET_CPUS
- */
-#ifdef CONFIG_SMP
-void __init setup_ioapic_dest(void)
-{
-	int pin, ioapic, irq, irq_entry;
-	struct irq_cfg *cfg;
-	struct irq_desc *desc;
-
-	if (skip_ioapic_setup == 1)
-		return;
-
-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
-			if (irq_entry == -1)
-				continue;
-			irq = pin_2_irq(irq_entry, ioapic, pin);
-
-			/* setup_IO_APIC_irqs could fail to get vector for some device
-			 * when you have too many devices, because at that time only boot
-			 * cpu is online.
-			 */
-			cfg = irq_cfg(irq);
-			if (!cfg->vector)
-				setup_IO_APIC_irq(ioapic, pin, irq,
-						  irq_trigger(irq_entry),
-						  irq_polarity(irq_entry));
-#ifdef CONFIG_INTR_REMAP
-			else if (intr_remapping_enabled) {
-				desc = irq_desc(irq);
-				set_ir_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-			}
-#endif
-			else {
-				desc = irq_desc(irq);
-				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-			}
-		}
-	}
-}
-#endif
-
-#ifdef CONFIG_X86_64
-#define IOAPIC_RESOURCE_NAME_SIZE 11
-
-static struct resource *ioapic_resources;
-
-static struct resource * __init ioapic_setup_resources(void)
-{
-	unsigned long n;
-	struct resource *res;
-	char *mem;
-	int i;
-
-	if (nr_ioapics <= 0)
-		return NULL;
-
-	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
-	n *= nr_ioapics;
-
-	mem = alloc_bootmem(n);
-	res = (void *)mem;
-
-	if (mem != NULL) {
-		mem += sizeof(struct resource) * nr_ioapics;
-
-		for (i = 0; i < nr_ioapics; i++) {
-			res[i].name = mem;
-			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-			sprintf(mem,  "IOAPIC %u", i);
-			mem += IOAPIC_RESOURCE_NAME_SIZE;
-		}
-	}
-
-	ioapic_resources = res;
-
-	return res;
-}
-#endif
-
-void __init ioapic_init_mappings(void)
-{
-	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-	int i;
-#ifdef CONFIG_X86_64
-	struct resource *ioapic_res;
-
-	ioapic_res = ioapic_setup_resources();
-#endif
-	for (i = 0; i < nr_ioapics; i++) {
-		if (smp_found_config) {
-			ioapic_phys = mp_ioapics[i].mp_apicaddr;
-#ifdef CONFIG_X86_32
-                        if (!ioapic_phys) {
-                                printk(KERN_ERR
-                                       "WARNING: bogus zero IO-APIC "
-                                       "address found in MPTABLE, "
-                                       "disabling IO/APIC support!\n");
-                                smp_found_config = 0;
-                                skip_ioapic_setup = 1;
-                                goto fake_ioapic_page;
-                        }
-#endif
-		} else {
-#ifdef CONFIG_X86_32
-fake_ioapic_page:
-#endif
-			ioapic_phys = (unsigned long)
-				alloc_bootmem_pages(PAGE_SIZE);
-			ioapic_phys = __pa(ioapic_phys);
-		}
-		set_fixmap_nocache(idx, ioapic_phys);
-		apic_printk(APIC_VERBOSE,
-			    "mapped IOAPIC to %08lx (%08lx)\n",
-			    __fix_to_virt(idx), ioapic_phys);
-		idx++;
-
-#ifdef CONFIG_X86_64
-		if (ioapic_res != NULL) {
-			ioapic_res->start = ioapic_phys;
-			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
-			ioapic_res++;
-		}
-#endif
-	}
-}
-
-#ifdef CONFIG_X86_64
-static int __init ioapic_insert_resources(void)
-{
-	int i;
-	struct resource *r = ioapic_resources;
-
-	if (!r) {
-		printk(KERN_ERR
-		       "IO APIC resources could be not be allocated.\n");
-		return -1;
-	}
-
-	for (i = 0; i < nr_ioapics; i++) {
-		insert_resource(&iomem_resource, r);
-		r++;
-	}
-
-	return 0;
-}
-
-/* Insert the IO APIC resources after PCI initialization has occured to handle
- * IO APICS that are mapped in on a BAR in PCI space. */
-late_initcall(ioapic_insert_resources);
-#endif

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 7/7] make 32 bit have io_apic resource in /proc/iomem
  2008-08-15 23:42             ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Yinghai Lu
@ 2008-08-15 23:42               ` Yinghai Lu
  2008-08-16  8:02               ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Ingo Molnar
  1 sibling, 0 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-15 23:42 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton
  Cc: linux-kernel, Yinghai Lu

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/x86/kernel/io_apic.c |    8 --------
 1 file changed, 8 deletions(-)

Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -3785,7 +3785,6 @@ void __init setup_ioapic_dest(void)
 }
 #endif
 
-#ifdef CONFIG_X86_64
 #define IOAPIC_RESOURCE_NAME_SIZE 11
 
 static struct resource *ioapic_resources;
@@ -3821,17 +3820,14 @@ static struct resource * __init ioapic_s
 
 	return res;
 }
-#endif
 
 void __init ioapic_init_mappings(void)
 {
 	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
 	int i;
-#ifdef CONFIG_X86_64
 	struct resource *ioapic_res;
 
 	ioapic_res = ioapic_setup_resources();
-#endif
 	for (i = 0; i < nr_ioapics; i++) {
 		if (smp_found_config) {
 			ioapic_phys = mp_ioapics[i].mp_apicaddr;
@@ -3860,17 +3856,14 @@ fake_ioapic_page:
 			    __fix_to_virt(idx), ioapic_phys);
 		idx++;
 
-#ifdef CONFIG_X86_64
 		if (ioapic_res != NULL) {
 			ioapic_res->start = ioapic_phys;
 			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
 			ioapic_res++;
 		}
-#endif
 	}
 }
 
-#ifdef CONFIG_X86_64
 static int __init ioapic_insert_resources(void)
 {
 	int i;
@@ -3893,4 +3886,3 @@ static int __init ioapic_insert_resource
 /* Insert the IO APIC resources after PCI initialization has occured to handle
  * IO APICS that are mapped in on a BAR in PCI space. */
 late_initcall(ioapic_insert_resources);
-#endif

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 6/7] rename io_apic_64.c to io_apic.c
  2008-08-15 23:42             ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Yinghai Lu
  2008-08-15 23:42               ` [PATCH 7/7] make 32 bit have io_apic resource in /proc/iomem Yinghai Lu
@ 2008-08-16  8:02               ` Ingo Molnar
  2008-08-16  8:22                 ` [PATCH] x86: io_apic.c, build fix Ingo Molnar
  1 sibling, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-16  8:02 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
> 
> ---
>  arch/x86/kernel/Makefile     |    2 
>  arch/x86/kernel/io_apic.c    | 3898 +++++++++++++++++++++++++++++++++++++++++++
>  arch/x86/kernel/io_apic_32.c | 3220 -----------------------------------
>  arch/x86/kernel/io_apic_64.c | 3898 -------------------------------------------
>  4 files changed, 3899 insertions(+), 7119 deletions(-)

very nice stuff!

Could we please make this rename more mechanic? Ie. more intermediate 
changes (or a single change, if it's safe enough) that makes 
io_apic_32.c equal to io_apic_64.c - and _then_ do the rename, ok?

I've looked at the diff (see it below), and there seem to be material 
differences.

Also, the move introduces bogus style that is still present on the 
64-bit side:

-static void mask_IO_APIC_irq(unsigned int irq)
+static void mask_IO_APIC_irq (unsigned int irq)

i'll put it all into tip/irq/sparseirq, to start testing it - but these 
changes _will_ be bisected to so it needs to be as finegrained as 
possible.

	Ingo

1 file changed, 1090 insertions(+), 414 deletions(-)

--- arch/x86/kernel/io_apic_32.c	2008-08-16 09:58:52.000000000 +0200
+++ arch/x86/kernel/io_apic_64.c	2008-08-16 09:58:52.000000000 +0200
@@ -35,7 +35,7 @@
 #include <linux/htirq.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
-#include <linux/jiffies.h>      /* time_after() */
+#include <linux/jiffies.h>	/* time_after() */
 #ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
 #endif
@@ -64,8 +64,8 @@
 #define __apicdebuginit(type) static type __init
 
 /*
- *	Is the SiS APIC rmw bug present ?
- *	-1 = don't know, 0 = no, 1 = yes
+ *      Is the SiS APIC rmw bug present ?
+ *      -1 = don't know, 0 = no, 1 = yes
  */
 int sis_apic_bug = -1;
 
@@ -102,7 +102,7 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BU
 
 int skip_ioapic_setup;
 
-static int __init parse_noapic(char *arg)
+static int __init parse_noapic(char *str)
 {
 	/* disable IO-APIC */
 	disable_ioapic_setup();
@@ -188,7 +188,7 @@ static void __init init_work(void *data)
 	irq_cfgx[legacy_count - 1].next = NULL;
 }
 
-#define for_each_irq_cfg(cfg)           \
+#define for_each_irq_cfg(cfg)		\
 	for (cfg = irq_cfgx; cfg; cfg = cfg->next)
 
 DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
@@ -262,7 +262,6 @@ static struct irq_cfg *irq_cfg_with_new(
 		irq_cfgx = cfg;
 	cfg->irq = irq;
 	printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
-
 #ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
 	{
 		/* dump the results */
@@ -384,9 +383,9 @@ static inline void io_apic_write(unsigne
  */
 static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
-	volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
-	if (sis_apic_bug)
-		writel(reg, &io_apic->index);
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+        if (sis_apic_bug)
+                writel(reg, &io_apic->index);
 	writel(value, &io_apic->data);
 }
 
@@ -494,11 +493,20 @@ static void __target_IO_APIC_irq(unsigne
 
 		apic = entry->apic;
 		pin = entry->pin;
+#ifdef CONFIG_INTR_REMAP
+		/*
+		 * With interrupt-remapping, destination information comes
+		 * from interrupt-remapping table entry.
+		 */
+		if (!irq_remapped(irq))
+			io_apic_write(apic, 0x11 + pin*2, dest);
+#else
 		io_apic_write(apic, 0x11 + pin*2, dest);
+#endif
 		reg = io_apic_read(apic, 0x10 + pin*2);
 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
 		reg |= vector;
-		io_apic_modify(apic, 0x10 + pin *2, reg);
+		io_apic_modify(apic, 0x10 + pin*2, reg);
 		if (!entry->next)
 			break;
 		entry = entry->next;
@@ -534,7 +542,6 @@ static void set_ioapic_affinity_irq(unsi
 	desc->affinity = mask;
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
-
 #endif /* CONFIG_SMP */
 
 /*
@@ -699,7 +706,7 @@ static void __unmask_and_level_IO_APIC_i
 
 #endif
 
-static void mask_IO_APIC_irq(unsigned int irq)
+static void mask_IO_APIC_irq (unsigned int irq)
 {
 	unsigned long flags;
 
@@ -708,7 +715,7 @@ static void mask_IO_APIC_irq(unsigned in
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void unmask_IO_APIC_irq(unsigned int irq)
+static void unmask_IO_APIC_irq (unsigned int irq)
 {
 	unsigned long flags;
 
@@ -725,14 +732,13 @@ static void clear_IO_APIC_pin(unsigned i
 	entry = ioapic_read_entry(apic, pin);
 	if (entry.delivery_mode == dest_SMI)
 		return;
-
 	/*
 	 * Disable it in the IO-APIC irq-routing table:
 	 */
 	ioapic_mask_entry(apic, pin);
 }
 
-static void clear_IO_APIC(void)
+static void clear_IO_APIC (void)
 {
 	int apic, pin;
 
@@ -741,7 +747,7 @@ static void clear_IO_APIC(void)
 			clear_IO_APIC_pin(apic, pin);
 }
 
-#ifndef CONFIG_SMP
+#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
 void send_IPI_self(int vector)
 {
 	unsigned int cfg;
@@ -756,9 +762,9 @@ void send_IPI_self(int vector)
 	 */
 	apic_write(APIC_ICR, cfg);
 }
-#endif /* !CONFIG_SMP */
-
+#endif /* !CONFIG_SMP && CONFIG_X86_32*/
 
+#ifdef CONFIG_X86_32
 /*
  * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
  * specific CPU-side IRQs.
@@ -797,6 +803,75 @@ static int __init ioapic_pirq_setup(char
 }
 
 __setup("pirq=", ioapic_pirq_setup);
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_INTR_REMAP
+/* I/O APIC RTE contents at the OS boot up */
+static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
+
+/*
+ * Saves and masks all the unmasked IO-APIC RTE's
+ */
+int save_mask_IO_APIC_setup(void)
+{
+	union IO_APIC_reg_01 reg_01;
+	unsigned long flags;
+	int apic, pin;
+
+	/*
+	 * The number of IO-APIC IRQ registers (== #pins):
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_01.raw = io_apic_read(apic, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+	}
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		early_ioapic_entries[apic] =
+			kzalloc(sizeof(struct IO_APIC_route_entry) *
+				nr_ioapic_registers[apic], GFP_KERNEL);
+		if (!early_ioapic_entries[apic])
+			return -ENOMEM;
+	}
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+
+			entry = early_ioapic_entries[apic][pin] =
+				ioapic_read_entry(apic, pin);
+			if (!entry.mask) {
+				entry.mask = 1;
+				ioapic_write_entry(apic, pin, entry);
+			}
+		}
+	return 0;
+}
+
+void restore_IO_APIC_setup(void)
+{
+	int apic, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			ioapic_write_entry(apic, pin,
+					   early_ioapic_entries[apic][pin]);
+}
+
+void reinit_intr_remapped_IO_APIC(int intr_remapping)
+{
+	/*
+	 * for now plain restore of previous settings.
+	 * TBD: In the case of OS enabling interrupt-remapping,
+	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
+	 * table entries. for now, do a plain restore, and wait for
+	 * the setup_IO_APIC_irqs() to do proper initialization.
+	 */
+	restore_IO_APIC_setup();
+}
+#endif
 
 /*
  * Find the IRQ entry number of a certain pin.
@@ -848,7 +923,7 @@ static int __init find_isa_irq_apic(int 
 	}
 	if (i < mp_irq_entries) {
 		int apic;
-		for (apic = 0; apic < nr_ioapics; apic++) {
+		for(apic = 0; apic < nr_ioapics; apic++) {
 			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
 				return apic;
 		}
@@ -867,10 +942,10 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
 {
 	int apic, i, best_guess = -1;
 
-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
-		"slot:%d, pin:%d.\n", bus, slot, pin);
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+		bus, slot, pin);
 	if (test_bit(bus, mp_bus_not_pci)) {
-		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
 	}
 	for (i = 0; i < mp_irq_entries; i++) {
@@ -885,7 +960,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
 		    !mp_irqs[i].mp_irqtype &&
 		    (bus == lbus) &&
 		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
-			int irq = pin_2_irq(i, apic, mp_irqs[i].mp_dstirq);
+			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
 
 			if (!(apic || IO_APIC_IRQ(irq)))
 				continue;
@@ -902,6 +977,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
 	}
 	return best_guess;
 }
+
 EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
@@ -918,6 +994,7 @@ static int EISA_ELCR(unsigned int irq)
 			"Broken MPtable reports ISA irq %d\n", irq);
 	return 0;
 }
+
 #endif
 
 /* ISA interrupts are always polarity zero edge triggered,
@@ -931,8 +1008,8 @@ static int EISA_ELCR(unsigned int irq)
  * EISA conforming in the MP table, that means its trigger type must
  * be read in from the ELCR */
 
-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
-#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
 
 /* PCI interrupts are always polarity one level triggered,
  * when listed as conforming in the MP table. */
@@ -940,11 +1017,14 @@ static int EISA_ELCR(unsigned int irq)
 #define default_PCI_trigger(idx)	(1)
 #define default_PCI_polarity(idx)	(1)
 
-/* MCA interrupts are always polarity zero level triggered,
- * when listed as conforming in the MP table. */
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+#define default_EISA_polarity(idx)      default_ISA_polarity(idx)
 
-#define default_MCA_trigger(idx)	(1)
-#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
 
 static int MPBIOS_polarity(int idx)
 {
@@ -954,36 +1034,36 @@ static int MPBIOS_polarity(int idx)
 	/*
 	 * Determine IRQ line polarity (high active or low active):
 	 */
-	switch (mp_irqs[idx].mp_irqflag & 3) {
-	case 0: /* conforms, ie. bus-type dependent polarity */
-	{
-		polarity = test_bit(bus, mp_bus_not_pci)?
-			default_ISA_polarity(idx):
-			default_PCI_polarity(idx);
-		break;
-	}
-	case 1: /* high active */
+	switch (mp_irqs[idx].mp_irqflag & 3)
 	{
-		polarity = 0;
-		break;
-	}
-	case 2: /* reserved */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		polarity = 1;
-		break;
-	}
-	case 3: /* low active */
-	{
-		polarity = 1;
-		break;
-	}
-	default: /* invalid */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		polarity = 1;
-		break;
-	}
+		case 0: /* conforms, ie. bus-type dependent polarity */
+			if (test_bit(bus, mp_bus_not_pci))
+				polarity = default_ISA_polarity(idx);
+			else
+				polarity = default_PCI_polarity(idx);
+			break;
+		case 1: /* high active */
+		{
+			polarity = 0;
+			break;
+		}
+		case 2: /* reserved */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
+		case 3: /* low active */
+		{
+			polarity = 1;
+			break;
+		}
+		default: /* invalid */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
 	}
 	return polarity;
 }
@@ -996,67 +1076,67 @@ static int MPBIOS_trigger(int idx)
 	/*
 	 * Determine IRQ trigger mode (edge or level sensitive):
 	 */
-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3) {
-	case 0: /* conforms, ie. bus-type dependent */
+	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
 	{
-		trigger = test_bit(bus, mp_bus_not_pci)?
-				default_ISA_trigger(idx):
-				default_PCI_trigger(idx);
+		case 0: /* conforms, ie. bus-type dependent */
+			if (test_bit(bus, mp_bus_not_pci))
+				trigger = default_ISA_trigger(idx);
+			else
+				trigger = default_PCI_trigger(idx);
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
-		switch (mp_bus_id_to_type[bus]) {
-		case MP_BUS_ISA: /* ISA pin */
-		{
-			/* set before the switch */
+			switch (mp_bus_id_to_type[bus]) {
+				case MP_BUS_ISA: /* ISA pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_EISA: /* EISA pin */
+				{
+					trigger = default_EISA_trigger(idx);
+					break;
+				}
+				case MP_BUS_PCI: /* PCI pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_MCA: /* MCA pin */
+				{
+					trigger = default_MCA_trigger(idx);
+					break;
+				}
+				default:
+				{
+					printk(KERN_WARNING "broken BIOS!!\n");
+					trigger = 1;
+					break;
+				}
+			}
+#endif
 			break;
-		}
-		case MP_BUS_EISA: /* EISA pin */
+		case 1: /* edge */
 		{
-			trigger = default_EISA_trigger(idx);
+			trigger = 0;
 			break;
 		}
-		case MP_BUS_PCI: /* PCI pin */
+		case 2: /* reserved */
 		{
-			/* set before the switch */
+			printk(KERN_WARNING "broken BIOS!!\n");
+			trigger = 1;
 			break;
 		}
-		case MP_BUS_MCA: /* MCA pin */
+		case 3: /* level */
 		{
-			trigger = default_MCA_trigger(idx);
+			trigger = 1;
 			break;
 		}
-		default:
+		default: /* invalid */
 		{
 			printk(KERN_WARNING "broken BIOS!!\n");
-			trigger = 1;
+			trigger = 0;
 			break;
 		}
 	}
-#endif
-		break;
-	}
-	case 1: /* edge */
-	{
-		trigger = 0;
-		break;
-	}
-	case 2: /* reserved */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		trigger = 1;
-		break;
-	}
-	case 3: /* level */
-	{
-		trigger = 1;
-		break;
-	}
-	default: /* invalid */
-	{
-		printk(KERN_WARNING "broken BIOS!!\n");
-		trigger = 0;
-		break;
-	}
-	}
 	return trigger;
 }
 
@@ -1082,9 +1162,9 @@ static int pin_2_irq(int idx, int apic, 
 	if (mp_irqs[idx].mp_dstirq != pin)
 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
 
-	if (test_bit(bus, mp_bus_not_pci))
+	if (test_bit(bus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].mp_srcbusirq;
-	else {
+	} else {
 		/*
 		 * PCI IRQs are mapped in order
 		 */
@@ -1092,14 +1172,14 @@ static int pin_2_irq(int idx, int apic, 
 		while (i < apic)
 			irq += nr_ioapic_registers[i++];
 		irq += pin;
-
-		/*
-		 * For MPS mode, so far only needed by ES7000 platform
-		 */
-		if (ioapic_renumber_irq)
-			irq = ioapic_renumber_irq(apic, irq);
+                /*
+                 * For MPS mode, so far only needed by ES7000 platform
+                 */
+                if (ioapic_renumber_irq)
+                        irq = ioapic_renumber_irq(apic, irq);
 	}
 
+#ifdef CONFIG_X86_32
 	/*
 	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
 	 */
@@ -1116,6 +1196,8 @@ static int pin_2_irq(int idx, int apic, 
 			}
 		}
 	}
+#endif
+
 	return irq;
 }
 
@@ -1145,74 +1227,70 @@ static int __assign_irq_vector(int irq, 
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-        static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
-        unsigned int old_vector;
-        int cpu;
-        struct irq_cfg *cfg;
-
-        cfg = irq_cfg(irq);
-
-        /* Only try and allocate irqs on cpus that are present */
-        cpus_and(mask, mask, cpu_online_map);
-
-        if ((cfg->move_in_progress) || cfg->move_cleanup_count)
-                return -EBUSY;
-
-        old_vector = cfg->vector;
-        if (old_vector) {
-                cpumask_t tmp;
-                cpus_and(tmp, cfg->domain, mask);
-                if (!cpus_empty(tmp))
-                        return 0;
-        }
+	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	unsigned int old_vector;
+	int cpu;
+	struct irq_cfg *cfg;
+
+	cfg = irq_cfg(irq);
+
+	/* Only try and allocate irqs on cpus that are present */
+	cpus_and(mask, mask, cpu_online_map);
 
-        for_each_cpu_mask_nr(cpu, mask) {
-                cpumask_t domain, new_mask;
-                int new_cpu;
-                int vector, offset;
+	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+		return -EBUSY;
 
-                domain = vector_allocation_domain(cpu);
-                cpus_and(new_mask, domain, cpu_online_map);
+	old_vector = cfg->vector;
+	if (old_vector) {
+		cpumask_t tmp;
+		cpus_and(tmp, cfg->domain, mask);
+		if (!cpus_empty(tmp))
+			return 0;
+	}
+
+	for_each_cpu_mask_nr(cpu, mask) {
+		cpumask_t domain, new_mask;
+		int new_cpu;
+		int vector, offset;
 
-                vector = current_vector;
-                offset = current_offset;
+		domain = vector_allocation_domain(cpu);
+		cpus_and(new_mask, domain, cpu_online_map);
+
+		vector = current_vector;
+		offset = current_offset;
 next:
-                vector += 8;
-                if (vector >= first_system_vector) {
-                        /* If we run out of vectors on large boxen, must share them. */
-                        offset = (offset + 1) % 8;
-                        vector = FIRST_DEVICE_VECTOR + offset;
-                }
-                if (unlikely(current_vector == vector))
-                        continue;
+		vector += 8;
+		if (vector >= first_system_vector) {
+			/* If we run out of vectors on large boxen, must share them. */
+			offset = (offset + 1) % 8;
+			vector = FIRST_DEVICE_VECTOR + offset;
+		}
+		if (unlikely(current_vector == vector))
+			continue;
 #ifdef CONFIG_X86_64
-                if (vector == IA32_SYSCALL_VECTOR)
-                        goto next;
+		if (vector == IA32_SYSCALL_VECTOR)
+			goto next;
 #else
-                if (vector == SYSCALL_VECTOR)
-                        goto next;
+		if (vector == SYSCALL_VECTOR)
+			goto next;
 #endif
-                for_each_cpu_mask_nr(new_cpu, new_mask)
-                        if (per_cpu(vector_irq, new_cpu)[vector] != -1)
-                                goto next;
-                /* Found one! */
-                current_vector = vector;
-                current_offset = offset;
-                if (old_vector) {
-                        cfg->move_in_progress = 1;
-                        cfg->old_domain = cfg->domain;
-                }
-		printk(KERN_DEBUG "assign_irq_vector: irq %d vector %#x cpu ", irq, vector);
-		for_each_cpu_mask_nr(new_cpu, new_mask) {
-			per_cpu(vector_irq, new_cpu)[vector] = irq;
-			printk(KERN_CONT " %d ", new_cpu);
+		for_each_cpu_mask_nr(new_cpu, new_mask)
+			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
+				goto next;
+		/* Found one! */
+		current_vector = vector;
+		current_offset = offset;
+		if (old_vector) {
+			cfg->move_in_progress = 1;
+			cfg->old_domain = cfg->domain;
 		}
-		printk(KERN_CONT "\n");
-                cfg->vector = vector;
-                cfg->domain = domain;
-                return 0;
-        }
-        return -ENOSPC;
+		for_each_cpu_mask_nr(new_cpu, new_mask)
+			per_cpu(vector_irq, new_cpu)[vector] = irq;
+		cfg->vector = vector;
+		cfg->domain = domain;
+		return 0;
+	}
+	return -ENOSPC;
 }
 
 static int assign_irq_vector(int irq, cpumask_t mask)
@@ -1223,7 +1301,6 @@ static int assign_irq_vector(int irq, cp
 	spin_lock_irqsave(&vector_lock, flags);
 	err = __assign_irq_vector(irq, mask);
 	spin_unlock_irqrestore(&vector_lock, flags);
-
 	return err;
 }
 
@@ -1269,36 +1346,39 @@ void __setup_vector_irq(int cpu)
 		cfg = irq_cfg(irq);
 		if (!cpu_isset(cpu, cfg->domain))
 			per_cpu(vector_irq, cpu)[vector] = -1;
-        }
+	}
 }
 
 static struct irq_chip ioapic_chip;
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip;
+#endif
 
-#define IOAPIC_AUTO	-1
-#define IOAPIC_EDGE	0
-#define IOAPIC_LEVEL	1
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
 
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
 {
-	int apic, idx, pin;
+        int apic, idx, pin;
 
-	for (apic = 0; apic < nr_ioapics; apic++) {
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			idx = find_irq_entry(apic, pin, mp_INT);
-			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-				return irq_trigger(idx);
-		}
-	}
-	/*
-	 * nonexistent IRQs are edge default
-	 */
-	return 0;
+        for (apic = 0; apic < nr_ioapics; apic++) {
+                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                        idx = find_irq_entry(apic, pin, mp_INT);
+                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+                                return irq_trigger(idx);
+                }
+        }
+        /*
+         * nonexistent IRQs are edge default
+         */
+        return 0;
 }
 #else
 static inline int IO_APIC_irq_trigger(int irq)
 {
-        return 1;
+	return 1;
 }
 #endif
 
@@ -1318,13 +1398,27 @@ static void ioapic_register_intr(int irq
 	else
 		desc->status &= ~IRQ_LEVEL;
 
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		desc->status |= IRQ_MOVE_PCNTXT;
+		if (trigger)
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_fasteoi_irq,
+						     "fasteoi");
+		else
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_edge_irq, "edge");
+		return;
+	}
+#endif
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 	    trigger == IOAPIC_LEVEL)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					 handle_fasteoi_irq, "fasteoi");
+					      handle_fasteoi_irq,
+					      "fasteoi");
 	else
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					 handle_edge_irq, "edge");
+					      handle_edge_irq, "edge");
 }
 
 static int setup_ioapic_entry(int apic, int irq,
@@ -1337,11 +1431,45 @@ static int setup_ioapic_entry(int apic, 
 	 */
 	memset(entry,0,sizeof(*entry));
 
-	entry->delivery_mode = INT_DELIVERY_MODE;
-	entry->dest_mode = INT_DEST_MODE;
-	entry->dest = destination;
+#ifdef CONFIG_INTR_REMAP
+	if (intr_remapping_enabled) {
+		struct intel_iommu *iommu = map_ioapic_to_ir(apic);
+		struct irte irte;
+		struct IR_IO_APIC_route_entry *ir_entry =
+			(struct IR_IO_APIC_route_entry *) entry;
+		int index;
+
+		if (!iommu)
+			panic("No mapping iommu for ioapic %d\n", apic);
+
+		index = alloc_irte(iommu, irq, 1);
+		if (index < 0)
+			panic("Failed to allocate IRTE for ioapic %d\n", apic);
+
+		memset(&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = INT_DEST_MODE;
+		irte.trigger_mode = trigger;
+		irte.dlvry_mode = INT_DELIVERY_MODE;
+		irte.vector = vector;
+		irte.dest_id = IRTE_DEST(destination);
+
+		modify_irte(irq, &irte);
+
+		ir_entry->index2 = (index >> 15) & 0x1;
+		ir_entry->zero = 0;
+		ir_entry->format = 1;
+		ir_entry->index = (index & 0x7fff);
+	} else
+#endif
+	{
+		entry->delivery_mode = INT_DELIVERY_MODE;
+		entry->dest_mode = INT_DEST_MODE;
+		entry->dest = destination;
+	}
 
-	entry->mask = 0;                                /* enable IRQ */
+	entry->mask = 0;				/* enable IRQ */
 	entry->trigger = trigger;
 	entry->polarity = polarity;
 	entry->vector = vector;
@@ -1351,12 +1479,11 @@ static int setup_ioapic_entry(int apic, 
 	 */
 	if (trigger)
 		entry->mask = 1;
-
 	return 0;
 }
 
 static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
-                              int trigger, int polarity)
+			      int trigger, int polarity)
 {
 	struct irq_cfg *cfg;
 	struct IO_APIC_route_entry entry;
@@ -1420,10 +1547,10 @@ static void __init setup_IO_APIC_irqs(vo
 		}
 
 		irq = pin_2_irq(idx, apic, pin);
-
+#ifdef CONFIG_X86_32
                 if (multi_timer_check(apic, irq))
                         continue;
-
+#endif
 		add_pin_to_irq(irq, apic, pin);
 
 		setup_IO_APIC_irq(apic, pin, irq,
@@ -1443,6 +1570,11 @@ static void __init setup_timer_IRQ0_pin(
 {
 	struct IO_APIC_route_entry entry;
 
+#ifdef CONFIG_INTR_REMAP
+	if (intr_remapping_enabled)
+		return;
+#endif
+
 	memset(&entry, 0, sizeof(entry));
 
 	/*
@@ -1461,7 +1593,7 @@ static void __init setup_timer_IRQ0_pin(
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we may have a 8259A-master in AEOI mode ...
 	 */
-	ioapic_register_intr(0, IOAPIC_EDGE);
+	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -1501,17 +1633,18 @@ __apicdebuginit(void) print_IO_APIC(void
 	reg_01.raw = io_apic_read(apic, 1);
 	if (reg_01.bits.version >= 0x10)
 		reg_02.raw = io_apic_read(apic, 2);
-	if (reg_01.bits.version >= 0x20)
-		reg_03.raw = io_apic_read(apic, 3);
+        if (reg_01.bits.version >= 0x20)
+                reg_03.raw = io_apic_read(apic, 3);
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
+	printk("\n");
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
 	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
 
-	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
 
 	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
@@ -1548,7 +1681,10 @@ __apicdebuginit(void) print_IO_APIC(void
 
 		entry = ioapic_read_entry(apic, i);
 
-		printk(KERN_DEBUG " %02x %02X  ", i, entry.dest);
+		printk(KERN_DEBUG " %02x %03X ",
+			i,
+			entry.dest
+		);
 
 		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
 			entry.mask,
@@ -1567,7 +1703,7 @@ __apicdebuginit(void) print_IO_APIC(void
 		struct irq_pin_list *entry = cfg->irq_2_pin;
 		if (!entry)
 			continue;
-		printk(KERN_DEBUG "IRQ%d ", i);
+		printk(KERN_DEBUG "IRQ%d ", cfg->irq);
 		for (;;) {
 			printk("-> %d:%d", entry->apic, entry->pin);
 			if (!entry->next)
@@ -1614,8 +1750,7 @@ __apicdebuginit(void) print_local_APIC(v
 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
-			GET_APIC_ID(v));
+	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
 	v = apic_read(APIC_LVR);
 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
 	ver = GET_APIC_VERSION(v);
@@ -1624,7 +1759,7 @@ __apicdebuginit(void) print_local_APIC(v
 	v = apic_read(APIC_TASKPRI);
 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
-	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
+	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
 		v = apic_read(APIC_ARBPRI);
 		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
 			v & APIC_ARBPRI_MASK);
@@ -1650,9 +1785,10 @@ __apicdebuginit(void) print_local_APIC(v
 	printk(KERN_DEBUG "... APIC IRR field:\n");
 	print_APIC_bitfield(APIC_IRR);
 
-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
+	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
+		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
+
 		v = apic_read(APIC_ESR);
 		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
 	}
@@ -1710,11 +1846,11 @@ __apicdebuginit(void) print_PIC(void)
 	v = inb(0xa0) << 8 | inb(0x20);
 	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
 
-	outb(0x0b, 0xa0);
-	outb(0x0b, 0x20);
+	outb(0x0b,0xa0);
+	outb(0x0b,0x20);
 	v = inb(0xa0) << 8 | inb(0x20);
-	outb(0x0a, 0xa0);
-	outb(0x0a, 0x20);
+	outb(0x0a,0xa0);
+	outb(0x0a,0x20);
 
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 
@@ -1739,16 +1875,19 @@ fs_initcall(print_all_ICs);
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
-static void __init enable_IO_APIC(void)
+void __init enable_IO_APIC(void)
 {
 	union IO_APIC_reg_01 reg_01;
 	int i8259_apic, i8259_pin;
-	int i, apic;
+	int apic;
 	unsigned long flags;
 
+#ifdef CONFIG_X86_32
+	int i;
 	if (!pirqs_enabled)
 		for (i = 0; i < MAX_PIRQS; i++)
 			pirq_entries[i] = -1;
+#endif
 
 	/*
 	 * The number of IO-APIC IRQ registers (== #pins):
@@ -1759,7 +1898,7 @@ static void __init enable_IO_APIC(void)
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
 	}
-	for (apic = 0; apic < nr_ioapics; apic++) {
+	for(apic = 0; apic < nr_ioapics; apic++) {
 		int pin;
 		/* See if any of the pins is in ExtINT mode */
 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
@@ -1830,16 +1969,18 @@ void disable_IO_APIC(void)
 		entry.dest_mode       = 0; /* Physical */
 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
 		entry.vector          = 0;
-		entry.dest	      = read_apic_id();
+		entry.dest            = read_apic_id();
 
 		/*
 		 * Add it to the IO-APIC irq-routing table:
 		 */
 		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
 	}
+
 	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
+#ifdef CONFIG_X86_32
 /*
  * function to set the IO-APIC physical IDs based on the
  * values stored in the MPC table.
@@ -1940,8 +2081,6 @@ static void __init setup_ioapic_ids_from
 
 		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
 		spin_lock_irqsave(&ioapic_lock, flags);
-		io_apic_write(apic, 0, reg_00.raw);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
@@ -1955,6 +2094,7 @@ static void __init setup_ioapic_ids_from
 			apic_printk(APIC_VERBOSE, " ok.\n");
 	}
 }
+#endif
 
 int no_timer_check __initdata;
 
@@ -1994,9 +2134,10 @@ static int __init timer_irq_works(void)
 	 * might have cached one ExtINT interrupt.  Finally, at
 	 * least one tick may be lost due to delays.
 	 */
+
+	/* jiffies wrap? */
 	if (time_after(jiffies, t1 + 4))
 		return 1;
-
 	return 0;
 }
 
@@ -2014,8 +2155,6 @@ static int __init timer_irq_works(void)
  */
 
 /*
- * Startup quirk:
- *
  * Starting up a edge-triggered IO-APIC interrupt is
  * nasty - we need to make sure that we get the edge.
  * If it is already asserted for some reason, we need
@@ -2023,9 +2162,8 @@ static int __init timer_irq_works(void)
  *
  * This is not complete - we should be able to fake
  * an edge even if it isn't on the 8259A...
- *
- * (We do this for level-triggered IRQs too - it cannot hurt.)
  */
+
 static unsigned int startup_ioapic_irq(unsigned int irq)
 {
 	int was_pending = 0;
@@ -2043,58 +2181,229 @@ static unsigned int startup_ioapic_irq(u
 	return was_pending;
 }
 
+#ifdef CONFIG_X86_64
 static int ioapic_retrigger_irq(unsigned int irq)
 {
-	send_IPI_self(irq_cfg(irq)->vector);
+
+	struct irq_cfg *cfg = irq_cfg(irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
+	spin_unlock_irqrestore(&vector_lock, flags);
 
 	return 1;
 }
-
-#ifdef CONFIG_SMP
-asmlinkage void smp_irq_move_cleanup_interrupt(void)
+#else
+static int ioapic_retrigger_irq(unsigned int irq)
 {
-	unsigned vector, me;
-	ack_APIC_irq();
-	irq_enter();
-
-	me = smp_processor_id();
-	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
-		unsigned int irq;
-		struct irq_desc *desc;
-		struct irq_cfg *cfg;
-		irq = __get_cpu_var(vector_irq)[vector];
+        send_IPI_self(irq_cfg(irq)->vector);
 
-		desc = irq_desc(irq);
-		if (!desc)
-			continue;
+        return 1;
+}
+#endif
 
-		cfg = irq_cfg(irq);
-		spin_lock(&desc->lock);
-		if (!cfg->move_cleanup_count)
-			goto unlock;
+/*
+ * Level and edge triggered IO-APIC interrupts need different handling,
+ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+ * handled with the level-triggered descriptor, but that one has slightly
+ * more overhead. Level-triggered interrupts cannot be handled with the
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
+ */
 
-		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
-			goto unlock;
+#ifdef CONFIG_SMP
 
-		__get_cpu_var(vector_irq)[vector] = -1;
-		cfg->move_cleanup_count--;
-unlock:
-		spin_unlock(&desc->lock);
-	}
+#ifdef CONFIG_INTR_REMAP
+static void ir_irq_migration(struct work_struct *work);
 
-	irq_exit();
-}
+static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
 
-static void irq_complete_move(unsigned int irq)
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For edge triggered, irq migration is a simple atomic update(of vector
+ * and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we need to modify the io-apic RTE aswell with the update
+ * vector information, along with modifying IRTE with vector and destination.
+ * So irq migration for level triggered is little  bit more complex compared to
+ * edge triggered migration. But the good news is, we use the same algorithm
+ * for level triggered migration as we have today, only difference being,
+ * we now initiate the irq migration from process context instead of the
+ * interrupt context.
+ *
+ * In future, when we do a directed EOI (combined with cpu EOI broadcast
+ * suppression) to the IO-APIC, level triggered irq migration will also be
+ * as simple as edge triggered migration and we can do the irq migration
+ * with a simple atomic update to IO-APIC RTE.
+ */
+static void migrate_ioapic_irq(int irq, cpumask_t mask)
 {
-	struct irq_cfg *cfg = irq_cfg(irq);
-	unsigned vector, me;
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+	cpumask_t tmp, cleanup_mask;
+	struct irte irte;
+	int modify_ioapic_rte;
+	unsigned int dest;
+	unsigned long flags;
 
-	if (likely(!cfg->move_in_progress))
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
 		return;
 
-	vector = ~get_irq_regs()->orig_ax;
-	me = smp_processor_id();
+	if (get_irte(irq, &irte))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	desc = irq_desc(irq);
+	modify_ioapic_rte = desc->status & IRQ_LEVEL;
+	if (modify_ioapic_rte) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		__target_IO_APIC_irq(irq, dest, cfg->vector);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * Modified the IRTE and flushes the Interrupt entry cache.
+	 */
+	modify_irte(irq, &irte);
+
+	if (cfg->move_in_progress) {
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+
+	desc->affinity = mask;
+}
+
+static int migrate_irq_remapped_level(int irq)
+{
+	int ret = -1;
+	struct irq_desc *desc = irq_desc(irq);
+
+	mask_IO_APIC_irq(irq);
+
+	if (io_apic_level_ack_pending(irq)) {
+		/*
+	 	 * Interrupt in progress. Migrating irq now will change the
+		 * vector information in the IO-APIC RTE and that will confuse
+		 * the EOI broadcast performed by cpu.
+		 * So, delay the irq migration to the next instance.
+		 */
+		schedule_delayed_work(&ir_migration_work, 1);
+		goto unmask;
+	}
+
+	/* everthing is clear. we have right of way */
+	migrate_ioapic_irq(irq, desc->pending_mask);
+
+	ret = 0;
+	desc->status &= ~IRQ_MOVE_PENDING;
+	cpus_clear(desc->pending_mask);
+
+unmask:
+	unmask_IO_APIC_irq(irq);
+	return ret;
+}
+
+static void ir_irq_migration(struct work_struct *work)
+{
+	unsigned int irq;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(irq, desc) {
+		if (desc->status & IRQ_MOVE_PENDING) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&desc->lock, flags);
+			if (!desc->chip->set_affinity ||
+			    !(desc->status & IRQ_MOVE_PENDING)) {
+				desc->status &= ~IRQ_MOVE_PENDING;
+				spin_unlock_irqrestore(&desc->lock, flags);
+				continue;
+			}
+
+			desc->chip->set_affinity(irq, desc, desc->pending_mask);
+			spin_unlock_irqrestore(&desc->lock, flags);
+		}
+	}
+}
+
+/*
+ * Migrates the IRQ destination in the process context.
+ */
+static void set_ir_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	if (desc->status & IRQ_LEVEL) {
+		desc->status |= IRQ_MOVE_PENDING;
+		desc->pending_mask = mask;
+		migrate_irq_remapped_level(irq);
+		return;
+	}
+
+	migrate_ioapic_irq(irq, mask);
+}
+#endif
+
+asmlinkage void smp_irq_move_cleanup_interrupt(void)
+{
+	unsigned vector, me;
+	ack_APIC_irq();
+#ifdef CONFIG_X86_64
+	exit_idle();
+#endif
+	irq_enter();
+
+	me = smp_processor_id();
+	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+		unsigned int irq;
+		struct irq_desc *desc;
+		struct irq_cfg *cfg;
+		irq = __get_cpu_var(vector_irq)[vector];
+
+		desc = irq_desc(irq);
+		if (!desc)
+			continue;
+
+		cfg = irq_cfg(irq);
+		spin_lock(&desc->lock);
+		if (!cfg->move_cleanup_count)
+			goto unlock;
+
+		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+			goto unlock;
+
+		__get_cpu_var(vector_irq)[vector] = -1;
+		cfg->move_cleanup_count--;
+unlock:
+		spin_unlock(&desc->lock);
+	}
+
+	irq_exit();
+}
+
+static void irq_complete_move(unsigned int irq)
+{
+	struct irq_cfg *cfg = irq_cfg(irq);
+	unsigned vector, me;
+
+	if (likely(!cfg->move_in_progress))
+		return;
+
+	vector = ~get_irq_regs()->orig_ax;
+	me = smp_processor_id();
 	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
 		cpumask_t cleanup_mask;
 
@@ -2107,6 +2416,17 @@ static void irq_complete_move(unsigned i
 #else
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
+#ifdef CONFIG_INTR_REMAP
+static void ack_x2apic_level(unsigned int irq, struct irq_desc *desc)
+{
+	ack_x2APIC_irq();
+}
+
+static void ack_x2apic_edge(unsigned int irq, struct irq_desc *desc)
+{
+	ack_x2APIC_irq();
+}
+#endif
 
 static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
 {
@@ -2118,55 +2438,55 @@ static void ack_apic_edge(unsigned int i
 #ifdef CONFIG_X86_64
 static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
 {
-        int do_unmask_irq = 0;
+	int do_unmask_irq = 0;
 
-        irq_complete_move(irq);
+	irq_complete_move(irq);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
-        /* If we are moving the irq we need to mask it */
-        if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
-                do_unmask_irq = 1;
-                mask_IO_APIC_irq(irq);
-        }
+	/* If we are moving the irq we need to mask it */
+	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+		do_unmask_irq = 1;
+		mask_IO_APIC_irq(irq);
+	}
 #endif
 
-        /*
-         * We must acknowledge the irq before we move it or the acknowledge will
-         * not propagate properly.
-         */
-        ack_APIC_irq();
+	/*
+	 * We must acknowledge the irq before we move it or the acknowledge will
+	 * not propagate properly.
+	 */
+	ack_APIC_irq();
 
-        /* Now we can move and renable the irq */
-        if (unlikely(do_unmask_irq)) {
-                /* Only migrate the irq if the ack has been received.
-                 *
-                 * On rare occasions the broadcast level triggered ack gets
-                 * delayed going to ioapics, and if we reprogram the
-                 * vector while Remote IRR is still set the irq will never
-                 * fire again.
-                 *
-                 * To prevent this scenario we read the Remote IRR bit
-                 * of the ioapic.  This has two effects.
-                 * - On any sane system the read of the ioapic will
-                 *   flush writes (and acks) going to the ioapic from
-                 *   this cpu.
-                 * - We get to see if the ACK has actually been delivered.
-                 *
-                 * Based on failed experiments of reprogramming the
-                 * ioapic entry from outside of irq context starting
-                 * with masking the ioapic entry and then polling until
-                 * Remote IRR was clear before reprogramming the
-                 * ioapic I don't trust the Remote IRR bit to be
-                 * completey accurate.
-                 *
-                 * However there appears to be no other way to plug
-                 * this race, so if the Remote IRR bit is not
-                 * accurate and is causing problems then it is a hardware bug
-                 * and you can go talk to the chipset vendor about it.
-                 */
-                if (!io_apic_level_ack_pending(irq))
-                        move_masked_irq(irq, desc);
-                unmask_IO_APIC_irq(irq);
-        }
+	/* Now we can move and renable the irq */
+	if (unlikely(do_unmask_irq)) {
+		/* Only migrate the irq if the ack has been received.
+		 *
+		 * On rare occasions the broadcast level triggered ack gets
+		 * delayed going to ioapics, and if we reprogram the
+		 * vector while Remote IRR is still set the irq will never
+		 * fire again.
+		 *
+		 * To prevent this scenario we read the Remote IRR bit
+		 * of the ioapic.  This has two effects.
+		 * - On any sane system the read of the ioapic will
+		 *   flush writes (and acks) going to the ioapic from
+		 *   this cpu.
+		 * - We get to see if the ACK has actually been delivered.
+		 *
+		 * Based on failed experiments of reprogramming the
+		 * ioapic entry from outside of irq context starting
+		 * with masking the ioapic entry and then polling until
+		 * Remote IRR was clear before reprogramming the
+		 * ioapic I don't trust the Remote IRR bit to be
+		 * completey accurate.
+		 *
+		 * However there appears to be no other way to plug
+		 * this race, so if the Remote IRR bit is not
+		 * accurate and is causing problems then it is a hardware bug
+		 * and you can go talk to the chipset vendor about it.
+		 */
+		if (!io_apic_level_ack_pending(irq))
+			move_masked_irq(irq, desc);
+		unmask_IO_APIC_irq(irq);
+	}
 }
 #else
 atomic_t irq_mis_count;
@@ -2177,25 +2497,25 @@ static void ack_apic_level(unsigned int 
 
 	irq_complete_move(irq);
 	move_native_irq(irq, desc);
-/*
- * It appears there is an erratum which affects at least version 0x11
- * of I/O APIC (that's the 82093AA and cores integrated into various
- * chipsets).  Under certain conditions a level-triggered interrupt is
- * erroneously delivered as edge-triggered one but the respective IRR
- * bit gets set nevertheless.  As a result the I/O unit expects an EOI
- * message but it will never arrive and further interrupts are blocked
- * from the source.  The exact reason is so far unknown, but the
- * phenomenon was observed when two consecutive interrupt requests
- * from a given source get delivered to the same CPU and the source is
- * temporarily disabled in between.
- *
- * A workaround is to simulate an EOI message manually.  We achieve it
- * by setting the trigger mode to edge and then to level when the edge
- * trigger mode gets detected in the TMR of a local APIC for a
- * level-triggered interrupt.  We mask the source for the time of the
- * operation to prevent an edge-triggered interrupt escaping meanwhile.
- * The idea is from Manfred Spraul.  --macro
- */
+	/*
+	* It appears there is an erratum which affects at least version 0x11
+	* of I/O APIC (that's the 82093AA and cores integrated into various
+	* chipsets).  Under certain conditions a level-triggered interrupt is
+	* erroneously delivered as edge-triggered one but the respective IRR
+	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
+	* message but it will never arrive and further interrupts are blocked
+	* from the source.  The exact reason is so far unknown, but the
+	* phenomenon was observed when two consecutive interrupt requests
+	* from a given source get delivered to the same CPU and the source is
+	* temporarily disabled in between.
+	*
+	* A workaround is to simulate an EOI message manually.  We achieve it
+	* by setting the trigger mode to edge and then to level when the edge
+	* trigger mode gets detected in the TMR of a local APIC for a
+	* level-triggered interrupt.  We mask the source for the time of the
+	* operation to prevent an edge-triggered interrupt escaping meanwhile.
+	* The idea is from Manfred Spraul.  --macro
+	*/
 	i = irq_cfg(irq)->vector;
 
 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
@@ -2225,6 +2545,20 @@ static struct irq_chip ioapic_chip __rea
 	.retrigger	= ioapic_retrigger_irq,
 };
 
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip ir_ioapic_chip __read_mostly = {
+	.name 		= "IR-IO-APIC",
+	.startup 	= startup_ioapic_irq,
+	.mask	 	= mask_IO_APIC_irq,
+	.unmask	 	= unmask_IO_APIC_irq,
+	.ack 		= ack_x2apic_edge,
+	.eoi 		= ack_x2apic_level,
+#ifdef CONFIG_SMP
+	.set_affinity 	= set_ir_ioapic_affinity_irq,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+#endif
 
 static inline void init_IO_APIC_traps(void)
 {
@@ -2383,12 +2717,12 @@ static inline void __init unlock_ExtINT_
 
 static int disable_timer_pin_1 __initdata;
 /* Actually the next is obsolete, but keep it for paranoid reasons -AK */
-static int __init parse_disable_timer_pin_1(char *arg)
+static int __init disable_timer_pin_setup(char *arg)
 {
 	disable_timer_pin_1 = 1;
 	return 0;
 }
-early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
+early_param("disable_timer_pin_1", disable_timer_pin_setup);
 
 int timer_through_8259 __initdata;
 
@@ -2397,6 +2731,8 @@ int timer_through_8259 __initdata;
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  * fanatically on his truly buggy board.
+ *
+ * FIXME: really need to revamp this for all platforms.
  */
 static inline void __init check_timer(void)
 {
@@ -2408,8 +2744,8 @@ static inline void __init check_timer(vo
 
 	local_irq_save(flags);
 
-	ver = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(ver);
+        ver = apic_read(APIC_LVR);
+        ver = GET_APIC_VERSION(ver);
 
 	/*
 	 * get/set the timer IRQ vector:
@@ -2428,7 +2764,9 @@ static inline void __init check_timer(vo
 	 */
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 	init_8259A(1);
+#ifdef CONFIG_X86_32
 	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+#endif
 
 	pin1  = find_isa_irq_pin(0, mp_INT);
 	apic1 = find_isa_irq_apic(0, mp_INT);
@@ -2447,6 +2785,10 @@ static inline void __init check_timer(vo
 	 * 8259A.
 	 */
 	if (pin1 == -1) {
+#ifdef CONFIG_INTR_REMAP
+		if (intr_remapping_enabled)
+			panic("BIOS bug: timer not connected to IO-APIC");
+#endif
 		pin1 = pin2;
 		apic1 = apic2;
 		no_pin1 = 1;
@@ -2473,6 +2815,10 @@ static inline void __init check_timer(vo
 				clear_IO_APIC_pin(0, pin1);
 			goto out;
 		}
+#ifdef CONFIG_INTR_REMAP
+		if (intr_remapping_enabled)
+			panic("timer doesn't work through Interrupt-remapped IO-APIC");
+#endif
 		clear_IO_APIC_pin(apic1, pin1);
 		if (!no_pin1)
 			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
@@ -2512,7 +2858,9 @@ static inline void __init check_timer(vo
 			    "through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = NMI_NONE;
 	}
+#ifdef CONFIG_X86_32
 	timer_ack = 0;
+#endif
 
 	apic_printk(APIC_QUIET, KERN_INFO
 		    "...trying to set up timer as Virtual Wire IRQ...\n");
@@ -2570,17 +2918,25 @@ out:
 
 void __init setup_IO_APIC(void)
 {
+
+#ifdef CONFIG_X86_32
 	enable_IO_APIC();
+#else
+	/*
+	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
+	 */
+#endif
 
 	io_apic_irqs = ~PIC_IRQS;
 
-	printk("ENABLING IO-APIC IRQs\n");
-
-	/*
-	 * Set up IO-APIC IRQ routing.
-	 */
-	if (!acpi_ioapic)
-		setup_ioapic_ids_from_mpc();
+	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+        /*
+         * Set up IO-APIC IRQ routing.
+         */
+#ifdef CONFIG_X86_32
+        if (!acpi_ioapic)
+                setup_ioapic_ids_from_mpc();
+#endif
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
@@ -2588,15 +2944,15 @@ void __init setup_IO_APIC(void)
 }
 
 /*
- *	Called after all the initialization is done. If we didnt find any
- *	APIC bugs then we can allow the modify fast path
+ *      Called after all the initialization is done. If we didnt find any
+ *      APIC bugs then we can allow the modify fast path
  */
 
 static int __init io_apic_bug_finalize(void)
 {
-	if (sis_apic_bug == -1)
-		sis_apic_bug = 0;
-	return 0;
+        if (sis_apic_bug == -1)
+                sis_apic_bug = 0;
+        return 0;
 }
 
 late_initcall(io_apic_bug_finalize);
@@ -2605,7 +2961,7 @@ struct sysfs_ioapic_data {
 	struct sys_device dev;
 	struct IO_APIC_route_entry entry[0];
 };
-static struct sysfs_ioapic_data *mp_ioapic_data[MAX_IO_APICS];
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
 
 static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
 {
@@ -2615,8 +2971,8 @@ static int ioapic_suspend(struct sys_dev
 
 	data = container_of(dev, struct sysfs_ioapic_data, dev);
 	entry = data->entry;
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-		entry[i] = ioapic_read_entry(dev->id, i);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+		*entry = ioapic_read_entry(dev->id, i);
 
 	return 0;
 }
@@ -2653,14 +3009,14 @@ static struct sysdev_class ioapic_sysdev
 
 static int __init ioapic_init_sysfs(void)
 {
-	struct sys_device *dev;
-	int i, size, error = 0;
+	struct sys_device * dev;
+	int i, size, error;
 
 	error = sysdev_class_register(&ioapic_sysdev_class);
 	if (error)
 		return error;
 
-	for (i = 0; i < nr_ioapics; i++) {
+	for (i = 0; i < nr_ioapics; i++ ) {
 		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
 			* sizeof(struct IO_APIC_route_entry);
 		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
@@ -2691,12 +3047,12 @@ device_initcall(ioapic_init_sysfs);
 unsigned int create_irq(unsigned int irq_want)
 {
 	/* Allocate an unused irq */
-	unsigned int irq, new;
+	unsigned int irq;
+	unsigned int new;
 	unsigned long flags;
 	struct irq_cfg *cfg_new;
 
 #ifndef CONFIG_HAVE_SPARSE_IRQ
-	/* only can use bus/dev/fn.. when per_cpu vector is used */
 	irq_want = nr_irqs - 1;
 #endif
 
@@ -2729,6 +3085,9 @@ void destroy_irq(unsigned int irq)
 
 	dynamic_irq_cleanup(irq);
 
+#ifdef CONFIG_INTR_REMAP
+	free_irte(irq);
+#endif
 	spin_lock_irqsave(&vector_lock, flags);
 	__clear_irq_vector(irq);
 	spin_unlock_irqrestore(&vector_lock, flags);
@@ -2754,25 +3113,54 @@ static int msi_compose_msg(struct pci_de
 	cpus_and(tmp, cfg->domain, tmp);
 	dest = cpu_mask_to_apicid(tmp);
 
-	msg->address_hi = MSI_ADDR_BASE_HI;
-	msg->address_lo =
-		MSI_ADDR_BASE_LO |
-		((INT_DEST_MODE == 0) ?
-			MSI_ADDR_DEST_MODE_PHYSICAL:
-			MSI_ADDR_DEST_MODE_LOGICAL) |
-		((INT_DELIVERY_MODE != dest_LowestPrio) ?
-			MSI_ADDR_REDIRECTION_CPU:
-			MSI_ADDR_REDIRECTION_LOWPRI) |
-		MSI_ADDR_DEST_ID(dest);
-
-	msg->data =
-		MSI_DATA_TRIGGER_EDGE |
-		MSI_DATA_LEVEL_ASSERT |
-		((INT_DELIVERY_MODE != dest_LowestPrio) ?
-			MSI_DATA_DELIVERY_FIXED:
-			MSI_DATA_DELIVERY_LOWPRI) |
-		MSI_DATA_VECTOR(cfg->vector);
-
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		struct irte irte;
+		int ir_index;
+		u16 sub_handle;
+
+		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
+		BUG_ON(ir_index == -1);
+
+		memset (&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = INT_DEST_MODE;
+		irte.trigger_mode = 0; /* edge */
+		irte.dlvry_mode = INT_DELIVERY_MODE;
+		irte.vector = cfg->vector;
+		irte.dest_id = IRTE_DEST(dest);
+
+		modify_irte(irq, &irte);
+
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->data = sub_handle;
+		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+				  MSI_ADDR_IR_SHV |
+				  MSI_ADDR_IR_INDEX1(ir_index) |
+				  MSI_ADDR_IR_INDEX2(ir_index);
+	} else
+#endif
+	{
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->address_lo =
+			MSI_ADDR_BASE_LO |
+			((INT_DEST_MODE == 0) ?
+				MSI_ADDR_DEST_MODE_PHYSICAL:
+				MSI_ADDR_DEST_MODE_LOGICAL) |
+			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+				MSI_ADDR_REDIRECTION_CPU:
+				MSI_ADDR_REDIRECTION_LOWPRI) |
+			MSI_ADDR_DEST_ID(dest);
+
+		msg->data =
+			MSI_DATA_TRIGGER_EDGE |
+			MSI_DATA_LEVEL_ASSERT |
+			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+				MSI_DATA_DELIVERY_FIXED:
+				MSI_DATA_DELIVERY_LOWPRI) |
+			MSI_DATA_VECTOR(cfg->vector);
+	}
 	return err;
 }
 
@@ -2805,6 +3193,56 @@ static void set_msi_irq_affinity(unsigne
 	write_msi_msg(irq, &msg);
 	desc->affinity = mask;
 }
+
+#ifdef CONFIG_INTR_REMAP
+/*
+ * Migrate the MSI irq to another cpumask. This migration is
+ * done in the process context using interrupt-remapping hardware.
+ */
+static void ir_set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	unsigned int dest;
+	cpumask_t tmp, cleanup_mask;
+	struct irte irte;
+
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (get_irte(irq, &irte))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * atomically update the IRTE with the new destination and vector.
+	 */
+	modify_irte(irq, &irte);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress) {
+		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		cfg->move_in_progress = 0;
+	}
+
+	desc->affinity = mask;
+}
+#endif
 #endif /* CONFIG_SMP */
 
 /*
@@ -2822,6 +3260,45 @@ static struct irq_chip msi_chip = {
 	.retrigger	= ioapic_retrigger_irq,
 };
 
+#ifdef CONFIG_INTR_REMAP
+static struct irq_chip msi_ir_chip = {
+	.name		= "IR-PCI-MSI",
+	.unmask		= unmask_msi_irq,
+	.mask		= mask_msi_irq,
+	.ack		= ack_x2apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= ir_set_msi_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+/*
+ * Map the PCI dev to the corresponding remapping hardware unit
+ * and allocate 'nvec' consecutive interrupt-remapping table entries
+ * in it.
+ */
+static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
+{
+	struct intel_iommu *iommu;
+	int index;
+
+	iommu = map_dev_to_ir(dev);
+	if (!iommu) {
+		printk(KERN_ERR
+		       "Unable to map PCI %s to iommu\n", pci_name(dev));
+		return -ENOENT;
+	}
+
+	index = alloc_irte(iommu, irq, nvec);
+	if (index < 0) {
+		printk(KERN_ERR
+		       "Unable to allocate %d IRTE for PCI %s\n", nvec,
+		        pci_name(dev));
+		return -ENOSPC;
+	}
+	return index;
+}
+#endif
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
 {
@@ -2835,7 +3312,17 @@ static int setup_msi_irq(struct pci_dev 
 	set_irq_msi(irq, desc);
 	write_msi_msg(irq, &msg);
 
-	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+#ifdef CONFIG_INTR_REMAP
+	if (irq_remapped(irq)) {
+		struct irq_desc *desc = irq_desc(irq);
+		/*
+		 * irq migration in process context
+		 */
+		desc->status |= IRQ_MOVE_PCNTXT;
+		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
+	} else
+#endif
+		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
 	return 0;
 }
@@ -2854,58 +3341,162 @@ static unsigned int build_irq_for_pci_de
 
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-	int irq, ret;
-        unsigned int irq_want;
-
-        irq_want = build_irq_for_pci_dev(dev) + 0x100;
+	unsigned int irq;
+	int ret;
+	unsigned int irq_want;
 
-        irq = create_irq(irq_want);
+	irq_want = build_irq_for_pci_dev(dev) + 0x100;
 
+	irq = create_irq(irq_want);
 	if (irq == 0)
 		return -1;
 
+#ifdef CONFIG_INTR_REMAP
+	if (!intr_remapping_enabled)
+		goto no_ir;
+
+	ret = msi_alloc_irte(dev, irq, 1);
+	if (ret < 0)
+		goto error;
+no_ir:
+#endif
 	ret = setup_msi_irq(dev, desc, irq);
 	if (ret < 0) {
 		destroy_irq(irq);
 		return ret;
-        }
-
+	}
 	return 0;
+
+#ifdef CONFIG_INTR_REMAP
+error:
+	destroy_irq(irq);
+	return ret;
+#endif
 }
 
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-        unsigned int irq;
-        int ret, sub_handle;
-        struct msi_desc *desc;
-        unsigned int irq_want;
-
-        irq_want = build_irq_for_pci_dev(dev) + 0x100;
-        sub_handle = 0;
-        list_for_each_entry(desc, &dev->msi_list, list) {
-                irq = create_irq(irq_want--);
-                if (irq == 0)
-                        return -1;
-                ret = setup_msi_irq(dev, desc, irq);
-                if (ret < 0)
-                        goto error;
-                sub_handle++;
-        }
-        return 0;
+	unsigned int irq;
+	int ret, sub_handle;
+	struct msi_desc *desc;
+	unsigned int irq_want;
+
+#ifdef CONFIG_INTR_REMAP
+	struct intel_iommu *iommu = 0;
+	int index = 0;
+#endif
+
+	irq_want = build_irq_for_pci_dev(dev) + 0x100;
+	sub_handle = 0;
+	list_for_each_entry(desc, &dev->msi_list, list) {
+		irq = create_irq(irq_want--);
+		if (irq == 0)
+			return -1;
+#ifdef CONFIG_INTR_REMAP
+		if (!intr_remapping_enabled)
+			goto no_ir;
+
+		if (!sub_handle) {
+			/*
+			 * allocate the consecutive block of IRTE's
+			 * for 'nvec'
+			 */
+			index = msi_alloc_irte(dev, irq, nvec);
+			if (index < 0) {
+				ret = index;
+				goto error;
+			}
+		} else {
+			iommu = map_dev_to_ir(dev);
+			if (!iommu) {
+				ret = -ENOENT;
+				goto error;
+			}
+			/*
+			 * setup the mapping between the irq and the IRTE
+			 * base index, the sub_handle pointing to the
+			 * appropriate interrupt remap table entry.
+			 */
+			set_irte_irq(irq, iommu, index, sub_handle);
+		}
+no_ir:
+#endif
+		ret = setup_msi_irq(dev, desc, irq);
+		if (ret < 0)
+			goto error;
+		sub_handle++;
+	}
+	return 0;
 
 error:
-        destroy_irq(irq);
-        return ret;
+	destroy_irq(irq);
+	return ret;
 }
 
-
 void arch_teardown_msi_irq(unsigned int irq)
 {
 	destroy_irq(irq);
 }
 
-#endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_DMAR
+#ifdef CONFIG_SMP
+static void dmar_msi_set_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+{
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+	cpumask_t tmp;
 
+	cpus_and(tmp, mask, cpu_online_map);
+	if (cpus_empty(tmp))
+		return;
+
+	if (assign_irq_vector(irq, mask))
+		return;
+
+	cfg = irq_cfg(irq);
+	cpus_and(tmp, cfg->domain, mask);
+	dest = cpu_mask_to_apicid(tmp);
+
+	dmar_msi_read(irq, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+	dmar_msi_write(irq, &msg);
+	desc->affinity = mask;
+}
+#endif /* CONFIG_SMP */
+
+struct irq_chip dmar_msi_type = {
+	.name = "DMAR_MSI",
+	.unmask = dmar_msi_unmask,
+	.mask = dmar_msi_mask,
+	.ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity = dmar_msi_set_affinity,
+#endif
+	.retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_dmar_msi(unsigned int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(NULL, irq, &msg);
+	if (ret < 0)
+		return ret;
+	dmar_msi_write(irq, &msg);
+	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+		"edge");
+	return 0;
+}
+#endif
+
+#endif /* CONFIG_PCI_MSI */
 /*
  * Hypertransport interrupt support
  */
@@ -2968,7 +3559,7 @@ int arch_setup_ht_irq(unsigned int irq, 
 
 	tmp = TARGET_CPUS;
 	err = assign_irq_vector(irq, tmp);
-	if ( !err) {
+	if (!err) {
 		struct ht_irq_msg msg;
 		unsigned dest;
 
@@ -3001,11 +3592,12 @@ int arch_setup_ht_irq(unsigned int irq, 
 #endif /* CONFIG_HT_IRQ */
 
 /* --------------------------------------------------------------------------
-			ACPI-based IOAPIC Configuration
+                          ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
 
 #ifdef CONFIG_ACPI
 
+#ifdef CONFIG_X86_32
 int __init io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
@@ -3080,7 +3672,6 @@ int __init io_apic_get_unique_id(int ioa
 	return apic_id;
 }
 
-
 int __init io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
@@ -3092,9 +3683,9 @@ int __init io_apic_get_version(int ioapi
 
 	return reg_01.bits.version;
 }
+#endif
 
-
-int __init io_apic_get_redir_entries(int ioapic)
+int __init io_apic_get_redir_entries (int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3107,10 +3698,10 @@ int __init io_apic_get_redir_entries(int
 }
 
 
-int io_apic_set_pci_routing(int ioapic, int pin, int irq, int triggering, int polarity)
+int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
 	if (!IO_APIC_IRQ(irq)) {
-		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
 			ioapic);
 		return -EINVAL;
 	}
@@ -3126,6 +3717,7 @@ int io_apic_set_pci_routing(int ioapic, 
 	return 0;
 }
 
+
 int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
 {
 	int i;
@@ -3178,13 +3770,56 @@ void __init setup_ioapic_dest(void)
 				setup_IO_APIC_irq(ioapic, pin, irq,
 						  irq_trigger(irq_entry),
 						  irq_polarity(irq_entry));
+#ifdef CONFIG_INTR_REMAP
+			else if (intr_remapping_enabled) {
+				desc = irq_desc(irq);
+				set_ir_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
+			}
+#endif
 			else {
 				desc = irq_desc(irq);
 				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
 			}
 		}
+	}
+}
+#endif
+
+#ifdef CONFIG_X86_64
+#define IOAPIC_RESOURCE_NAME_SIZE 11
+
+static struct resource *ioapic_resources;
+
+static struct resource * __init ioapic_setup_resources(void)
+{
+	unsigned long n;
+	struct resource *res;
+	char *mem;
+	int i;
+
+	if (nr_ioapics <= 0)
+		return NULL;
 
+	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+	n *= nr_ioapics;
+
+	mem = alloc_bootmem(n);
+	res = (void *)mem;
+
+	if (mem != NULL) {
+		mem += sizeof(struct resource) * nr_ioapics;
+
+		for (i = 0; i < nr_ioapics; i++) {
+			res[i].name = mem;
+			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+			sprintf(mem,  "IOAPIC %u", i);
+			mem += IOAPIC_RESOURCE_NAME_SIZE;
+		}
 	}
+
+	ioapic_resources = res;
+
+	return res;
 }
 #endif
 
@@ -3192,29 +3827,70 @@ void __init ioapic_init_mappings(void)
 {
 	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
 	int i;
+#ifdef CONFIG_X86_64
+	struct resource *ioapic_res;
 
+	ioapic_res = ioapic_setup_resources();
+#endif
 	for (i = 0; i < nr_ioapics; i++) {
 		if (smp_found_config) {
 			ioapic_phys = mp_ioapics[i].mp_apicaddr;
-			if (!ioapic_phys) {
-				printk(KERN_ERR
-				       "WARNING: bogus zero IO-APIC "
-				       "address found in MPTABLE, "
-				       "disabling IO/APIC support!\n");
-				smp_found_config = 0;
-				skip_ioapic_setup = 1;
-				goto fake_ioapic_page;
-			}
+#ifdef CONFIG_X86_32
+                        if (!ioapic_phys) {
+                                printk(KERN_ERR
+                                       "WARNING: bogus zero IO-APIC "
+                                       "address found in MPTABLE, "
+                                       "disabling IO/APIC support!\n");
+                                smp_found_config = 0;
+                                skip_ioapic_setup = 1;
+                                goto fake_ioapic_page;
+                        }
+#endif
 		} else {
+#ifdef CONFIG_X86_32
 fake_ioapic_page:
+#endif
 			ioapic_phys = (unsigned long)
-				      alloc_bootmem_pages(PAGE_SIZE);
+				alloc_bootmem_pages(PAGE_SIZE);
 			ioapic_phys = __pa(ioapic_phys);
 		}
 		set_fixmap_nocache(idx, ioapic_phys);
-		printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
-		       __fix_to_virt(idx), ioapic_phys);
+		apic_printk(APIC_VERBOSE,
+			    "mapped IOAPIC to %08lx (%08lx)\n",
+			    __fix_to_virt(idx), ioapic_phys);
 		idx++;
+
+#ifdef CONFIG_X86_64
+		if (ioapic_res != NULL) {
+			ioapic_res->start = ioapic_phys;
+			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+			ioapic_res++;
+		}
+#endif
 	}
 }
 
+#ifdef CONFIG_X86_64
+static int __init ioapic_insert_resources(void)
+{
+	int i;
+	struct resource *r = ioapic_resources;
+
+	if (!r) {
+		printk(KERN_ERR
+		       "IO APIC resources could be not be allocated.\n");
+		return -1;
+	}
+
+	for (i = 0; i < nr_ioapics; i++) {
+		insert_resource(&iomem_resource, r);
+		r++;
+	}
+
+	return 0;
+}
+
+/* Insert the IO APIC resources after PCI initialization has occured to handle
+ * IO APICS that are mapped in on a BAR in PCI space. */
+late_initcall(ioapic_insert_resources);
+#endif

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] x86: io_apic.c, build fix
  2008-08-16  8:02               ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Ingo Molnar
@ 2008-08-16  8:22                 ` Ingo Molnar
  2008-08-16  8:26                   ` Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-16  8:22 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel


>From 306bb46f92d326c5afae3fa04860bdccb879b6b8 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Sat, 16 Aug 2008 10:18:31 +0200
Subject: [PATCH] x86: io_apic.c, build fix

fix:

 arch/x86/kernel/io_apic.c: In function 'MPBIOS_trigger':
 arch/x86/kernel/io_apic.c:1105: error: implicit declaration of function 'default_MCA_trigger'

the MCA defines got lost in the unification.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/kernel/io_apic.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index 2043cd8..929429f 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -1025,6 +1025,12 @@ static int EISA_ELCR(unsigned int irq)
 #define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
 #define default_EISA_polarity(idx)      default_ISA_polarity(idx)
 
+/* MCA interrupts are always polarity zero level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_MCA_trigger(idx)	(1)
+#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
+
 
 static int MPBIOS_polarity(int idx)
 {

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH] x86: io_apic.c, build fix
  2008-08-16  8:22                 ` [PATCH] x86: io_apic.c, build fix Ingo Molnar
@ 2008-08-16  8:26                   ` Yinghai Lu
  0 siblings, 0 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-16  8:26 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Thomas Gleixner, H. Peter Anvin, Eric W. Biederman,
	Andrew Morton, linux-kernel

On Sat, Aug 16, 2008 at 1:22 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> From 306bb46f92d326c5afae3fa04860bdccb879b6b8 Mon Sep 17 00:00:00 2001
> From: Ingo Molnar <mingo@elte.hu>
> Date: Sat, 16 Aug 2008 10:18:31 +0200
> Subject: [PATCH] x86: io_apic.c, build fix
>
> fix:
>
>  arch/x86/kernel/io_apic.c: In function 'MPBIOS_trigger':
>  arch/x86/kernel/io_apic.c:1105: error: implicit declaration of function 'default_MCA_trigger'
>
> the MCA defines got lost in the unification.
>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
> ---
>  arch/x86/kernel/io_apic.c |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
> index 2043cd8..929429f 100644
> --- a/arch/x86/kernel/io_apic.c
> +++ b/arch/x86/kernel/io_apic.c
> @@ -1025,6 +1025,12 @@ static int EISA_ELCR(unsigned int irq)
>  #define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
>  #define default_EISA_polarity(idx)      default_ISA_polarity(idx)
>
> +/* MCA interrupts are always polarity zero level triggered,
> + * when listed as conforming in the MP table. */
> +
> +#define default_MCA_trigger(idx)       (1)
> +#define default_MCA_polarity(idx)      default_ISA_polarity(idx)
> +
>
>  static int MPBIOS_polarity(int idx)
>  {
>

ah. EISA got too copies

/* ISA interrupts are always polarity zero edge triggered,
 * when listed as conforming in the MP table. */

#define default_ISA_trigger(idx)        (0)
#define default_ISA_polarity(idx)       (0)

/* EISA interrupts are always polarity zero and can be edge or level
 * trigger depending on the ELCR value.  If an interrupt is listed as
 * EISA conforming in the MP table, that means its trigger type must
 * be read in from the ELCR */

#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
#define default_EISA_polarity(idx)      default_ISA_polarity(idx)

/* PCI interrupts are always polarity one level triggered,
 * when listed as conforming in the MP table. */

#define default_PCI_trigger(idx)        (1)
#define default_PCI_polarity(idx)       (1)

/* EISA interrupts are always polarity zero and can be edge or level
 * trigger depending on the ELCR value.  If an interrupt is listed as
 * EISA conforming in the MP table, that means its trigger type must
 * be read in from the ELCR */

#define default_EISA_trigger(idx)       (EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
#define default_EISA_polarity(idx)      default_ISA_polarity(idx)


need to remove the  extra one.

YH

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] x86: apic - unify lapic_resume - fix
       [not found] <no>
  2008-08-15  2:20 ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Yinghai Lu
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
@ 2008-08-18  4:12 ` Yinghai Lu
  2008-08-18  4:12   ` [PATCH 1/2] x86: make HAVE_SPARSE_IRQ support selectable Yinghai Lu
  2008-08-18  7:25   ` [PATCH] x86: apic - unify lapic_resume - fix Ingo Molnar
  2008-08-18 20:44 ` [PATCH] irq: rename irq_desc() to to_irq_desc() " Yinghai Lu
                   ` (35 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18  4:12 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 1b0baf5..7fb7dca 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -1448,6 +1448,7 @@ static int lapic_resume(struct sys_device *dev)
 		enable_x2apic();
 	else
 #endif
+	{
 		/*
 		 * Make sure the APICBASE points to the right address
 		 *
@@ -1458,6 +1459,7 @@ static int lapic_resume(struct sys_device *dev)
 		l &= ~MSR_IA32_APICBASE_BASE;
 		l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
 		wrmsr(MSR_IA32_APICBASE, l, h);
+	}
 
 	apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
 	apic_write(APIC_ID, apic_pm_state.apic_id);

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 1/2] x86: make HAVE_SPARSE_IRQ support selectable
  2008-08-18  4:12 ` [PATCH] x86: apic - unify lapic_resume - fix Yinghai Lu
@ 2008-08-18  4:12   ` Yinghai Lu
  2008-08-18  4:12     ` [PATCH 2/2] irq: rename irq_desc() to to_irq_desc() Yinghai Lu
  2008-08-18  7:25   ` [PATCH] x86: apic - unify lapic_resume - fix Ingo Molnar
  1 sibling, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18  4:12 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

Ingo said sparse_irq is some intrusive. need to make it selectable

to make it simple, remove irq_desc as parameter in some functions.
(ack, eoi, set_affinity).
may need to make member if irq_chip to take irq_desc, or struct irq later.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
 arch/Kconfig              |    3 -
 arch/x86/Kconfig          |   12 ++++
 arch/x86/kernel/io_apic.c |  124 ++++++++++++++++++++++++++++++----------------
 arch/x86/kernel/irq_32.c  |    2 
 arch/x86/kernel/irq_64.c  |    4 -
 include/linux/irq.h       |   12 ----
 kernel/irq/chip.c         |   26 ---------
 kernel/irq/handle.c       |   34 +-----------
 kernel/irq/manage.c       |    8 --
 kernel/irq/migration.c    |    8 --
 10 files changed, 103 insertions(+), 130 deletions(-)

Index: linux-2.6/arch/Kconfig
===================================================================
--- linux-2.6.orig/arch/Kconfig
+++ linux-2.6/arch/Kconfig
@@ -106,6 +106,3 @@ config HAVE_CLK
 config HAVE_DYN_ARRAY
 	def_bool n
 
-config HAVE_SPARSE_IRQ
-	def_bool n
-
Index: linux-2.6/arch/x86/Kconfig
===================================================================
--- linux-2.6.orig/arch/x86/Kconfig
+++ linux-2.6/arch/x86/Kconfig
@@ -34,7 +34,6 @@ config X86
 	select HAVE_GENERIC_DMA_COHERENT if X86_32
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_DYN_ARRAY
-	select HAVE_SPARSE_IRQ
 
 config ARCH_DEFCONFIG
 	string
@@ -241,6 +240,17 @@ config SMP
 
 	  If you don't know what to do here, say N.
 
+config HAVE_SPARSE_IRQ
+	bool "Support sparse irq numbering"
+	depends on PCI_MSI || HT_IRQ
+	default y
+	help
+	  This enables support for sparse irq, esp for msi/msi-x. the irq
+	  number will be bus/dev/fn + 12bit. You may need if you have lots of
+	  cards supports msi-x installed.
+
+	  If you don't know what to do here, say Y.
+
 config X86_FIND_SMP_CONFIG
 	def_bool y
 	depends on X86_MPPARSE || X86_VOYAGER
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -107,7 +107,9 @@ struct irq_cfg;
 struct irq_pin_list;
 struct irq_cfg {
 	unsigned int irq;
+#ifdef CONFIG_HAVE_SPARSE_IRQ
 	struct irq_cfg *next;
+#endif
 	struct irq_pin_list *irq_2_pin;
 	cpumask_t domain;
 	cpumask_t old_domain;
@@ -137,20 +139,6 @@ static struct irq_cfg irq_cfg_legacy[] _
 };
 
 static struct irq_cfg irq_cfg_init = { .irq =  -1U, };
-/* need to be biger than size of irq_cfg_legacy */
-static int nr_irq_cfg = 32;
-
-static int __init parse_nr_irq_cfg(char *arg)
-{
-	if (arg) {
-		nr_irq_cfg = simple_strtoul(arg, NULL, 0);
-		if (nr_irq_cfg < 32)
-			nr_irq_cfg = 32;
-	}
-	return 0;
-}
-
-early_param("nr_irq_cfg", parse_nr_irq_cfg);
 
 static void init_one_irq_cfg(struct irq_cfg *cfg)
 {
@@ -158,7 +146,9 @@ static void init_one_irq_cfg(struct irq_
 }
 
 static struct irq_cfg *irq_cfgx;
+#ifdef CONFIG_HAVE_SPARSE_IRQ
 static struct irq_cfg *irq_cfgx_free;
+#endif
 static void __init init_work(void *data)
 {
 	struct dyn_array *da = data;
@@ -174,15 +164,34 @@ static void __init init_work(void *data)
 	for (i = legacy_count; i < *da->nr; i++)
 		init_one_irq_cfg(&cfg[i]);
 
+#ifdef CONFIG_HAVE_SPARSE_IRQ
 	for (i = 1; i < *da->nr; i++)
 		cfg[i-1].next = &cfg[i];
 
 	irq_cfgx_free = &irq_cfgx[legacy_count];
 	irq_cfgx[legacy_count - 1].next = NULL;
+#endif
 }
 
-#define for_each_irq_cfg(cfg)		\
-	for (cfg = irq_cfgx; cfg; cfg = cfg->next)
+#ifdef CONFIG_HAVE_SPARSE_IRQ
+/* need to be biger than size of irq_cfg_legacy */
+static int nr_irq_cfg = 32;
+
+static int __init parse_nr_irq_cfg(char *arg)
+{
+	if (arg) {
+		nr_irq_cfg = simple_strtoul(arg, NULL, 0);
+		if (nr_irq_cfg < 32)
+			nr_irq_cfg = 32;
+	}
+	return 0;
+}
+
+early_param("nr_irq_cfg", parse_nr_irq_cfg);
+
+#define for_each_irq_cfg(irqX, cfg)           \
+        for (cfg = irq_cfgx, irqX = cfg->irq; cfg; cfg = cfg->next, irqX = cfg ? cfg->irq : -1U)
+
 
 DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
 
@@ -273,7 +282,26 @@ static struct irq_cfg *irq_cfg_with_new(
 #endif
 	return cfg;
 }
+#else
 
+#define for_each_irq_cfg(irq, cfg)		\
+	for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq])
+
+DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work);
+
+struct irq_cfg *irq_cfg(unsigned int irq)
+{
+        if (irq < nr_irqs)
+                return &irq_cfgx[irq];
+
+        return NULL;
+}
+struct irq_cfg *irq_cfg_with_new(unsigned int irq)
+{
+        return irq_cfg(irq);
+}
+
+#endif
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -506,12 +534,13 @@ static void __target_IO_APIC_irq(unsigne
 
 static int assign_irq_vector(int irq, cpumask_t mask);
 
-static void set_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
 	struct irq_cfg *cfg;
 	unsigned long flags;
 	unsigned int dest;
 	cpumask_t tmp;
+	struct irq_desc *desc;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
@@ -528,6 +557,7 @@ static void set_ioapic_affinity_irq(unsi
 	 */
 	dest = SET_APIC_LOGICAL_ID(dest);
 
+	desc = irq_desc(irq);
 	spin_lock_irqsave(&ioapic_lock, flags);
 	__target_IO_APIC_irq(irq, dest, cfg->vector);
 	desc->affinity = mask;
@@ -1289,11 +1319,10 @@ void __setup_vector_irq(int cpu)
 	struct irq_cfg *cfg;
 
 	/* Mark the inuse vectors */
-	for_each_irq_cfg(cfg) {
+	for_each_irq_cfg(irq, cfg) {
 		if (!cpu_isset(cpu, cfg->domain))
 			continue;
 		vector = cfg->vector;
-		irq = cfg->irq;
 		per_cpu(vector_irq, cpu)[vector] = irq;
 	}
 	/* Mark the free vectors */
@@ -1570,6 +1599,7 @@ __apicdebuginit(void) print_IO_APIC(void
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 	struct irq_cfg *cfg;
+	unsigned int irq;
 
 	if (apic_verbosity == APIC_QUIET)
 		return;
@@ -1658,11 +1688,11 @@ __apicdebuginit(void) print_IO_APIC(void
 	}
 	}
 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
-	for_each_irq_cfg(cfg) {
+	for_each_irq_cfg(irq, cfg) {
 		struct irq_pin_list *entry = cfg->irq_2_pin;
 		if (!entry)
 			continue;
-		printk(KERN_DEBUG "IRQ%d ", cfg->irq);
+		printk(KERN_DEBUG "IRQ%d ", irq);
 		for (;;) {
 			printk("-> %d:%d", entry->apic, entry->pin);
 			if (!entry->next)
@@ -2299,7 +2329,7 @@ static void ir_irq_migration(struct work
 				continue;
 			}
 
-			desc->chip->set_affinity(irq, desc, desc->pending_mask);
+			desc->chip->set_affinity(irq, desc->pending_mask);
 			spin_unlock_irqrestore(&desc->lock, flags);
 		}
 	}
@@ -2308,8 +2338,10 @@ static void ir_irq_migration(struct work
 /*
  * Migrates the IRQ destination in the process context.
  */
-static void set_ir_ioapic_affinity_irq(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
+	struct irq_desc *desc = irq_desc(irq);
+
 	if (desc->status & IRQ_LEVEL) {
 		desc->status |= IRQ_MOVE_PENDING;
 		desc->pending_mask = mask;
@@ -2381,19 +2413,21 @@ static void irq_complete_move(unsigned i
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
 #ifdef CONFIG_INTR_REMAP
-static void ack_x2apic_level(unsigned int irq, struct irq_desc *desc)
+static void ack_x2apic_level(unsigned int irq)
 {
 	ack_x2APIC_irq();
 }
 
-static void ack_x2apic_edge(unsigned int irq, struct irq_desc *desc)
+static void ack_x2apic_edge(unsigned int irq)
 {
 	ack_x2APIC_irq();
 }
 #endif
 
-static void ack_apic_edge(unsigned int irq, struct irq_desc *desc)
+static void ack_apic_edge(unsigned int irq)
 {
+	struct irq_desc *desc = irq_desc(irq);
+
 	irq_complete_move(irq);
 	move_native_irq(irq, desc);
 	ack_APIC_irq();
@@ -2403,13 +2437,14 @@ static void ack_apic_edge(unsigned int i
 atomic_t irq_mis_count;
 #endif
 
-static void ack_apic_level(unsigned int irq, struct irq_desc *desc)
+static void ack_apic_level(unsigned int irq)
 {
 #ifdef CONFIG_X86_32
 	unsigned long v;
 	int i;
 #endif
 	int do_unmask_irq = 0;
+	struct irq_desc *desc = irq_desc(irq);
 
 	irq_complete_move(irq);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -2540,8 +2575,7 @@ static inline void init_IO_APIC_traps(vo
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	for_each_irq_cfg(cfg) {
-		irq = cfg->irq;
+	for_each_irq_cfg(irq, cfg) {
 		if (IO_APIC_IRQ(irq) && !cfg->vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2579,7 +2613,7 @@ static void unmask_lapic_irq(unsigned in
 	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
-static void ack_lapic_irq(unsigned int irq, struct irq_desc *desc)
+static void ack_lapic_irq(unsigned int irq)
 {
 	ack_APIC_irq();
 }
@@ -3128,12 +3162,13 @@ static int msi_compose_msg(struct pci_de
 }
 
 #ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
 	struct irq_cfg *cfg;
 	struct msi_msg msg;
 	unsigned int dest;
 	cpumask_t tmp;
+	struct irq_desc *desc;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
@@ -3154,6 +3189,7 @@ static void set_msi_irq_affinity(unsigne
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	write_msi_msg(irq, &msg);
+	desc = irq_desc(irq);
 	desc->affinity = mask;
 }
 
@@ -3162,12 +3198,13 @@ static void set_msi_irq_affinity(unsigne
  * Migrate the MSI irq to another cpumask. This migration is
  * done in the process context using interrupt-remapping hardware.
  */
-static void ir_set_msi_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
 	struct irq_cfg *cfg;
 	unsigned int dest;
 	cpumask_t tmp, cleanup_mask;
 	struct irte irte;
+	struct irq_desc *desc;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
@@ -3203,6 +3240,7 @@ static void ir_set_msi_irq_affinity(unsi
 		cfg->move_in_progress = 0;
 	}
 
+	desc = irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif
@@ -3403,12 +3441,13 @@ void arch_teardown_msi_irq(unsigned int
 
 #ifdef CONFIG_DMAR
 #ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
 {
 	struct irq_cfg *cfg;
 	struct msi_msg msg;
 	unsigned int dest;
 	cpumask_t tmp;
+	struct irq_desc *desc;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
@@ -3429,6 +3468,8 @@ static void dmar_msi_set_affinity(unsign
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	dmar_msi_write(irq, &msg);
+
+	desc = irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif /* CONFIG_SMP */
@@ -3481,11 +3522,12 @@ static void target_ht_irq(unsigned int i
 	write_ht_irq_msg(irq, &msg);
 }
 
-static void set_ht_irq_affinity(unsigned int irq, struct irq_desc *desc, cpumask_t mask)
+static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
 {
 	struct irq_cfg *cfg;
 	unsigned int dest;
 	cpumask_t tmp;
+	struct irq_desc *desc;
 
 	cpus_and(tmp, mask, cpu_online_map);
 	if (cpus_empty(tmp))
@@ -3499,6 +3541,7 @@ static void set_ht_irq_affinity(unsigned
 	dest = cpu_mask_to_apicid(tmp);
 
 	target_ht_irq(irq, dest, cfg->vector);
+	desc = irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif
@@ -3712,7 +3755,6 @@ void __init setup_ioapic_dest(void)
 {
 	int pin, ioapic, irq, irq_entry;
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 
 	if (skip_ioapic_setup == 1)
 		return;
@@ -3734,15 +3776,11 @@ void __init setup_ioapic_dest(void)
 						  irq_trigger(irq_entry),
 						  irq_polarity(irq_entry));
 #ifdef CONFIG_INTR_REMAP
-			else if (intr_remapping_enabled) {
-				desc = irq_desc(irq);
-				set_ir_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-			}
+			else if (intr_remapping_enabled)
+				set_ir_ioapic_affinity_irq(irq, TARGET_CPUS);
 #endif
-			else {
-				desc = irq_desc(irq);
-				set_ioapic_affinity_irq(irq, desc, TARGET_CPUS);
-			}
+			else
+				set_ioapic_affinity_irq(irq, TARGET_CPUS);
 		}
 	}
 }
Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_64.c
+++ linux-2.6/arch/x86/kernel/irq_64.c
@@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p,
 	struct irqaction * action;
 	unsigned long flags;
 	unsigned int entries;
-	struct irq_desc *desc;
+	struct irq_desc *desc = NULL;
 	int tail = 0;
 
 #ifdef CONFIG_HAVE_SPARSE_IRQ
@@ -275,7 +275,7 @@ void fixup_irqs(cpumask_t map)
 			desc->chip->mask(irq);
 
 		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, desc, mask);
+			desc->chip->set_affinity(irq, mask);
 		else if (!(warned++))
 			set_affinity = 0;
 
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -104,26 +104,14 @@ struct irq_chip {
 	void		(*enable)(unsigned int irq);
 	void		(*disable)(unsigned int irq);
 
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	void		(*ack)(unsigned int irq, struct irq_desc *desc);
-#else
 	void		(*ack)(unsigned int irq);
-#endif
 	void		(*mask)(unsigned int irq);
 	void		(*mask_ack)(unsigned int irq);
 	void		(*unmask)(unsigned int irq);
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	void		(*eoi)(unsigned int irq, struct irq_desc *desc);
-#else
 	void		(*eoi)(unsigned int irq);
-#endif
 
 	void		(*end)(unsigned int irq);
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	void		(*set_affinity)(unsigned int irq, struct irq_desc *desc, cpumask_t dest);
-#else
 	void		(*set_affinity)(unsigned int irq, cpumask_t dest);
-#endif
 	int		(*retrigger)(unsigned int irq);
 	int		(*set_type)(unsigned int irq, unsigned int flow_type);
 	int		(*set_wake)(unsigned int irq, unsigned int on);
Index: linux-2.6/kernel/irq/chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/chip.c
+++ linux-2.6/kernel/irq/chip.c
@@ -299,11 +299,7 @@ static inline void mask_ack_irq(struct i
 		desc->chip->mask_ack(irq);
 	else {
 		desc->chip->mask(irq);
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->ack(irq, desc);
-#else
 		desc->chip->ack(irq);
-#endif
 	}
 }
 
@@ -443,11 +439,7 @@ handle_fasteoi_irq(unsigned int irq, str
 	spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
 out:
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	desc->chip->eoi(irq, desc);
-#else
 	desc->chip->eoi(irq);
-#endif
 
 	spin_unlock(&desc->lock);
 }
@@ -490,11 +482,7 @@ handle_edge_irq(unsigned int irq, struct
 	kstat_irqs_this_cpu(desc)++;
 
 	/* Start handling the irq */
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	desc->chip->ack(irq, desc);
-#else
 	desc->chip->ack(irq);
-#endif
 
 	/* Mark the IRQ currently in progress.*/
 	desc->status |= IRQ_INPROGRESS;
@@ -548,25 +536,15 @@ handle_percpu_irq(unsigned int irq, stru
 
 	kstat_irqs_this_cpu(desc)++;
 
-	if (desc->chip->ack) {
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->ack(irq, desc);
-#else
+	if (desc->chip->ack)
 		desc->chip->ack(irq);
-#endif
-	}
 
 	action_ret = handle_IRQ_event(irq, desc->action);
 	if (!noirqdebug)
 		note_interrupt(irq, desc, action_ret);
 
-	if (desc->chip->eoi) {
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->eoi(irq, desc);
-#else
+	if (desc->chip->eoi)
 		desc->chip->eoi(irq);
-#endif
-	}
 }
 
 void
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -285,13 +285,6 @@ struct irq_desc *irq_desc_with_new(unsig
  * What should we do if we get a hw irq event on an illegal vector?
  * Each architecture has to answer this themself.
  */
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-static void ack_bad(unsigned int irq, struct irq_desc *desc)
-{
-	print_irq_desc(irq, desc);
-	ack_bad_irq(irq);
-}
-#else
 static void ack_bad(unsigned int irq)
 {
 	struct irq_desc *desc;
@@ -300,7 +293,6 @@ static void ack_bad(unsigned int irq)
 	print_irq_desc(irq, desc);
 	ack_bad_irq(irq);
 }
-#endif
 
 /*
  * NOP functions
@@ -309,12 +301,6 @@ static void noop(unsigned int irq)
 {
 }
 
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-static void noop_desc(unsigned int irq, struct irq_desc *desc)
-{
-}
-#endif
-
 static unsigned int noop_ret(unsigned int irq)
 {
 	return 0;
@@ -343,11 +329,7 @@ struct irq_chip dummy_irq_chip = {
 	.shutdown	= noop,
 	.enable		= noop,
 	.disable	= noop,
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	.ack		= noop_desc,
-#else
 	.ack		= noop,
-#endif
 	.mask		= noop,
 	.unmask		= noop,
 	.end		= noop,
@@ -415,13 +397,9 @@ unsigned int __do_IRQ(unsigned int irq,
 		/*
 		 * No locking required for CPU-local interrupts:
 		 */
-		if (desc->chip->ack) {
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-			desc->chip->ack(irq, desc);
-#else
+		if (desc->chip->ack)
 			desc->chip->ack(irq);
-#endif
-		}
+
 		if (likely(!(desc->status & IRQ_DISABLED))) {
 			action_ret = handle_IRQ_event(irq, desc->action);
 			if (!noirqdebug)
@@ -432,13 +410,9 @@ unsigned int __do_IRQ(unsigned int irq,
 	}
 
 	spin_lock(&desc->lock);
-	if (desc->chip->ack) {
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->ack(irq, desc);
-#else
+	if (desc->chip->ack)
 		desc->chip->ack(irq);
-#endif
-	}
+
 	/*
 	 * REPLAY is when Linux resends an IRQ that was dropped earlier
 	 * WAITING is used by probe to mark irqs that are being tested
Index: linux-2.6/kernel/irq/manage.c
===================================================================
--- linux-2.6.orig/kernel/irq/manage.c
+++ linux-2.6/kernel/irq/manage.c
@@ -91,11 +91,7 @@ int irq_set_affinity(unsigned int irq, c
 		unsigned long flags;
 
 		spin_lock_irqsave(&desc->lock, flags);
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->set_affinity(irq, desc, cpumask);
-#else
 		desc->chip->set_affinity(irq, cpumask);
-#endif
 		spin_unlock_irqrestore(&desc->lock, flags);
 	} else
 		set_pending_irq(irq, cpumask);
@@ -122,11 +118,7 @@ int irq_select_affinity(unsigned int irq
 
 	desc = irq_desc(irq);
 	desc->affinity = mask;
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-	desc->chip->set_affinity(irq, desc, mask);
-#else
 	desc->chip->set_affinity(irq, mask);
-#endif
 
 	return 0;
 }
Index: linux-2.6/kernel/irq/migration.c
===================================================================
--- linux-2.6.orig/kernel/irq/migration.c
+++ linux-2.6/kernel/irq/migration.c
@@ -51,13 +51,9 @@ void move_masked_irq(int irq, struct irq
 	 * For correct operation this depends on the caller
 	 * masking the irqs.
 	 */
-	if (likely(!cpus_empty(tmp))) {
-#ifdef CONFIG_HAVE_SPARSE_IRQ
-		desc->chip->set_affinity(irq, desc, tmp);
-#else
+	if (likely(!cpus_empty(tmp)))
 		desc->chip->set_affinity(irq, tmp);
-#endif
-	}
+
 	cpus_clear(desc->pending_mask);
 }
 
Index: linux-2.6/arch/x86/kernel/irq_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_32.c
+++ linux-2.6/arch/x86/kernel/irq_32.c
@@ -269,7 +269,7 @@ int show_interrupts(struct seq_file *p,
 	struct irqaction * action;
 	unsigned long flags;
 	unsigned int entries;
-	struct irq_desc *desc;
+	struct irq_desc *desc = NULL;
 	int tail = 0;
 
 #ifdef CONFIG_HAVE_SPARSE_IRQ
@@ -434,7 +434,7 @@ void fixup_irqs(cpumask_t map)
 			mask = map;
 		}
 		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, desc, mask);
+			desc->chip->set_affinity(irq, mask);
 		else if (desc->action && !(warned++))
 			printk("Cannot set affinity for irq %i\n", irq);
 	}

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 2/2] irq: rename irq_desc() to to_irq_desc()
  2008-08-18  4:12   ` [PATCH 1/2] x86: make HAVE_SPARSE_IRQ support selectable Yinghai Lu
@ 2008-08-18  4:12     ` Yinghai Lu
  2008-08-18  7:37       ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18  4:12 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

So could revert back to use irq_desc[] for other arch except x86

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/alpha/kernel/irq.c                     |   21 +--
 arch/alpha/kernel/irq_alpha.c               |    7 -
 arch/alpha/kernel/irq_i8259.c               |    8 -
 arch/alpha/kernel/irq_pyxis.c               |    9 -
 arch/alpha/kernel/irq_srm.c                 |    9 -
 arch/alpha/kernel/sys_alcor.c               |    9 -
 arch/alpha/kernel/sys_cabriolet.c           |    8 -
 arch/alpha/kernel/sys_dp264.c               |    9 -
 arch/alpha/kernel/sys_eb64p.c               |    8 -
 arch/alpha/kernel/sys_eiger.c               |    7 -
 arch/alpha/kernel/sys_jensen.c              |   50 ++++-----
 arch/alpha/kernel/sys_marvel.c              |   20 +--
 arch/alpha/kernel/sys_mikasa.c              |    8 -
 arch/alpha/kernel/sys_noritake.c            |    8 -
 arch/alpha/kernel/sys_rawhide.c             |    8 -
 arch/alpha/kernel/sys_rx164.c               |    8 -
 arch/alpha/kernel/sys_sable.c               |    8 -
 arch/alpha/kernel/sys_takara.c              |    8 -
 arch/alpha/kernel/sys_titan.c               |    8 -
 arch/alpha/kernel/sys_wildfire.c            |   19 +--
 arch/arm/common/gic.c                       |    2 
 arch/arm/common/it8152.c                    |    2 
 arch/arm/common/locomo.c                    |   16 +--
 arch/arm/common/sa1111.c                    |    4 
 arch/arm/kernel/ecard.c                     |    4 
 arch/arm/kernel/irq.c                       |    8 -
 arch/arm/mach-at91/gpio.c                   |    4 
 arch/arm/mach-davinci/gpio.c                |   13 --
 arch/arm/mach-ep93xx/core.c                 |   12 +-
 arch/arm/mach-footbridge/isa-irq.c          |    2 
 arch/arm/mach-h720x/common.c                |    2 
 arch/arm/mach-h720x/cpu-h7202.c             |    2 
 arch/arm/mach-imx/irq.c                     |    2 
 arch/arm/mach-integrator/integrator_cp.c    |    2 
 arch/arm/mach-iop13xx/msi.c                 |    2 
 arch/arm/mach-ixp2000/core.c                |    4 
 arch/arm/mach-ixp2000/ixdp2x00.c            |    2 
 arch/arm/mach-ixp2000/ixdp2x01.c            |    2 
 arch/arm/mach-ixp23xx/core.c                |    2 
 arch/arm/mach-ixp23xx/ixdp2351.c            |    4 
 arch/arm/mach-lh7a40x/common.h              |    2 
 arch/arm/mach-netx/generic.c                |    2 
 arch/arm/mach-ns9xxx/board-a9m9750dev.c     |    2 
 arch/arm/mach-omap1/fpga.c                  |    2 
 arch/arm/mach-orion5x/irq.c                 |   12 +-
 arch/arm/mach-pxa/gpio.c                    |    2 
 arch/arm/mach-pxa/lpd270.c                  |    2 
 arch/arm/mach-pxa/lubbock.c                 |    2 
 arch/arm/mach-pxa/mainstone.c               |    2 
 arch/arm/mach-pxa/pcm990-baseboard.c        |    2 
 arch/arm/mach-s3c2410/bast-irq.c            |    6 -
 arch/arm/mach-s3c2412/irq.c                 |    4 
 arch/arm/mach-s3c2440/irq.c                 |    4 
 arch/arm/mach-s3c2443/irq.c                 |    4 
 arch/arm/mach-sa1100/h3600.c                |   14 +-
 arch/arm/mach-sa1100/irq.c                  |    2 
 arch/arm/mach-sa1100/neponset.c             |    6 -
 arch/arm/mach-versatile/core.c              |    2 
 arch/arm/oprofile/op_model_mpcore.c         |    2 
 arch/arm/plat-mxc/gpio.c                    |    7 -
 arch/arm/plat-omap/gpio.c                   |   12 --
 arch/arm/plat-orion/irq.c                   |    2 
 arch/arm/plat-s3c24xx/irq.c                 |   14 +-
 arch/arm/plat-s3c24xx/s3c244x-irq.c         |    4 
 arch/avr32/mach-at32ap/extint.c             |    7 -
 arch/avr32/mach-at32ap/intc.c               |    2 
 arch/avr32/mach-at32ap/pio.c                |    2 
 arch/blackfin/kernel/irqchip.c              |   12 --
 arch/blackfin/kernel/traps.c                |    8 -
 arch/blackfin/mach-bf537/boards/cm_bf537.c  |    2 
 arch/blackfin/mach-bf537/boards/stamp.c     |    2 
 arch/blackfin/mach-bf561/boards/cm_bf561.c  |    2 
 arch/blackfin/mach-common/ints-priority.c   |    8 -
 arch/cris/arch-v10/kernel/irq.c             |    2 
 arch/cris/arch-v32/kernel/irq.c             |    6 -
 arch/cris/kernel/irq.c                      |   12 --
 arch/frv/kernel/irq.c                       |   10 -
 arch/h8300/kernel/irq.c                     |   24 +---
 arch/ia64/hp/sim/hpsim_irq.c                |    2 
 arch/ia64/include/asm/hw_irq.h              |    2 
 arch/ia64/kernel/iosapic.c                  |   19 +--
 arch/ia64/kernel/irq.c                      |   16 +--
 arch/ia64/kernel/irq_ia64.c                 |   12 +-
 arch/ia64/kernel/mca.c                      |    2 
 arch/ia64/kernel/msi_ia64.c                 |    4 
 arch/ia64/kernel/smpboot.c                  |    2 
 arch/ia64/sn/kernel/irq.c                   |   11 --
 arch/ia64/sn/kernel/msi_sn.c                |    4 
 arch/m32r/kernel/irq.c                      |   12 --
 arch/m32r/platforms/m32104ut/setup.c        |   37 +++---
 arch/m32r/platforms/m32700ut/setup.c        |  133 +++++++++++-------------
 arch/m32r/platforms/mappi/setup.c           |   84 ++++++---------
 arch/m32r/platforms/mappi2/setup.c          |  103 +++++++------------
 arch/m32r/platforms/mappi3/setup.c          |  103 +++++++------------
 arch/m32r/platforms/oaks32r/setup.c         |   62 ++++-------
 arch/m32r/platforms/opsput/setup.c          |  149 +++++++++++-----------------
 arch/m32r/platforms/usrv/setup.c            |   92 ++++++-----------
 arch/m68knommu/kernel/irq.c                 |   18 +--
 arch/mips/au1000/common/irq.c               |    2 
 arch/mips/dec/ioasic-irq.c                  |    2 
 arch/mips/emma2rh/markeins/irq_markeins.c   |    2 
 arch/mips/kernel/irq-gic.c                  |    2 
 arch/mips/kernel/irq-msc01.c                |    2 
 arch/mips/kernel/irq.c                      |   10 -
 arch/mips/kernel/smtc.c                     |    2 
 arch/mips/mti-malta/malta-smtc.c            |    2 
 arch/mips/sgi-ip22/ip22-int.c               |    2 
 arch/mips/sgi-ip22/ip22-time.c              |    2 
 arch/mips/sgi-ip32/ip32-irq.c               |   10 -
 arch/mips/sibyte/bcm1480/irq.c              |    5 
 arch/mips/sibyte/bcm1480/smp.c              |    2 
 arch/mips/sibyte/sb1250/irq.c               |    5 
 arch/mips/sibyte/sb1250/smp.c               |    2 
 arch/mips/sni/a20r.c                        |    2 
 arch/mips/sni/pcimt.c                       |    2 
 arch/mips/sni/pcit.c                        |    2 
 arch/mips/sni/rm200.c                       |    2 
 arch/mips/vr41xx/common/icu.c               |   44 ++++----
 arch/mips/vr41xx/common/irq.c               |    2 
 arch/mn10300/kernel/irq.c                   |   13 --
 arch/parisc/kernel/irq.c                    |   41 +++----
 arch/powerpc/include/asm/irq.h              |    2 
 arch/powerpc/kernel/crash.c                 |    2 
 arch/powerpc/kernel/irq.c                   |   15 +-
 arch/powerpc/platforms/8xx/m8xx_setup.c     |    2 
 arch/powerpc/platforms/powermac/pic.c       |    4 
 arch/powerpc/platforms/pseries/eeh_driver.c |    2 
 arch/powerpc/platforms/pseries/xics.c       |    4 
 arch/powerpc/sysdev/cpm2_pic.c              |    5 
 arch/powerpc/sysdev/mpic.c                  |   16 +--
 arch/powerpc/sysdev/qe_lib/qe_ic.c          |    2 
 arch/sh/boards/mach-cayman/irq.c            |    4 
 arch/sh/boards/mach-dreamcast/irq.c         |    2 
 arch/sh/boards/mach-dreamcast/setup.c       |    2 
 arch/sh/boards/mach-microdev/irq.c          |    4 
 arch/sh/boards/mach-se/7206/irq.c           |    2 
 arch/sh/boards/mach-se/7343/irq.c           |    2 
 arch/sh/boards/mach-se/7722/irq.c           |    2 
 arch/sh/boards/mach-systemh/irq.c           |    4 
 arch/sh/cchips/hd6446x/hd64461.c            |    4 
 arch/sh/cchips/hd6446x/hd64465/setup.c      |    4 
 arch/sh/kernel/cpu/irq/imask.c              |    4 
 arch/sh/kernel/cpu/irq/intc-sh5.c           |    4 
 arch/sh/kernel/irq.c                        |   12 --
 arch/sparc64/kernel/irq.c                   |   41 +++----
 arch/sparc64/kernel/pci_msi.c               |    2 
 arch/sparc64/kernel/time.c                  |    2 
 arch/um/kernel/irq.c                        |   31 ++---
 arch/x86/kernel/io_apic.c                   |   32 +++---
 arch/x86/kernel/irq_32.c                    |    4 
 arch/x86/kernel/irq_64.c                    |    4 
 arch/x86/kernel/irqinit_32.c                |    2 
 arch/x86/kernel/irqinit_64.c                |    2 
 arch/x86/kernel/visws_quirks.c              |    8 -
 arch/x86/mach-voyager/voyager_smp.c         |    4 
 arch/xtensa/kernel/irq.c                    |   12 --
 drivers/char/random.c                       |    4 
 drivers/gpio/gpiolib.c                      |    2 
 drivers/mfd/asic3.c                         |    4 
 drivers/mfd/htc-egpio.c                     |    2 
 drivers/parisc/dino.c                       |    6 -
 drivers/parisc/eisa.c                       |    6 -
 drivers/parisc/gsc.c                        |    8 -
 drivers/parisc/iosapic.c                    |    2 
 drivers/parisc/superio.c                    |    4 
 drivers/pci/intr_remapping.c                |    4 
 drivers/pcmcia/hd64465_ss.c                 |    4 
 drivers/xen/events.c                        |    6 -
 include/asm-mips/irq.h                      |    2 
 include/linux/irq.h                         |   26 ++--
 kernel/irq/autoprobe.c                      |   10 -
 kernel/irq/chip.c                           |   28 ++---
 kernel/irq/handle.c                         |   24 ++--
 kernel/irq/manage.c                         |   26 ++--
 kernel/irq/migration.c                      |    2 
 kernel/irq/proc.c                           |   12 +-
 kernel/irq/resend.c                         |    2 
 kernel/irq/spurious.c                       |    4 
 178 files changed, 877 insertions(+), 1129 deletions(-)

Index: linux-2.6/arch/alpha/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq.c
+++ linux-2.6/arch/alpha/kernel/irq.c
@@ -46,19 +46,16 @@ int irq_select_affinity(unsigned int irq
 {
 	static int last_cpu;
 	int cpu = last_cpu + 1;
-	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
-
-	if (!desc->chip->set_affinity || irq_user_affinity[irq])
+	if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq])
 		return 1;
 
 	while (!cpu_possible(cpu) || !cpu_isset(cpu, irq_default_affinity))
 		cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
 	last_cpu = cpu;
 
-	desc->affinity = cpumask_of_cpu(cpu);
-	desc->chip->set_affinity(irq, cpumask_of_cpu(cpu));
+	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
 	return 0;
 }
 #endif /* CONFIG_SMP */
@@ -83,10 +80,8 @@ show_interrupts(struct seq_file *p, void
 #endif
 
 	if (irq < ACTUAL_NR_IRQS) {
-		struct irq_desc *desc = irq_desc(irq);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[irq].lock, flags);
+		action = irq_desc[irq].action;
 		if (!action) 
 			goto unlock;
 		seq_printf(p, "%3d: ", irq);
@@ -96,7 +91,7 @@ show_interrupts(struct seq_file *p, void
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[irq].chip->typename);
 		seq_printf(p, "  %c%s",
 			(action->flags & IRQF_DISABLED)?'+':' ',
 			action->name);
@@ -109,7 +104,7 @@ show_interrupts(struct seq_file *p, void
 
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
 	} else if (irq == ACTUAL_NR_IRQS) {
 #ifdef CONFIG_SMP
 		seq_puts(p, "IPI: ");
@@ -161,6 +156,6 @@ handle_irq(int irq)
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 }
Index: linux-2.6/arch/alpha/kernel/irq_alpha.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c
+++ linux-2.6/arch/alpha/kernel/irq_alpha.c
@@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned l
 		smp_percpu_timer_interrupt(regs);
 		cpu = smp_processor_id();
 		if (cpu != boot_cpuid) {
-			irq_desc(RTC_IRQ)->kstat_irqs[cpu]++;
+			irq_desc[RTC_IRQ].kstat_irqs[cpu]++;
 		} else {
 			handle_irq(RTC_IRQ);
 		}
@@ -240,9 +240,8 @@ static struct hw_interrupt_type rtc_irq_
 void __init
 init_rtc_irq(void)
 {
-	struct irq_desc *desc = irq_desc(RTC_IRQ);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &rtc_irq_type;
+	irq_desc[RTC_IRQ].status = IRQ_DISABLED;
+	irq_desc[RTC_IRQ].chip = &rtc_irq_type;
 	setup_irq(RTC_IRQ, &timer_irqaction);
 }
 
Index: linux-2.6/arch/alpha/kernel/irq_i8259.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_i8259.c
+++ linux-2.6/arch/alpha/kernel/irq_i8259.c
@@ -79,7 +79,7 @@ i8259a_startup_irq(unsigned int irq)
 void
 i8259a_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		i8259a_enable_irq(irq);
 }
 
@@ -107,10 +107,8 @@ init_i8259a_irqs(void)
 	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
 
 	for (i = 0; i < 16; i++) {
-		struct irq_desc *desc;
-		desc = irq_desc(i);
-		desc->status = IRQ_DISABLED;
-		desc->chip = &i8259a_irq_type;
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].chip = &i8259a_irq_type;
 	}
 
 	setup_irq(2, &cascade);
Index: linux-2.6/arch/alpha/kernel/irq_pyxis.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_pyxis.c
+++ linux-2.6/arch/alpha/kernel/irq_pyxis.c
@@ -50,7 +50,7 @@ pyxis_startup_irq(unsigned int irq)
 static void
 pyxis_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		pyxis_enable_irq(irq);
 }
 
@@ -117,13 +117,10 @@ init_pyxis_irqs(unsigned long ignore_mas
 	*(vuip) CIA_IACK_SC;
 
 	for (i = 16; i < 48; ++i) {
-		struct irq_desc *desc;
-
 		if ((ignore_mask >> i) & 1)
 			continue;
-		desc = irq_desc(i);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &pyxis_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &pyxis_irq_type;
 	}
 
 	setup_irq(16+7, &isa_cascade_irqaction);
Index: linux-2.6/arch/alpha/kernel/irq_srm.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_srm.c
+++ linux-2.6/arch/alpha/kernel/irq_srm.c
@@ -43,7 +43,7 @@ srm_startup_irq(unsigned int irq)
 static void
 srm_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		srm_enable_irq(irq);
 }
 
@@ -64,13 +64,10 @@ init_srm_irqs(long max, unsigned long ig
 	long i;
 
 	for (i = 16; i < max; ++i) {
-		struct irq_desc *desc;
-
 		if (i < 64 && ((ignore_mask >> i) & 1))
 			continue;
-		desc = irq_desc(i);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &srm_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &srm_irq_type;
 	}
 }
 
Index: linux-2.6/arch/alpha/kernel/sys_alcor.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_alcor.c
+++ linux-2.6/arch/alpha/kernel/sys_alcor.c
@@ -85,7 +85,7 @@ alcor_isa_mask_and_ack_irq(unsigned int
 static void
 alcor_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		alcor_enable_irq(irq);
 }
 
@@ -137,16 +137,13 @@ alcor_init_irq(void)
 	*(vuip)GRU_INT_CLEAR = 0; mb();			/* all clear */
 
 	for (i = 16; i < 48; ++i) {
-		struct irq_desc *desc;
-
 		/* On Alcor, at least, lines 20..30 are not connected
 		   and can generate spurious interrupts if we turn them
 		   on while IRQ probing.  */
 		if (i >= 16+20 && i <= 16+30)
 			continue;
-		desc = irq_desc(i);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &alcor_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &alcor_irq_type;
 	}
 	i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
 
Index: linux-2.6/arch/alpha/kernel/sys_cabriolet.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_cabriolet.c
+++ linux-2.6/arch/alpha/kernel/sys_cabriolet.c
@@ -67,7 +67,7 @@ cabriolet_startup_irq(unsigned int irq)
 static void
 cabriolet_end_irq(unsigned int irq)
 { 
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		cabriolet_enable_irq(irq);
 }
 
@@ -122,10 +122,8 @@ common_init_irq(void (*srm_dev_int)(unsi
 		outb(0xff, 0x806);
 
 		for (i = 16; i < 35; ++i) {
-			struct irq_desc *desc = irq_desc(i);
-
-			desc->status = IRQ_DISABLED | IRQ_LEVEL;
-			desc->chip = &cabriolet_irq_type;
+			irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+			irq_desc[i].chip = &cabriolet_irq_type;
 		}
 	}
 
Index: linux-2.6/arch/alpha/kernel/sys_dp264.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_dp264.c
+++ linux-2.6/arch/alpha/kernel/sys_dp264.c
@@ -125,7 +125,7 @@ dp264_startup_irq(unsigned int irq)
 static void
 dp264_end_irq(unsigned int irq)
 { 
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		dp264_enable_irq(irq);
 }
 
@@ -157,7 +157,7 @@ clipper_startup_irq(unsigned int irq)
 static void
 clipper_end_irq(unsigned int irq)
 { 
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		clipper_enable_irq(irq);
 }
 
@@ -298,9 +298,8 @@ init_tsunami_irqs(struct hw_interrupt_ty
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = ops;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = ops;
 	}
 }
 
Index: linux-2.6/arch/alpha/kernel/sys_eb64p.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_eb64p.c
+++ linux-2.6/arch/alpha/kernel/sys_eb64p.c
@@ -65,7 +65,7 @@ eb64p_startup_irq(unsigned int irq)
 static void
 eb64p_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		eb64p_enable_irq(irq);
 }
 
@@ -135,10 +135,8 @@ eb64p_init_irq(void)
 	init_i8259a_irqs();
 
 	for (i = 16; i < 32; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &eb64p_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &eb64p_irq_type;
 	}		
 
 	common_init_isa_dma();
Index: linux-2.6/arch/alpha/kernel/sys_eiger.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_eiger.c
+++ linux-2.6/arch/alpha/kernel/sys_eiger.c
@@ -76,7 +76,7 @@ eiger_startup_irq(unsigned int irq)
 static void
 eiger_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		eiger_enable_irq(irq);
 }
 
@@ -153,9 +153,8 @@ eiger_init_irq(void)
 	init_i8259a_irqs();
 
 	for (i = 16; i < 128; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &eiger_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &eiger_irq_type;
 	}
 }
 
Index: linux-2.6/arch/alpha/kernel/sys_jensen.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_jensen.c
+++ linux-2.6/arch/alpha/kernel/sys_jensen.c
@@ -68,16 +68,13 @@ jensen_local_startup(unsigned int irq)
 	/* the parport is really hw IRQ 1, silly Jensen.  */
 	if (irq == 7)
 		i8259a_startup_irq(1);
-	else {
-		struct irq_desc *desc = irq_desc(irq);
-
+	else
 		/*
 		 * For all true local interrupts, set the flag that prevents
 		 * the IPL from being dropped during handler processing.
 		 */
-		if (desc->action)
-			desc->action->flags |= IRQF_DISABLED;
-	}
+		if (irq_desc[irq].action)
+			irq_desc[irq].action->flags |= IRQF_DISABLED;
 	return 0;
 }
 
@@ -161,21 +158,22 @@ jensen_device_interrupt(unsigned long ve
 	}
 
 	/* If there is no handler yet... */
-	if (irq_desc(irq)->action == NULL) {
-		/* If it is a local interrupt that cannot be masked... */
-		if (vector >= 0x900) {
-			/* Clear keyboard/mouse state */
-			inb(0x64);
-			inb(0x60);
-			/* Reset serial ports */
-			inb(0x3fa);
-			inb(0x2fa);
-			outb(0x0c, 0x3fc);
-			outb(0x0c, 0x2fc);
-			/* Clear NMI */
-			outb(0, 0x61);
-			outb(0, 0x461);
-		}
+	if (irq_desc[irq].action == NULL) {
+	    /* If it is a local interrupt that cannot be masked... */
+	    if (vector >= 0x900)
+	    {
+	        /* Clear keyboard/mouse state */
+	    	inb(0x64);
+		inb(0x60);
+		/* Reset serial ports */
+		inb(0x3fa);
+		inb(0x2fa);
+		outb(0x0c, 0x3fc);
+		outb(0x0c, 0x2fc);
+		/* Clear NMI */
+		outb(0,0x61);
+		outb(0,0x461);
+	    }
 	}
 
 #if 0
@@ -208,11 +206,11 @@ jensen_init_irq(void)
 {
 	init_i8259a_irqs();
 
-	irq_desc(1)->chip = &jensen_local_irq_type;
-	irq_desc(4)->chip = &jensen_local_irq_type;
-	irq_desc(3)->chip = &jensen_local_irq_type;
-	irq_desc(7)->chip = &jensen_local_irq_type;
-	irq_desc(9)->chip = &jensen_local_irq_type;
+	irq_desc[1].chip = &jensen_local_irq_type;
+	irq_desc[4].chip = &jensen_local_irq_type;
+	irq_desc[3].chip = &jensen_local_irq_type;
+	irq_desc[7].chip = &jensen_local_irq_type;
+	irq_desc[9].chip = &jensen_local_irq_type;
 
 	common_init_isa_dma();
 }
Index: linux-2.6/arch/alpha/kernel/sys_marvel.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_marvel.c
+++ linux-2.6/arch/alpha/kernel/sys_marvel.c
@@ -152,7 +152,7 @@ io7_startup_irq(unsigned int irq)
 static void
 io7_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		io7_enable_irq(irq);
 }
 
@@ -303,10 +303,8 @@ init_io7_irqs(struct io7 *io7,
 
 	/* Set up the lsi irqs.  */
 	for (i = 0; i < 128; ++i) {
-		struct irq_desc *desc = irq_desc(base + i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = lsi_ops;
+		irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[base + i].chip = lsi_ops;
 	}
 
 	/* Disable the implemented irqs in hardware.  */
@@ -319,10 +317,8 @@ init_io7_irqs(struct io7 *io7,
 
 	/* Set up the msi irqs.  */
 	for (i = 128; i < (128 + 512); ++i) {
-		struct irq_desc *desc = irq_desc(base + i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = msi_ops;
+		irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[base + i].chip = msi_ops;
 	}
 
 	for (i = 0; i < 16; ++i)
@@ -339,10 +335,8 @@ marvel_init_irq(void)
 
 	/* Reserve the legacy irqs.  */
 	for (i = 0; i < 16; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED;
-		desc->chip = &marvel_legacy_irq_type;
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].chip = &marvel_legacy_irq_type;
 	}
 
 	/* Init the io7 irqs.  */
Index: linux-2.6/arch/alpha/kernel/sys_mikasa.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_mikasa.c
+++ linux-2.6/arch/alpha/kernel/sys_mikasa.c
@@ -64,7 +64,7 @@ mikasa_startup_irq(unsigned int irq)
 static void
 mikasa_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		mikasa_enable_irq(irq);
 }
 
@@ -115,10 +115,8 @@ mikasa_init_irq(void)
 	mikasa_update_irq_hw(0);
 
 	for (i = 16; i < 32; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &mikasa_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &mikasa_irq_type;
 	}
 
 	init_i8259a_irqs();
Index: linux-2.6/arch/alpha/kernel/sys_noritake.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_noritake.c
+++ linux-2.6/arch/alpha/kernel/sys_noritake.c
@@ -69,7 +69,7 @@ noritake_startup_irq(unsigned int irq)
 static void
 noritake_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
                 noritake_enable_irq(irq);
 }
 
@@ -144,10 +144,8 @@ noritake_init_irq(void)
 	outw(0, 0x54c);
 
 	for (i = 16; i < 48; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &noritake_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &noritake_irq_type;
 	}
 
 	init_i8259a_irqs();
Index: linux-2.6/arch/alpha/kernel/sys_rawhide.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_rawhide.c
+++ linux-2.6/arch/alpha/kernel/sys_rawhide.c
@@ -131,7 +131,7 @@ rawhide_startup_irq(unsigned int irq)
 static void
 rawhide_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		rawhide_enable_irq(irq);
 }
 
@@ -194,10 +194,8 @@ rawhide_init_irq(void)
 	}
 
 	for (i = 16; i < 128; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &rawhide_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &rawhide_irq_type;
 	}
 
 	init_i8259a_irqs();
Index: linux-2.6/arch/alpha/kernel/sys_rx164.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_rx164.c
+++ linux-2.6/arch/alpha/kernel/sys_rx164.c
@@ -68,7 +68,7 @@ rx164_startup_irq(unsigned int irq)
 static void
 rx164_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		rx164_enable_irq(irq);
 }
 
@@ -116,10 +116,8 @@ rx164_init_irq(void)
 
 	rx164_update_irq_hw(0);
 	for (i = 16; i < 40; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &rx164_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &rx164_irq_type;
 	}
 
 	init_i8259a_irqs();
Index: linux-2.6/arch/alpha/kernel/sys_sable.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_sable.c
+++ linux-2.6/arch/alpha/kernel/sys_sable.c
@@ -484,7 +484,7 @@ sable_lynx_startup_irq(unsigned int irq)
 static void
 sable_lynx_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		sable_lynx_enable_irq(irq);
 }
 
@@ -535,10 +535,8 @@ sable_lynx_init_irq(int nr_irqs)
 	long i;
 
 	for (i = 0; i < nr_irqs; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &sable_lynx_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &sable_lynx_irq_type;
 	}
 
 	common_init_isa_dma();
Index: linux-2.6/arch/alpha/kernel/sys_takara.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_takara.c
+++ linux-2.6/arch/alpha/kernel/sys_takara.c
@@ -70,7 +70,7 @@ takara_startup_irq(unsigned int irq)
 static void
 takara_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		takara_enable_irq(irq);
 }
 
@@ -153,10 +153,8 @@ takara_init_irq(void)
 		takara_update_irq_hw(i, -1);
 
 	for (i = 16; i < 128; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &takara_irq_type;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = &takara_irq_type;
 	}
 
 	common_init_isa_dma();
Index: linux-2.6/arch/alpha/kernel/sys_titan.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_titan.c
+++ linux-2.6/arch/alpha/kernel/sys_titan.c
@@ -139,7 +139,7 @@ titan_startup_irq(unsigned int irq)
 static void
 titan_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		titan_enable_irq(irq);
 }
 
@@ -187,10 +187,8 @@ init_titan_irqs(struct hw_interrupt_type
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		struct irq_desc *desc = irq_desc(i);
-
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = ops;
+		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i].chip = ops;
 	}
 }
 
Index: linux-2.6/arch/alpha/kernel/sys_wildfire.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/sys_wildfire.c
+++ linux-2.6/arch/alpha/kernel/sys_wildfire.c
@@ -150,10 +150,10 @@ static void
 wildfire_end_irq(unsigned int irq)
 { 
 #if 0
-	if (!irq_desc(irq)->action)
+	if (!irq_desc[irq].action)
 		printk("got irq %d\n", irq);
 #endif
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		wildfire_enable_irq(irq);
 }
 
@@ -196,20 +196,17 @@ wildfire_init_irq_per_pca(int qbbno, int
 #endif
 
 	for (i = 0; i < 16; ++i) {
-		struct irq_desc *desc;
 		if (i == 2)
 			continue;
-		desc = irq_desc(i+irq_bias);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &wildfire_irq_type;
+		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i+irq_bias].chip = &wildfire_irq_type;
 	}
 
-	irq_desc(36+irq_bias)->status = IRQ_DISABLED | IRQ_LEVEL;
-	irq_desc(36+irq_bias)->chip = &wildfire_irq_type;
+	irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+	irq_desc[36+irq_bias].chip = &wildfire_irq_type;
 	for (i = 40; i < 64; ++i) {
-		struct irq_desc *desc = irq_desc(i+irq_bias);
-		desc->status = IRQ_DISABLED | IRQ_LEVEL;
-		desc->chip = &wildfire_irq_type;
+		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
+		irq_desc[i+irq_bias].chip = &wildfire_irq_type;
 	}
 
 	setup_irq(32+irq_bias, &isa_enable);	
Index: linux-2.6/arch/arm/common/gic.c
===================================================================
--- linux-2.6.orig/arch/arm/common/gic.c
+++ linux-2.6/arch/arm/common/gic.c
@@ -117,7 +117,7 @@ static void gic_set_cpu(unsigned int irq
 	u32 val;
 
 	spin_lock(&irq_controller_lock);
-	irq_desc(irq)->cpu = cpu;
+	irq_desc[irq].cpu = cpu;
 	val = readl(reg) & ~(0xff << shift);
 	val |= 1 << (cpu + shift);
 	writel(val, reg);
Index: linux-2.6/arch/arm/common/it8152.c
===================================================================
--- linux-2.6.orig/arch/arm/common/it8152.c
+++ linux-2.6/arch/arm/common/it8152.c
@@ -70,7 +70,7 @@ static inline void it8152_irq(int irq)
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	desc_handle_irq(irq, desc);
 }
 
Index: linux-2.6/arch/arm/common/locomo.c
===================================================================
--- linux-2.6.orig/arch/arm/common/locomo.c
+++ linux-2.6/arch/arm/common/locomo.c
@@ -181,8 +181,8 @@ static void locomo_handler(unsigned int
 	if (req) {
 		/* generate the next interrupt(s) */
 		irq = LOCOMO_IRQ_START;
-		d = irq_desc(irq);
-		for (i = 0; i <= 3; i++, irq++, d = irq_desc(irq)) {
+		d = irq_desc + irq;
+		for (i = 0; i <= 3; i++, d++, irq++) {
 			if (req & (0x0100 << i)) {
 				desc_handle_irq(irq, d);
 			}
@@ -226,7 +226,7 @@ static void locomo_key_handler(unsigned
 	void __iomem *mapbase = get_irq_chip_data(irq);
 
 	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
-		d = irq_desc(LOCOMO_IRQ_KEY_START);
+		d = irq_desc + LOCOMO_IRQ_KEY_START;
 		desc_handle_irq(LOCOMO_IRQ_KEY_START, d);
 	}
 }
@@ -277,8 +277,8 @@ static void locomo_gpio_handler(unsigned
 
 	if (req) {
 		irq = LOCOMO_IRQ_GPIO_START;
-		d = irq_desc(LOCOMO_IRQ_GPIO_START);
-		for (i = 0; i <= 15; i++, irq++, d = irq_desc(irq)) {
+		d = irq_desc + LOCOMO_IRQ_GPIO_START;
+		for (i = 0; i <= 15; i++, irq++, d++) {
 			if (req & (0x0001 << i)) {
 				desc_handle_irq(irq, d);
 			}
@@ -365,7 +365,7 @@ static void locomo_lt_handler(unsigned i
 	void __iomem *mapbase = get_irq_chip_data(irq);
 
 	if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
-		d = irq_desc(LOCOMO_IRQ_LT_START);
+		d = irq_desc + LOCOMO_IRQ_LT_START;
 		desc_handle_irq(LOCOMO_IRQ_LT_START, d);
 	}
 }
@@ -413,9 +413,9 @@ static void locomo_spi_handler(unsigned
 	req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
 	if (req) {
 		irq = LOCOMO_IRQ_SPI_START;
-		d = irq_desc(irq);
+		d = irq_desc + irq;
 
-		for (i = 0; i <= 3; i++, irq++, d = irq_desc(irq)) {
+		for (i = 0; i <= 3; i++, irq++, d++) {
 			if (req & (0x0001 << i)) {
 				desc_handle_irq(irq, d);
 			}
Index: linux-2.6/arch/arm/common/sa1111.c
===================================================================
--- linux-2.6.orig/arch/arm/common/sa1111.c
+++ linux-2.6/arch/arm/common/sa1111.c
@@ -170,11 +170,11 @@ sa1111_irq_handler(unsigned int irq, str
 
 	for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
 		if (stat0 & 1)
-			handle_edge_irq(i, irq_desc(i));
+			handle_edge_irq(i, irq_desc + i);
 
 	for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
 		if (stat1 & 1)
-			handle_edge_irq(i, irq_desc(i));
+			handle_edge_irq(i, irq_desc + i);
 
 	/* For level-based interrupts */
 	desc->chip->unmask(irq);
Index: linux-2.6/arch/arm/kernel/ecard.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/ecard.c
+++ linux-2.6/arch/arm/kernel/ecard.c
@@ -587,7 +587,7 @@ ecard_irq_handler(unsigned int irq, stru
 			pending = ecard_default_ops.irqpending(ec);
 
 		if (pending) {
-			struct irq_desc *d = irq_desc(ec->irq);
+			struct irq_desc *d = irq_desc + ec->irq;
 			desc_handle_irq(ec->irq, d);
 			called ++;
 		}
@@ -622,7 +622,7 @@ ecard_irqexp_handler(unsigned int irq, s
 		ecard_t *ec = slot_to_ecard(slot);
 
 		if (ec->claimed) {
-			struct irq_desc *d = irq_desc(ec->irq);
+			struct irq_desc *d = irq_desc + ec->irq;
 			/*
 			 * this ugly code is so that we can operate a
 			 * prioritorising system:
Index: linux-2.6/arch/arm/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/irq.c
+++ linux-2.6/arch/arm/kernel/irq.c
@@ -112,7 +112,7 @@ static struct irq_desc bad_irq_desc = {
 asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 
 	/*
 	 * Some hardware gives randomly wrong interrupts.  Rather
@@ -142,7 +142,7 @@ void set_irq_flags(unsigned int irq, uns
 		return;
 	}
 
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	spin_lock_irqsave(&desc->lock, flags);
 	desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
 	if (iflags & IRQF_VALID)
@@ -159,7 +159,7 @@ void __init init_IRQ(void)
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++)
-		irq_desc(irq)->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
+		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
 #ifdef CONFIG_SMP
 	bad_irq_desc.affinity = CPU_MASK_ALL;
@@ -189,7 +189,7 @@ void migrate_irqs(void)
 	unsigned int i, cpu = smp_processor_id();
 
 	for (i = 0; i < NR_IRQS; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = irq_desc + i;
 
 		if (desc->cpu == cpu) {
 			unsigned int newcpu = any_online_cpu(desc->affinity);
Index: linux-2.6/arch/arm/mach-at91/gpio.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-at91/gpio.c
+++ linux-2.6/arch/arm/mach-at91/gpio.c
@@ -404,7 +404,7 @@ static void gpio_irq_handler(unsigned ir
 		}
 
 		pin = bank->chipbase;
-		gpio = irq_desc(pin);
+		gpio = &irq_desc[pin];
 
 		while (isr) {
 			if (isr & 1) {
@@ -515,7 +515,7 @@ void __init at91_gpio_irq_setup(void)
 		__raw_writel(~0, this->regbase + PIO_IDR);
 
 		for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
-			lockdep_set_class(&irq_desc(pin)->lock, &gpio_lock_class);
+			lockdep_set_class(&irq_desc[pin].lock, &gpio_lock_class);
 
 			/*
 			 * Can use the "simple" and not "edge" handler since it's
Index: linux-2.6/arch/arm/mach-davinci/gpio.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-davinci/gpio.c
+++ linux-2.6/arch/arm/mach-davinci/gpio.c
@@ -155,11 +155,10 @@ static void gpio_irq_enable(unsigned irq
 {
 	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
 	u32 mask = __gpio_mask(irq_to_gpio(irq));
-	struct irq_desc *desc = irq_desc(irq);
 
-	if (desc->status & IRQ_TYPE_EDGE_FALLING)
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
 		__raw_writel(mask, &g->set_falling);
-	if (desc->status & IRQ_TYPE_EDGE_RISING)
+	if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
 		__raw_writel(mask, &g->set_rising);
 }
 
@@ -167,14 +166,12 @@ static int gpio_irq_type(unsigned irq, u
 {
 	struct gpio_controller *__iomem g = get_irq_chip_data(irq);
 	u32 mask = __gpio_mask(irq_to_gpio(irq));
-	struct irq_desc *desc;
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
 
-	desc = irq_desc(irq);
-	desc->status &= ~IRQ_TYPE_SENSE_MASK;
-	desc->status |= trigger;
+	irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+	irq_desc[irq].status |= trigger;
 
 	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
 		     ? &g->set_falling : &g->clr_falling);
@@ -218,7 +215,7 @@ gpio_irq_handler(unsigned irq, struct ir
 
 		/* now demux them to the right lowlevel handler */
 		n = (int)get_irq_data(irq);
-		gpio = irq_desc(n);
+		gpio = &irq_desc[n];
 		while (status) {
 			res = ffs(status);
 			n += res;
Index: linux-2.6/arch/arm/mach-ep93xx/core.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ep93xx/core.c
+++ linux-2.6/arch/arm/mach-ep93xx/core.c
@@ -192,7 +192,7 @@ static void ep93xx_gpio_ab_irq_handler(u
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
-			desc = irq_desc(gpio_irq);
+			desc = irq_desc + gpio_irq;
 			desc_handle_irq(gpio_irq, desc);
 		}
 	}
@@ -201,7 +201,7 @@ static void ep93xx_gpio_ab_irq_handler(u
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
-			desc = irq_desc(gpio_irq);
+			desc = irq_desc + gpio_irq;
 			desc_handle_irq(gpio_irq, desc);
 		}
 	}
@@ -217,7 +217,7 @@ static void ep93xx_gpio_f_irq_handler(un
 	int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
 	int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
 
-	desc_handle_irq(gpio_irq, irq_desc(gpio_irq));
+	desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
 }
 
 static void ep93xx_gpio_irq_ack(unsigned int irq)
@@ -226,7 +226,7 @@ static void ep93xx_gpio_irq_ack(unsigned
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc(irq)->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 		ep93xx_gpio_update_int_params(port);
 	}
@@ -240,7 +240,7 @@ static void ep93xx_gpio_irq_mask_ack(uns
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc(irq)->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+	if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 
 	gpio_int_unmasked[port] &= ~port_mask;
@@ -275,7 +275,7 @@ static void ep93xx_gpio_irq_unmask(unsig
  */
 static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	const int gpio = irq_to_gpio(irq);
 	const int port = gpio >> 3;
 	const int port_mask = 1 << (gpio & 7);
Index: linux-2.6/arch/arm/mach-footbridge/isa-irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-footbridge/isa-irq.c
+++ linux-2.6/arch/arm/mach-footbridge/isa-irq.c
@@ -94,7 +94,7 @@ isa_irq_handler(unsigned int irq, struct
 		return;
 	}
 
-	desc = irq_desc(isa_irq);
+	desc = irq_desc + isa_irq;
 	desc_handle_irq(isa_irq, desc);
 }
 
Index: linux-2.6/arch/arm/mach-h720x/common.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-h720x/common.c
+++ linux-2.6/arch/arm/mach-h720x/common.c
@@ -104,7 +104,7 @@ h720x_gpio_handler(unsigned int mask, un
                  struct irq_desc *desc)
 {
 	IRQDBG("%s irq: %d\n", __func__, irq);
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1) {
 			IRQDBG("handling irq %d\n", irq);
Index: linux-2.6/arch/arm/mach-h720x/cpu-h7202.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-h720x/cpu-h7202.c
+++ linux-2.6/arch/arm/mach-h720x/cpu-h7202.c
@@ -120,7 +120,7 @@ h7202_timerx_demux_handler(unsigned int
 
 	mask >>= 1;
 	irq = IRQ_TIMER1;
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1)
 			desc_handle_irq(irq, desc);
Index: linux-2.6/arch/arm/mach-imx/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-imx/irq.c
+++ linux-2.6/arch/arm/mach-imx/irq.c
@@ -182,7 +182,7 @@ static void
 imx_gpio_handler(unsigned int mask, unsigned int irq,
                  struct irq_desc *desc)
 {
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	while (mask) {
 		if (mask & 1) {
 			DEBUG_IRQ("handling irq %d\n", irq);
Index: linux-2.6/arch/arm/mach-integrator/integrator_cp.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-integrator/integrator_cp.c
+++ linux-2.6/arch/arm/mach-integrator/integrator_cp.c
@@ -217,7 +217,7 @@ sic_handle_irq(unsigned int irq, struct
 
 		irq += IRQ_SIC_START;
 
-		desc = irq_desc(irq);
+		desc = irq_desc + irq;
 		desc_handle_irq(irq, desc);
 	} while (status);
 }
Index: linux-2.6/arch/arm/mach-iop13xx/msi.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-iop13xx/msi.c
+++ linux-2.6/arch/arm/mach-iop13xx/msi.c
@@ -110,7 +110,7 @@ static void iop13xx_msi_handler(unsigned
 		do {
 			j = find_first_bit(&status, 32);
 			(write_imipr[i])(1 << j); /* write back to clear bit */
-			desc = irq_desc(IRQ_IOP13XX_MSI_0 + j + (32*i));
+			desc = irq_desc + IRQ_IOP13XX_MSI_0 + j + (32*i);
 			desc_handle_irq(IRQ_IOP13XX_MSI_0 + j + (32*i),	desc);
 			status = (read_imipr[i])();
 		} while (status);
Index: linux-2.6/arch/arm/mach-ixp2000/core.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ixp2000/core.c
+++ linux-2.6/arch/arm/mach-ixp2000/core.c
@@ -311,7 +311,7 @@ static void ixp2000_GPIO_irq_handler(uns
 		   
 	for (i = 0; i <= 7; i++) {
 		if (status & (1<<i)) {
-			desc = irq_desc(i + IRQ_IXP2000_GPIO0);
+			desc = irq_desc + i + IRQ_IXP2000_GPIO0;
 			desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc);
 		}
 	}
@@ -404,7 +404,7 @@ static void ixp2000_err_irq_handler(unsi
 
 	for(i = 31; i >= 0; i--) {
 		if(status & (1 << i)) {
-			desc = irq_desc(IRQ_IXP2000_DRAM0_MIN_ERR + i);
+			desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
 			desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc);
 		}
 	}
Index: linux-2.6/arch/arm/mach-ixp2000/ixdp2x00.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ixp2000/ixdp2x00.c
+++ linux-2.6/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -131,7 +131,7 @@ static void ixdp2x00_irq_handler(unsigne
 		if(ex_interrupt & (1 << i))  {
 			struct irq_desc *cpld_desc;
 			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
-			cpld_desc = irq_desc(cpld_irq);
+			cpld_desc = irq_desc + cpld_irq;
 			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
Index: linux-2.6/arch/arm/mach-ixp2000/ixdp2x01.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ixp2000/ixdp2x01.c
+++ linux-2.6/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -81,7 +81,7 @@ static void ixdp2x01_irq_handler(unsigne
 		if (ex_interrupt & (1 << i)) {
 			struct irq_desc *cpld_desc;
 			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
-			cpld_desc = irq_desc(cpld_irq);
+			cpld_desc = irq_desc + cpld_irq;
 			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
Index: linux-2.6/arch/arm/mach-ixp23xx/core.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ixp23xx/core.c
+++ linux-2.6/arch/arm/mach-ixp23xx/core.c
@@ -268,7 +268,7 @@ static void pci_handler(unsigned int irq
 		BUG();
 	}
 
-	int_desc = irq_desc(irqno);
+	int_desc = irq_desc + irqno;
 	desc_handle_irq(irqno, int_desc);
 
 	desc->chip->unmask(irq);
Index: linux-2.6/arch/arm/mach-ixp23xx/ixdp2351.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ixp23xx/ixdp2351.c
+++ linux-2.6/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -71,7 +71,7 @@ static void ixdp2351_inta_handler(unsign
 			struct irq_desc *cpld_desc;
 			int cpld_irq =
 				IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i);
-			cpld_desc = irq_desc(cpld_irq);
+			cpld_desc = irq_desc + cpld_irq;
 			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
@@ -108,7 +108,7 @@ static void ixdp2351_intb_handler(unsign
 			struct irq_desc *cpld_desc;
 			int cpld_irq =
 				IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i);
-			cpld_desc = irq_desc(cpld_irq);
+			cpld_desc = irq_desc + cpld_irq;
 			desc_handle_irq(cpld_irq, cpld_desc);
 		}
 	}
Index: linux-2.6/arch/arm/mach-lh7a40x/common.h
===================================================================
--- linux-2.6.orig/arch/arm/mach-lh7a40x/common.h
+++ linux-2.6/arch/arm/mach-lh7a40x/common.h
@@ -15,4 +15,4 @@ extern void lh7a404_init_irq (void);
 extern void lh7a40x_clcd_init (void);
 extern void lh7a40x_init_board_irq (void);
 
-#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc(irq)))
+#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq))
Index: linux-2.6/arch/arm/mach-netx/generic.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-netx/generic.c
+++ linux-2.6/arch/arm/mach-netx/generic.c
@@ -77,7 +77,7 @@ netx_hif_demux_handler(unsigned int irq_
 	stat = ((readl(NETX_DPMAS_INT_EN) &
 		readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
 
-	desc = irq_desc(NETX_IRQ_HIF_CHAINED(0));
+	desc = irq_desc + NETX_IRQ_HIF_CHAINED(0);
 
 	while (stat) {
 		if (stat & 1) {
Index: linux-2.6/arch/arm/mach-ns9xxx/board-a9m9750dev.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ns9xxx/board-a9m9750dev.c
+++ linux-2.6/arch/arm/mach-ns9xxx/board-a9m9750dev.c
@@ -90,7 +90,7 @@ static void a9m9750dev_fpga_demux_handle
 
 		stat &= ~(1 << irqno);
 
-		fpgadesc = irq_desc(FPGA_IRQ(irqno));
+		fpgadesc = irq_desc + FPGA_IRQ(irqno);
 
 		desc_handle_irq(FPGA_IRQ(irqno), fpgadesc);
 	}
Index: linux-2.6/arch/arm/mach-omap1/fpga.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-omap1/fpga.c
+++ linux-2.6/arch/arm/mach-omap1/fpga.c
@@ -99,7 +99,7 @@ void innovator_fpga_IRQ_demux(unsigned i
 	     (fpga_irq < OMAP_FPGA_IRQ_END) && stat;
 	     fpga_irq++, stat >>= 1) {
 		if (stat & 1) {
-			d = irq_desc(fpga_irq);
+			d = irq_desc + fpga_irq;
 			desc_handle_irq(fpga_irq, d);
 		}
 	}
Index: linux-2.6/arch/arm/mach-orion5x/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-orion5x/irq.c
+++ linux-2.6/arch/arm/mach-orion5x/irq.c
@@ -47,7 +47,7 @@
 static void orion5x_gpio_irq_ack(u32 irq)
 {
 	int pin = irq_to_gpio(irq);
-	if (irq_desc(irq)->status & IRQ_LEVEL)
+	if (irq_desc[irq].status & IRQ_LEVEL)
 		/*
 		 * Mask bit for level interrupt
 		 */
@@ -62,7 +62,7 @@ static void orion5x_gpio_irq_ack(u32 irq
 static void orion5x_gpio_irq_mask(u32 irq)
 {
 	int pin = irq_to_gpio(irq);
-	if (irq_desc(irq)->status & IRQ_LEVEL)
+	if (irq_desc[irq].status & IRQ_LEVEL)
 		orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
 	else
 		orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
@@ -71,7 +71,7 @@ static void orion5x_gpio_irq_mask(u32 ir
 static void orion5x_gpio_irq_unmask(u32 irq)
 {
 	int pin = irq_to_gpio(irq);
-	if (irq_desc(irq)->status & IRQ_LEVEL)
+	if (irq_desc[irq].status & IRQ_LEVEL)
 		orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
 	else
 		orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
@@ -88,7 +88,7 @@ static int orion5x_gpio_set_irq_type(u32
 		return -EINVAL;
 	}
 
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 
 	switch (type) {
 	case IRQ_TYPE_LEVEL_HIGH:
@@ -155,7 +155,7 @@ static void orion5x_gpio_irq_handler(uns
 	for (pin = offs; pin < offs + 8; pin++) {
 		if (cause & (1 << pin)) {
 			irq = gpio_to_irq(pin);
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
 				/* Swap polarity (race with GPIO line) */
 				u32 polarity = readl(GPIO_IN_POL);
@@ -186,7 +186,7 @@ static void __init orion5x_init_gpio_irq
 	for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
 		set_irq_chip(i, &orion5x_gpio_irq_chip);
 		set_irq_handler(i, handle_level_irq);
-		desc = irq_desc(i);
+		desc = irq_desc + i;
 		desc->status |= IRQ_LEVEL;
 		set_irq_flags(i, IRQF_VALID);
 	}
Index: linux-2.6/arch/arm/mach-pxa/gpio.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-pxa/gpio.c
+++ linux-2.6/arch/arm/mach-pxa/gpio.c
@@ -275,7 +275,7 @@ static void pxa_gpio_demux_handler(unsig
 			loop = 1;
 
 			n = PXA_GPIO_IRQ_BASE + bit;
-			desc_handle_irq(n, irq_desc(n));
+			desc_handle_irq(n, irq_desc + n);
 
 			bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
 		}
Index: linux-2.6/arch/arm/mach-pxa/lpd270.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-pxa/lpd270.c
+++ linux-2.6/arch/arm/mach-pxa/lpd270.c
@@ -88,7 +88,7 @@ static void lpd270_irq_handler(unsigned
 		GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
 		if (likely(pending)) {
 			irq = LPD270_IRQ(0) + __ffs(pending);
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			desc_handle_irq(irq, desc);
 
 			pending = __raw_readw(LPD270_INT_STATUS) &
Index: linux-2.6/arch/arm/mach-pxa/lubbock.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-pxa/lubbock.c
+++ linux-2.6/arch/arm/mach-pxa/lubbock.c
@@ -131,7 +131,7 @@ static void lubbock_irq_handler(unsigned
 		GEDR(0) = GPIO_bit(0);	/* clear our parent irq */
 		if (likely(pending)) {
 			irq = LUBBOCK_IRQ(0) + __ffs(pending);
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			desc_handle_irq(irq, desc);
 		}
 		pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
Index: linux-2.6/arch/arm/mach-pxa/mainstone.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-pxa/mainstone.c
+++ linux-2.6/arch/arm/mach-pxa/mainstone.c
@@ -162,7 +162,7 @@ static void mainstone_irq_handler(unsign
 		GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
 		if (likely(pending)) {
 			irq = MAINSTONE_IRQ(0) + __ffs(pending);
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			desc_handle_irq(irq, desc);
 		}
 		pending = MST_INTSETCLR & mainstone_irq_enabled;
Index: linux-2.6/arch/arm/mach-pxa/pcm990-baseboard.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-pxa/pcm990-baseboard.c
+++ linux-2.6/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -262,7 +262,7 @@ static void pcm990_irq_handler(unsigned
 					GPIO_bit(PCM990_CTRL_INT_IRQ_GPIO);
 		if (likely(pending)) {
 			irq = PCM027_IRQ(0) + __ffs(pending);
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			desc_handle_irq(irq, desc);
 		}
 		pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled;
Index: linux-2.6/arch/arm/mach-s3c2410/bast-irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/bast-irq.c
+++ linux-2.6/arch/arm/mach-s3c2410/bast-irq.c
@@ -87,7 +87,7 @@ bast_pc104_mask(unsigned int irqno)
 static void
 bast_pc104_maskack(unsigned int irqno)
 {
-	struct irq_desc *desc = irq_desc(IRQ_ISA);
+	struct irq_desc *desc = irq_desc + IRQ_ISA;
 
 	bast_pc104_mask(irqno);
 	desc->chip->ack(IRQ_ISA);
@@ -122,7 +122,7 @@ bast_irq_pc104_demux(unsigned int irq,
 	if (unlikely(stat == 0)) {
 		/* ack if we get an irq with nothing (ie, startup) */
 
-		desc = irq_desc(IRQ_ISA);
+		desc = irq_desc + IRQ_ISA;
 		desc->chip->ack(IRQ_ISA);
 	} else {
 		/* handle the IRQ */
@@ -130,7 +130,7 @@ bast_irq_pc104_demux(unsigned int irq,
 		for (i = 0; stat != 0; i++, stat >>= 1) {
 			if (stat & 1) {
 				irqno = bast_pc104_irqs[i];
-				desc = irq_desc(irqno);
+				desc = irq_desc + irqno;
 				desc_handle_irq(irqno, desc);
 			}
 		}
Index: linux-2.6/arch/arm/mach-s3c2412/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2412/irq.c
+++ linux-2.6/arch/arm/mach-s3c2412/irq.c
@@ -123,10 +123,10 @@ static void s3c2412_irq_demux_cfsdi(unsi
 	subsrc  &= ~submsk;
 
 	if (subsrc & INTBIT(IRQ_S3C2412_SDI))
-		desc_handle_irq(IRQ_S3C2412_SDI, irq_desc(IRQ_S3C2412_SDI));
+		desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI);
 
 	if (subsrc & INTBIT(IRQ_S3C2412_CF))
-		desc_handle_irq(IRQ_S3C2412_CF, irq_desc(IRQ_S3C2412_CF));
+		desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF);
 }
 
 #define INTMSK_CFSDI	(1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
Index: linux-2.6/arch/arm/mach-s3c2440/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2440/irq.c
+++ linux-2.6/arch/arm/mach-s3c2440/irq.c
@@ -58,11 +58,11 @@ static void s3c_irq_demux_wdtac97(unsign
 
 	if (subsrc != 0) {
 		if (subsrc & 1) {
-			mydesc = irq_desc(IRQ_S3C2440_WDT);
+			mydesc = irq_desc + IRQ_S3C2440_WDT;
 			desc_handle_irq(IRQ_S3C2440_WDT, mydesc);
 		}
 		if (subsrc & 2) {
-			mydesc = irq_desc(IRQ_S3C2440_AC97);
+			mydesc = irq_desc + IRQ_S3C2440_AC97;
 			desc_handle_irq(IRQ_S3C2440_AC97, mydesc);
 		}
 	}
Index: linux-2.6/arch/arm/mach-s3c2443/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2443/irq.c
+++ linux-2.6/arch/arm/mach-s3c2443/irq.c
@@ -57,13 +57,13 @@ static inline void s3c2443_irq_demux(uns
 	subsrc  &= (1 << len)-1;
 
 	end = len + irq;
-	mydesc = irq_desc(irq);
+	mydesc = irq_desc + irq;
 
 	for (; irq < end && subsrc; irq++) {
 		if (subsrc & 1)
 			desc_handle_irq(irq, mydesc);
 
-		mydesc = irq_desc(irq);
+		mydesc++;
 		subsrc >>= 1;
 	}
 }
Index: linux-2.6/arch/arm/mach-sa1100/h3600.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-sa1100/h3600.c
+++ linux-2.6/arch/arm/mach-sa1100/h3600.c
@@ -719,14 +719,14 @@ static void h3800_IRQ_demux(unsigned int
 		if (0) printk("%s KPIO 0x%08X\n", __func__, irq);
 		for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
 			if (irq & kpio_irq_mask[j])
-				handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc(H3800_KPIO_IRQ_COUNT + j));
+				handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j);
 
 		/* GPIO2 */
 		irq = H3800_ASIC2_GPIINTFLAG;
 		if (0) printk("%s GPIO 0x%08X\n", __func__, irq);
 		for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
 			if (irq & gpio_irq_mask[j])
-				handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc(H3800_GPIO_IRQ_COUNT + j));
+				handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j);
 	}
 
 	if (i >= MAX_ASIC_ISR_LOOPS)
@@ -822,17 +822,15 @@ static void __init h3800_init_irq(void)
 #if 0
 	for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) {
 		int irq = i + H3800_KPIO_IRQ_START;
-		struct irq_desc *desc = irq_desc(irq);
-		desc->valid    = 1;
-		desc->probe_ok = 1;
+		irq_desc[irq].valid    = 1;
+		irq_desc[irq].probe_ok = 1;
 		set_irq_chip(irq, &h3800_kpio_irqchip);
 	}
 
 	for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) {
 		int irq = i + H3800_GPIO_IRQ_START;
-		struct irq_desc *desc = irq_desc(irq);
-		desc->valid    = 1;
-		desc->probe_ok = 1;
+		irq_desc[irq].valid    = 1;
+		irq_desc[irq].probe_ok = 1;
 		set_irq_chip(irq, &h3800_gpio_irqchip);
 	}
 #endif
Index: linux-2.6/arch/arm/mach-sa1100/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-sa1100/irq.c
+++ linux-2.6/arch/arm/mach-sa1100/irq.c
@@ -122,7 +122,7 @@ sa1100_high_gpio_handler(unsigned int ir
 		GEDR = mask;
 
 		irq = IRQ_GPIO11;
-		desc = irq_desc(irq);
+		desc = irq_desc + irq;
 		mask >>= 11;
 		do {
 			if (mask & 1)
Index: linux-2.6/arch/arm/mach-sa1100/neponset.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-sa1100/neponset.c
+++ linux-2.6/arch/arm/mach-sa1100/neponset.c
@@ -67,12 +67,12 @@ neponset_irq_handler(unsigned int irq, s
 			desc->chip->ack(irq);
 
 			if (irr & IRR_ETHERNET) {
-				d = irq_desc(IRQ_NEPONSET_SMC9196);
+				d = irq_desc + IRQ_NEPONSET_SMC9196;
 				desc_handle_irq(IRQ_NEPONSET_SMC9196, d);
 			}
 
 			if (irr & IRR_USAR) {
-				d = irq_desc(IRQ_NEPONSET_USAR);
+				d = irq_desc + IRQ_NEPONSET_USAR;
 				desc_handle_irq(IRQ_NEPONSET_USAR, d);
 			}
 
@@ -80,7 +80,7 @@ neponset_irq_handler(unsigned int irq, s
 		}
 
 		if (irr & IRR_SA1111) {
-			d = irq_desc(IRQ_NEPONSET_SA1111);
+			d = irq_desc + IRQ_NEPONSET_SA1111;
 			desc_handle_irq(IRQ_NEPONSET_SA1111, d);
 		}
 	}
Index: linux-2.6/arch/arm/mach-versatile/core.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-versatile/core.c
+++ linux-2.6/arch/arm/mach-versatile/core.c
@@ -95,7 +95,7 @@ sic_handle_irq(unsigned int irq, struct
 
 		irq += IRQ_SIC_START;
 
-		desc = irq_desc(irq);
+		desc = irq_desc + irq;
 		desc_handle_irq(irq, desc);
 	} while (status);
 }
Index: linux-2.6/arch/arm/oprofile/op_model_mpcore.c
===================================================================
--- linux-2.6.orig/arch/arm/oprofile/op_model_mpcore.c
+++ linux-2.6/arch/arm/oprofile/op_model_mpcore.c
@@ -259,7 +259,7 @@ static void em_stop(void)
  */
 static void em_route_irq(int irq, unsigned int cpu)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	cpumask_t mask = cpumask_of_cpu(cpu);
 
 	spin_lock_irq(&desc->lock);
Index: linux-2.6/arch/arm/plat-mxc/gpio.c
===================================================================
--- linux-2.6.orig/arch/arm/plat-mxc/gpio.c
+++ linux-2.6/arch/arm/plat-mxc/gpio.c
@@ -105,14 +105,13 @@ static void mxc_gpio_irq_handler(struct
 
 	gpio_irq_no = port->virtual_irq_start;
 	for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
-		struct irq_desc *desc;
 
 		if ((irq_stat & 1) == 0)
 			continue;
 
-		desc = irq_desc(gpio_irq_no);
-		BUG_ON(!(desc->handle_irq));
-		desc->handle_irq(gpio_irq_no, desc);
+		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
+		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
+				&irq_desc[gpio_irq_no]);
 	}
 }
 
Index: linux-2.6/arch/arm/plat-omap/gpio.c
===================================================================
--- linux-2.6.orig/arch/arm/plat-omap/gpio.c
+++ linux-2.6/arch/arm/plat-omap/gpio.c
@@ -648,10 +648,8 @@ static int gpio_irq_type(unsigned irq, u
 	spin_lock_irqsave(&bank->lock, flags);
 	retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
 	if (retval == 0) {
-		struct irq_desc *desc = irq_desc(irq);
-
-		desc->status &= ~IRQ_TYPE_SENSE_MASK;
-		desc->status |= type;
+		irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+		irq_desc[irq].status |= type;
 	}
 	spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -1057,7 +1055,7 @@ static void gpio_irq_handler(unsigned in
 
 			if (!(isr & 1))
 				continue;
-			d = irq_desc(gpio_irq);
+			d = irq_desc + gpio_irq;
 
 			desc_handle_irq(gpio_irq, d);
 		}
@@ -1505,7 +1503,7 @@ static int __init _omap_gpio_init(void)
 
 		for (j = bank->virtual_irq_start;
 		     j < bank->virtual_irq_start + gpio_count; j++) {
-			lockdep_set_class(&irq_desc(j)->lock, &gpio_lock_class);
+			lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
 			set_irq_chip_data(j, bank);
 			if (bank_is_mpuio(bank))
 				set_irq_chip(j, &mpuio_irq_chip);
@@ -1820,7 +1818,7 @@ static int dbg_gpio_show(struct seq_file
 
 /* FIXME for at least omap2, show pullup/pulldown state */
 
-			irqstat = irq_desc(irq)->status;
+			irqstat = irq_desc[irq].status;
 			if (is_in && ((bank->suspend_wakeup & mask)
 					|| irqstat & IRQ_TYPE_SENSE_MASK)) {
 				char	*trigger = NULL;
Index: linux-2.6/arch/arm/plat-orion/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/plat-orion/irq.c
+++ linux-2.6/arch/arm/plat-orion/irq.c
@@ -59,7 +59,7 @@ void __init orion_irq_init(unsigned int
 		set_irq_chip(irq, &orion_irq_chip);
 		set_irq_chip_data(irq, maskaddr);
 		set_irq_handler(irq, handle_level_irq);
-		irq_desc(irq)->status |= IRQ_LEVEL;
+		irq_desc[irq].status |= IRQ_LEVEL;
 		set_irq_flags(irq, IRQF_VALID);
 	}
 }
Index: linux-2.6/arch/arm/plat-s3c24xx/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/plat-s3c24xx/irq.c
+++ linux-2.6/arch/arm/plat-s3c24xx/irq.c
@@ -482,11 +482,11 @@ static void s3c_irq_demux_adc(unsigned i
 
 	if (subsrc != 0) {
 		if (subsrc & 1) {
-			mydesc = irq_desc(IRQ_TC);
+			mydesc = irq_desc + IRQ_TC;
 			desc_handle_irq(IRQ_TC, mydesc);
 		}
 		if (subsrc & 2) {
-			mydesc = irq_desc(IRQ_ADC);
+			mydesc = irq_desc + IRQ_ADC;
 			desc_handle_irq(IRQ_ADC, mydesc);
 		}
 	}
@@ -512,17 +512,17 @@ static void s3c_irq_demux_uart(unsigned
 	subsrc &= 7;
 
 	if (subsrc != 0) {
-		desc = irq_desc(start);
+		desc = irq_desc + start;
 
 		if (subsrc & 1)
 			desc_handle_irq(start, desc);
 
-		desc = irq_desc(start + 1);
+		desc++;
 
 		if (subsrc & 2)
 			desc_handle_irq(start+1, desc);
 
-		desc = irq_desc(start + 2);
+		desc++;
 
 		if (subsrc & 4)
 			desc_handle_irq(start+2, desc);
@@ -572,7 +572,7 @@ s3c_irq_demux_extint8(unsigned int irq,
 		eintpnd &= ~(1<<irq);
 
 		irq += (IRQ_EINT4 - 4);
-		desc_handle_irq(irq, irq_desc(irq));
+		desc_handle_irq(irq, irq_desc + irq);
 	}
 
 }
@@ -595,7 +595,7 @@ s3c_irq_demux_extint4t7(unsigned int irq
 
 		irq += (IRQ_EINT4 - 4);
 
-		desc_handle_irq(irq, irq_desc(irq));
+		desc_handle_irq(irq, irq_desc + irq);
 	}
 }
 
Index: linux-2.6/arch/arm/plat-s3c24xx/s3c244x-irq.c
===================================================================
--- linux-2.6.orig/arch/arm/plat-s3c24xx/s3c244x-irq.c
+++ linux-2.6/arch/arm/plat-s3c24xx/s3c244x-irq.c
@@ -58,11 +58,11 @@ static void s3c_irq_demux_cam(unsigned i
 
 	if (subsrc != 0) {
 		if (subsrc & 1) {
-			mydesc = irq_desc(IRQ_S3C2440_CAM_C);
+			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
 			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc);
 		}
 		if (subsrc & 2) {
-			mydesc = irq_desc(IRQ_S3C2440_CAM_P);
+			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
 			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc);
 		}
 	}
Index: linux-2.6/arch/avr32/mach-at32ap/extint.c
===================================================================
--- linux-2.6.orig/arch/avr32/mach-at32ap/extint.c
+++ linux-2.6/arch/avr32/mach-at32ap/extint.c
@@ -88,6 +88,7 @@ static void eic_unmask_irq(unsigned int
 static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
 {
 	struct eic *eic = get_irq_chip_data(irq);
+	struct irq_desc *desc;
 	unsigned int i = irq - eic->first_irq;
 	u32 mode, edge, level;
 	int ret = 0;
@@ -96,6 +97,8 @@ static int eic_set_irq_type(unsigned int
 	if (flow_type == IRQ_TYPE_NONE)
 		flow_type = IRQ_TYPE_LEVEL_LOW;
 
+	desc = &irq_desc[irq];
+
 	mode = eic_readl(eic, MODE);
 	edge = eic_readl(eic, EDGE);
 	level = eic_readl(eic, LEVEL);
@@ -123,10 +126,6 @@ static int eic_set_irq_type(unsigned int
 	}
 
 	if (ret == 0) {
-		struct irq_desc *desc;
-
-		desc = irq_desc(irq);
-
 		eic_writel(eic, MODE, mode);
 		eic_writel(eic, EDGE, edge);
 		eic_writel(eic, LEVEL, level);
Index: linux-2.6/arch/avr32/mach-at32ap/intc.c
===================================================================
--- linux-2.6.orig/arch/avr32/mach-at32ap/intc.c
+++ linux-2.6/arch/avr32/mach-at32ap/intc.c
@@ -69,7 +69,7 @@ asmlinkage void do_IRQ(int level, struct
 	irq_enter();
 
 	irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	desc->handle_irq(irq, desc);
 
 	/*
Index: linux-2.6/arch/avr32/mach-at32ap/pio.c
===================================================================
--- linux-2.6.orig/arch/avr32/mach-at32ap/pio.c
+++ linux-2.6/arch/avr32/mach-at32ap/pio.c
@@ -262,7 +262,7 @@ static void gpio_irq_handler(unsigned ir
 			isr &= ~(1 << i);
 
 			i += gpio_irq;
-			d = irq_desc(i);
+			d = &irq_desc[i];
 
 			d->handle_irq(i, d);
 		} while (isr);
Index: linux-2.6/arch/blackfin/kernel/irqchip.c
===================================================================
--- linux-2.6.orig/arch/blackfin/kernel/irqchip.c
+++ linux-2.6/arch/blackfin/kernel/irqchip.c
@@ -77,10 +77,8 @@ int show_interrupts(struct seq_file *p,
 	unsigned long flags;
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 
@@ -91,7 +89,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
  unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "Err: %10lu\n", irq_err_count);
 	}
@@ -110,7 +108,7 @@ __attribute__((l1_text))
 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	unsigned short pending, other_ints;
 
 	old_regs = set_irq_regs(regs);
@@ -146,7 +144,7 @@ void __init init_IRQ(void)
 	int irq;
 
 	spin_lock_init(&irq_controller_lock);
-	for (irq = 0, desc = irq_desc(0); irq < NR_IRQS; irq++, desc = irq_desc(irq)) {
+	for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
 		*desc = bad_irq_desc;
 	}
 
Index: linux-2.6/arch/blackfin/kernel/traps.c
===================================================================
--- linux-2.6.orig/arch/blackfin/kernel/traps.c
+++ linux-2.6/arch/blackfin/kernel/traps.c
@@ -1003,10 +1003,8 @@ void show_regs(struct pt_regs *fp)
 	/* if no interrupts are going off, don't print this out */
 	if (fp->ipend & ~0x3F) {
 		for (i = 0; i < (NR_IRQS - 1); i++) {
-			struct irq_desc *desc = irq_desc(i);
-
-			spin_lock_irqsave(&desc->lock, flags);
-			action = desc->action;
+			spin_lock_irqsave(&irq_desc[i].lock, flags);
+			action = irq_desc[i].action;
 			if (!action)
 				goto unlock;
 
@@ -1018,7 +1016,7 @@ void show_regs(struct pt_regs *fp)
 			}
 			printk("\n");
 unlock:
-			spin_unlock_irqrestore(&desc->lock, flags);
+			spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 		}
 	}
 
Index: linux-2.6/arch/blackfin/mach-bf537/boards/cm_bf537.c
===================================================================
--- linux-2.6.orig/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ linux-2.6/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -575,7 +575,7 @@ static int __init cm_bf537_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
+	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
Index: linux-2.6/arch/blackfin/mach-bf537/boards/stamp.c
===================================================================
--- linux-2.6.orig/arch/blackfin/mach-bf537/boards/stamp.c
+++ linux-2.6/arch/blackfin/mach-bf537/boards/stamp.c
@@ -1026,7 +1026,7 @@ static int __init stamp_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
+	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
 #endif
 
 	return 0;
Index: linux-2.6/arch/blackfin/mach-bf561/boards/cm_bf561.c
===================================================================
--- linux-2.6.orig/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ linux-2.6/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -411,7 +411,7 @@ static int __init cm_bf561_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
+	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
Index: linux-2.6/arch/blackfin/mach-common/ints-priority.c
===================================================================
--- linux-2.6.orig/arch/blackfin/mach-common/ints-priority.c
+++ linux-2.6/arch/blackfin/mach-common/ints-priority.c
@@ -315,7 +315,7 @@ static void bfin_demux_error_irq(unsigne
 
 	if (irq) {
 		if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
-			struct irq_desc *desc = irq_desc(irq);
+			struct irq_desc *desc = irq_desc + irq;
 			desc->handle_irq(irq, desc);
 		} else {
 
@@ -561,7 +561,7 @@ static void bfin_demux_gpio_irq(unsigned
 
 			while (mask) {
 				if (mask & 1) {
-					desc = irq_desc(irq);
+					desc = irq_desc + irq;
 					desc->handle_irq(irq, desc);
 				}
 				irq++;
@@ -576,7 +576,7 @@ static void bfin_demux_gpio_irq(unsigned
 
 			do {
 				if (mask & 1) {
-					desc = irq_desc(irq);
+					desc = irq_desc + irq;
 					desc->handle_irq(irq, desc);
 				}
 				irq++;
@@ -928,7 +928,7 @@ static void bfin_demux_gpio_irq(unsigned
 	while (request) {
 		if (request & 1) {
 			irq = pint2irq_lut[pint_val] + SYS_IRQS;
-			desc = irq_desc(irq);
+			desc = irq_desc + irq;
 			desc->handle_irq(irq, desc);
 		}
 		pint_val++;
Index: linux-2.6/arch/cris/arch-v10/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/arch-v10/kernel/irq.c
+++ linux-2.6/arch/cris/arch-v10/kernel/irq.c
@@ -221,7 +221,7 @@ init_IRQ(void)
 
 	/* Initialize IRQ handler descriptors. */
 	for(i = 2; i < NR_IRQS; i++) {
-		irq_desc(i)->chip = &crisv10_irq_type;
+		irq_desc[i].chip = &crisv10_irq_type;
 		set_int_vector(i, interrupt[i]);
 	}
 
Index: linux-2.6/arch/cris/arch-v32/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/arch-v32/kernel/irq.c
+++ linux-2.6/arch/cris/arch-v32/kernel/irq.c
@@ -475,15 +475,15 @@ init_IRQ(void)
 
 	/* Point all IRQ's to bad handlers. */
 	for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
-		irq_desc(j)->chip = &crisv32_irq_type;
+		irq_desc[j].chip = &crisv32_irq_type;
 		set_exception_vector(i, interrupt[j]);
 	}
 
         /* Mark Timer and IPI IRQs as CPU local */
 	irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc(TIMER0_INTR_VECT)->status |= IRQ_PER_CPU;
+	irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU;
 	irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc(IPI_INTR_VECT)->status |= IRQ_PER_CPU;
+	irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU;
 
 	set_exception_vector(0x00, nmi_interrupt);
 	set_exception_vector(0x30, multiple_interrupt);
Index: linux-2.6/arch/cris/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/kernel/irq.c
+++ linux-2.6/arch/cris/kernel/irq.c
@@ -57,10 +57,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -70,7 +68,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -78,7 +76,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -101,7 +99,7 @@ asmlinkage void do_IRQ(int irq, struct p
 		printk("do_IRQ: stack overflow: %lX\n", sp);
 		show_stack(NULL, (unsigned long *)sp);
 	}
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
         irq_exit();
 	set_irq_regs(old_regs);
 }
Index: linux-2.6/arch/frv/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/frv/kernel/irq.c
+++ linux-2.6/arch/frv/kernel/irq.c
@@ -69,15 +69,13 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
 				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-			seq_printf(p, " %10s", desc->chip->name ? : "-");
+			seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 			seq_printf(p, "  %s", action->name);
 			for (action = action->next;
 			     action;
@@ -87,7 +85,7 @@ int show_interrupts(struct seq_file *p,
 			seq_putc(p, '\n');
 		}
 
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
 	}
Index: linux-2.6/arch/h8300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/irq.c
+++ linux-2.6/arch/h8300/kernel/irq.c
@@ -166,19 +166,17 @@ void __init init_IRQ(void)
 	setup_vector();
 
 	for (c = 0; c < NR_IRQS; c++) {
-		struct irq_desc *desc = irq_desc(c);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-		desc->chip = &h8300irq_chip;
+		irq_desc[c].status = IRQ_DISABLED;
+		irq_desc[c].action = NULL;
+		irq_desc[c].depth = 1;
+		irq_desc[c].chip = &h8300irq_chip;
 	}
 }
 
 asmlinkage void do_IRQ(int irq)
 {
 	irq_enter();
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 }
 
@@ -193,23 +191,21 @@ int show_interrupts(struct seq_file *p,
 		seq_puts(p, "           CPU0");
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		seq_printf(p, " %14s", desc->chip->name);
-		seq_printf(p, "-%-8s", desc->name);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
Index: linux-2.6/arch/ia64/hp/sim/hpsim_irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/hp/sim/hpsim_irq.c
+++ linux-2.6/arch/ia64/hp/sim/hpsim_irq.c
@@ -44,7 +44,7 @@ hpsim_irq_init (void)
 	int i;
 
 	for (i = 0; i < NR_IRQS; ++i) {
-		idesc = irq_desc(i);
+		idesc = irq_desc + i;
 		if (idesc->chip == &no_irq_type)
 			idesc->chip = &irq_type_hp_sim;
 	}
Index: linux-2.6/arch/ia64/include/asm/hw_irq.h
===================================================================
--- linux-2.6.orig/arch/ia64/include/asm/hw_irq.h
+++ linux-2.6/arch/ia64/include/asm/hw_irq.h
@@ -146,7 +146,7 @@ static inline void ia64_native_resend_ir
  * Default implementations for the irq-descriptor API:
  */
 
-extern irq_desc_t irq_descX[NR_IRQS];
+extern irq_desc_t irq_desc[NR_IRQS];
 
 #ifndef CONFIG_IA64_GENERIC
 static inline ia64_vector __ia64_irq_to_vector(int irq)
Index: linux-2.6/arch/ia64/kernel/iosapic.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/iosapic.c
+++ linux-2.6/arch/ia64/kernel/iosapic.c
@@ -398,7 +398,7 @@ iosapic_end_level_irq (unsigned int irq)
 	int do_unmask_irq = 0;
 
 	irq_complete_move(irq);
-	if (unlikely(irq_desc(irq)->status & IRQ_MOVE_PENDING)) {
+	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
 		do_unmask_irq = 1;
 		mask_irq(irq);
 	}
@@ -407,7 +407,7 @@ iosapic_end_level_irq (unsigned int irq)
 		iosapic_eoi(rte->iosapic->addr, vec);
 
 	if (unlikely(do_unmask_irq)) {
-		move_masked_irq(irq, irq_desc(irq));
+		move_masked_irq(irq, &irq_desc[irq]);
 		unmask_irq(irq);
 	}
 }
@@ -449,7 +449,7 @@ iosapic_startup_edge_irq (unsigned int i
 static void
 iosapic_ack_edge_irq (unsigned int irq)
 {
-	irq_desc_t *idesc = irq_desc(irq);
+	irq_desc_t *idesc = irq_desc + irq;
 
 	irq_complete_move(irq);
 	move_native_irq(irq, idesc);
@@ -646,7 +646,7 @@ register_intr (unsigned int gsi, int irq
 
 	irq_type = iosapic_get_irq_chip(trigger);
 
-	idesc = irq_desc(irq);
+	idesc = irq_desc + irq;
 	if (irq_type != NULL && idesc->chip != irq_type) {
 		if (idesc->chip != &no_irq_type)
 			printk(KERN_WARNING
@@ -765,7 +765,6 @@ iosapic_register_intr (unsigned int gsi,
 	struct iosapic_rte_info *rte;
 	u32 low32;
 	unsigned char dmode;
-	struct irq_desc *desc;
 
 	/*
 	 * If this GSI has already been registered (i.e., it's a
@@ -793,14 +792,12 @@ iosapic_register_intr (unsigned int gsi,
 			goto unlock_iosapic_lock;
 	}
 
-	desc = irq_desc(irq);
-
-	spin_lock(&desc->lock);
+	spin_lock(&irq_desc[irq].lock);
 	dest = get_target_cpu(gsi, irq);
 	dmode = choose_dmode();
 	err = register_intr(gsi, irq, dmode, polarity, trigger);
 	if (err < 0) {
-		spin_unlock(&desc->lock);
+		spin_unlock(&irq_desc[irq].lock);
 		irq = err;
 		goto unlock_iosapic_lock;
 	}
@@ -819,7 +816,7 @@ iosapic_register_intr (unsigned int gsi,
 	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 	       cpu_logical_id(dest), dest, irq_to_vector(irq));
 
-	spin_unlock(&desc->lock);
+	spin_unlock(&irq_desc[irq].lock);
  unlock_iosapic_lock:
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 	return irq;
@@ -860,7 +857,7 @@ iosapic_unregister_intr (unsigned int gs
 	if (--rte->refcnt > 0)
 		goto out;
 
-	idesc = irq_desc(irq);
+	idesc = irq_desc + irq;
 	rte->refcnt = NO_REF_RTE;
 
 	/* Mask the interrupt */
Index: linux-2.6/arch/ia64/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq.c
+++ linux-2.6/arch/ia64/kernel/irq.c
@@ -71,10 +71,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -85,7 +83,7 @@ int show_interrupts(struct seq_file *p,
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 		}
 #endif
-		seq_printf(p, " %14s", desc->chip->name);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -93,7 +91,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS)
 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 	return 0;
@@ -109,7 +107,7 @@ void set_irq_affinity_info (unsigned int
 	cpu_set(cpu_logical_id(hwid), mask);
 
 	if (irq < NR_IRQS) {
-		irq_desc(irq)->affinity = mask;
+		irq_desc[irq].affinity = mask;
 		irq_redir[irq] = (char) (redir & 0xff);
 	}
 }
@@ -140,7 +138,7 @@ static void migrate_irqs(void)
 	int 		irq, new_cpu;
 
 	for (irq=0; irq < NR_IRQS; irq++) {
-		desc = irq_desc(irq);
+		desc = irq_desc + irq;
 
 		if (desc->status == IRQ_DISABLED)
 			continue;
@@ -154,7 +152,7 @@ static void migrate_irqs(void)
 		if (desc->status == IRQ_PER_CPU)
 			continue;
 
-		cpus_and(mask, desc->affinity, cpu_online_map);
+		cpus_and(mask, irq_desc[irq].affinity, cpu_online_map);
 		if (any_online_cpu(mask) == NR_CPUS) {
 			/*
 			 * Save it for phase 2 processing
Index: linux-2.6/arch/ia64/kernel/irq_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq_ia64.c
+++ linux-2.6/arch/ia64/kernel/irq_ia64.c
@@ -343,7 +343,7 @@ static irqreturn_t smp_irq_move_cleanup_
 		if (irq < 0)
 			continue;
 
-		desc = irq_desc(irq);
+		desc = irq_desc + irq;
 		cfg = irq_cfg + irq;
 		spin_lock(&desc->lock);
 		if (!cfg->move_cleanup_count)
@@ -495,9 +495,9 @@ ia64_handle_irq (ia64_vector vector, str
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_irqs_this_cpu(irq_desc(vector))++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_irqs_this_cpu(irq_desc(vector))++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		else {
 			int irq = local_vector_to_irq(vector);
 
@@ -553,9 +553,9 @@ void ia64_process_pending_intr(void)
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_irqs_this_cpu(irq_desc(vector))++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_irqs_this_cpu(irq_desc(vector))++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		else {
 			struct pt_regs *old_regs = set_irq_regs(NULL);
 			int irq = local_vector_to_irq(vector);
@@ -629,7 +629,7 @@ ia64_native_register_percpu_irq (ia64_ve
 
 	irq = vec;
 	BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
-	desc = irq_desc(irq);
+	desc = irq_desc + irq;
 	desc->status |= IRQ_PER_CPU;
 	desc->chip = &irq_type_ia64_lsapic;
 	if (action)
Index: linux-2.6/arch/ia64/kernel/mca.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/mca.c
+++ linux-2.6/arch/ia64/kernel/mca.c
@@ -2101,7 +2101,7 @@ ia64_mca_late_init(void)
 			irq = local_vector_to_irq(cpe_vector);
 			if (irq > 0) {
 				cpe_poll_enabled = 0;
-				desc = irq_desc(irq);
+				desc = irq_desc + irq;
 				desc->status |= IRQ_PER_CPU;
 				setup_irq(irq, &mca_cpe_irqaction);
 				ia64_cpe_irq = irq;
Index: linux-2.6/arch/ia64/kernel/msi_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/msi_ia64.c
+++ linux-2.6/arch/ia64/kernel/msi_ia64.c
@@ -73,7 +73,7 @@ static void ia64_set_msi_irq_affinity(un
 	msg.data = data;
 
 	write_msi_msg(irq, &msg);
-	irq_desc(irq)->affinity = cpumask_of_cpu(cpu);
+	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
 }
 #endif /* CONFIG_SMP */
 
@@ -120,7 +120,7 @@ void ia64_teardown_msi_irq(unsigned int
 static void ia64_ack_msi_irq(unsigned int irq)
 {
 	irq_complete_move(irq);
-	move_native_irq(irq, irq_desc(irq));
+	move_native_irq(irq, &irq_desc[irq]);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/ia64/kernel/smpboot.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/smpboot.c
+++ linux-2.6/arch/ia64/kernel/smpboot.c
@@ -701,7 +701,7 @@ int migrate_platform_irqs(unsigned int c
 			new_cpei_cpu = any_online_cpu(cpu_online_map);
 			mask = cpumask_of_cpu(new_cpei_cpu);
 			set_cpei_target_cpu(new_cpei_cpu);
-			desc = irq_desc(ia64_cpe_irq);
+			desc = irq_desc + ia64_cpe_irq;
 			/*
 			 * Switch for now, immediately, we need to do fake intr
 			 * as other interrupts, but need to study CPEI behaviour with
Index: linux-2.6/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/irq.c
+++ linux-2.6/arch/ia64/sn/kernel/irq.c
@@ -110,7 +110,7 @@ static void sn_ack_irq(unsigned int irq)
 	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_native_irq(irq, irq_desc(irq));
+	move_native_irq(irq, &irq_desc[irq]);
 }
 
 static void sn_end_irq(unsigned int irq)
@@ -293,15 +293,14 @@ unsigned int sn_local_vector_to_irq(u8 v
 void sn_irq_init(void)
 {
 	int i;
-	irq_desc_t *desc;
+	irq_desc_t *base_desc = irq_desc;
 
 	ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
 	ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
 
 	for (i = 0; i < NR_IRQS; i++) {
-		desc = irq_desc(i);
-		if (desc->chip == &no_irq_type) {
-			desc->chip = &irq_type_sn;
+		if (base_desc[i].chip == &no_irq_type) {
+			base_desc[i].chip = &irq_type_sn;
 		}
 	}
 }
@@ -430,7 +429,7 @@ sn_call_force_intr_provider(struct sn_ir
 	pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
 
 	/* Don't force an interrupt if the irq has been disabled */
-	if (!(irq_desc(sn_irq_info->irq_irq)->status & IRQ_DISABLED) &&
+	if (!(irq_desc[sn_irq_info->irq_irq].status & IRQ_DISABLED) &&
 	    pci_provider && pci_provider->force_interrupt)
 		(*pci_provider->force_interrupt)(sn_irq_info);
 }
Index: linux-2.6/arch/ia64/sn/kernel/msi_sn.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/msi_sn.c
+++ linux-2.6/arch/ia64/sn/kernel/msi_sn.c
@@ -204,13 +204,13 @@ static void sn_set_msi_irq_affinity(unsi
 	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
 	write_msi_msg(irq, &msg);
-	irq_desc(irq)->affinity = cpu_mask;
+	irq_desc[irq].affinity = cpu_mask;
 }
 #endif /* CONFIG_SMP */
 
 static void sn_ack_msi_irq(unsigned int irq)
 {
-	move_native_irq(irq, irq_desc(irq));
+	move_native_irq(irq, &irq_desc[irq]);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/m32r/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/irq.c
+++ linux-2.6/arch/m32r/kernel/irq.c
@@ -43,10 +43,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -56,7 +54,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -64,7 +62,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
@@ -86,7 +84,7 @@ asmlinkage unsigned int do_IRQ(int irq,
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 	set_irq_regs(old_regs);
 
Index: linux-2.6/arch/m32r/platforms/m32104ut/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/m32104ut/setup.c
+++ linux-2.6/arch/m32r/platforms/m32104ut/setup.c
@@ -77,7 +77,6 @@ static struct hw_interrupt_type m32104ut
 void __init init_IRQ(void)
 {
 	static int once = 0;
-	struct irq_desc *desc;
 
 	if (once)
 		return;
@@ -86,40 +85,36 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/
-	desc = irq_desc(M32R_IRQ_INT0);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32104ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].chip = &m32104ut_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */
 	disable_m32104ut_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	desc = irq_desc(M32R_IRQ_MFT2);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32104ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &m32104ut_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	desc = irq_desc(M32R_IRQ_SIO0_R);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32104ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &m32104ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	desc = irq_desc(M32R_IRQ_SIO0_S);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32104ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &m32104ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
Index: linux-2.6/arch/m32r/platforms/m32700ut/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/m32700ut/setup.c
+++ linux-2.6/arch/m32r/platforms/m32700ut/setup.c
@@ -297,117 +297,103 @@ static struct hw_interrupt_type m32700ut
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
-	desc = irq_desc(M32700UT_LAN_IRQ_LAN);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32700UT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+	irq_desc[M32700UT_LAN_IRQ_LAN].chip = &m32700ut_lanpld_irq_type;
+	irq_desc[M32700UT_LAN_IRQ_LAN].action = 0;
+	irq_desc[M32700UT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
 	lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	desc = irq_desc(M32R_IRQ_MFT2);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32700ut_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	desc = irq_desc(M32R_IRQ_SIO0_R);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	desc = irq_desc(M32R_IRQ_SIO0_S);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	desc = irq_desc(M32R_IRQ_SIO1_R);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	desc = irq_desc(M32R_IRQ_SIO1_S);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	desc = irq_desc(M32R_IRQ_DMA1)
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_DMA1].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_DMA1].action = 0;
+	irq_desc[M32R_IRQ_DMA1].depth = 1;
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	desc = irq_desc(PLD_IRQ_SIO0_RCV);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_RCV].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	desc = irq_desc(PLD_IRQ_SIO0_SND);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_SND].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	desc = irq_desc(PLD_IRQ_CFIREQ);
-	desc->status = IRQ_DISABLED;
-	desc->hip = &m32700ut_pld_irq_type;
-	desc->ction = 0;
-	desc->epth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	desc = irq_desc(PLD_IRQ_CFC_INSERT);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	desc = irq_desc(PLD_IRQ_CFC_EJECT);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
 
@@ -427,13 +413,13 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_USB)
 	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
-	desc = irq_desc(M32700UT_LCD_IRQ_USB_INT1);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_lcdpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
-	lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
-	disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
+
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].chip = &m32700ut_lcdpld_irq_type;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+    disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
 #endif
 	/*
 	 * INT2# is used for BAT, USB, AUDIO
@@ -446,11 +432,10 @@ void __init init_IRQ(void)
 	/*
 	 * INT3# is used for AR
 	 */
-	desc = irq_desc(M32R_IRQ_INT3);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].chip = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_m32700ut_irq(M32R_IRQ_INT3);
 #endif	/* CONFIG_VIDEO_M32R_AR */
Index: linux-2.6/arch/m32r/platforms/mappi/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/mappi/setup.c
+++ linux-2.6/arch/m32r/platforms/mappi/setup.c
@@ -45,7 +45,7 @@ static void mask_and_ack_mappi(unsigned
 
 static void end_mappi_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		enable_mappi_irq(irq);
 }
 
@@ -77,8 +77,6 @@ static struct hw_interrupt_type mappi_ir
 void __init init_IRQ(void)
 {
 	static int once = 0;
-	struct irq_desc *desc;
-	unsigned irq;
 
 	if (once)
 		return;
@@ -87,86 +85,70 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_NE2000
 	/* INT0 : LAN controller (RTL8019AS) */
-	irq = M32R_IRQ_INT0;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = NULL;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
 	disable_mappi_irq(M32R_IRQ_INT0);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = NULL;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = NULL;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = NULL;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = NULL;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = NULL;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
 
 #if defined(CONFIG_M32R_PCC)
 	/* INT1 : pccard0 interrupt */
-	irq = M32R_IRQ_INT1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = NULL;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT1);
 
 	/* INT2 : pccard1 interrupt */
-	irq = M32R_IRQ_INT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = NULL;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT2].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT2].action = NULL;
+	irq_desc[M32R_IRQ_INT2].depth = 1;
 	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT2);
 #endif /* CONFIG_M32RPCC */
Index: linux-2.6/arch/m32r/platforms/mappi2/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/mappi2/setup.c
+++ linux-2.6/arch/m32r/platforms/mappi2/setup.c
@@ -83,112 +83,89 @@ static struct hw_interrupt_type mappi2_i
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-	unsigned int i;
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-
-	irq = M32R_IRQ_INT0;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi2_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	irq = M32R_IRQ_INT1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].chip = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* ICUCR40: CFC IREQ */
-	irq_desc PLD_IRQ_CFIREQ;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].chip = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert */
-	irq = PLD_IRQ_CFC_INSERT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].chip = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
 
 	/* ICUCR42: CFC Eject */
-	irq = PLD_IRQ_CFC_EJECT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi2_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].chip = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
 #endif /* CONFIG_MAPPI2_CFC */
Index: linux-2.6/arch/m32r/platforms/mappi3/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/mappi3/setup.c
+++ linux-2.6/arch/m32r/platforms/mappi3/setup.c
@@ -83,114 +83,91 @@ static struct hw_interrupt_type mappi3_i
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-	unsigned int irq;
-
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-	irq = M32R_IRQ_INT0;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi3_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	irq = M32R_IRQ_INT1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].chip = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* CFC IREQ */
-	irq = PLD_IRQ_CFIREQ;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].chip = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert & eject */
-	irq = PLD_IRQ_CFC_INSERT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].chip = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
 
 #endif /* CONFIG_M32R_CFC */
 
 	/* IDE IREQ */
-	irq = PLD_IRQ_IDEIREQ;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi3_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_IDEIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_IDEIREQ].chip = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_IDEIREQ].action = 0;
+	irq_desc[PLD_IRQ_IDEIREQ].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_IDEIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(PLD_IRQ_IDEIREQ);
 
Index: linux-2.6/arch/m32r/platforms/oaks32r/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/oaks32r/setup.c
+++ linux-2.6/arch/m32r/platforms/oaks32r/setup.c
@@ -75,8 +75,6 @@ static struct hw_interrupt_type oaks32r_
 void __init init_IRQ(void)
 {
 	static int once = 0;
-	struct irq_desc *desc;
-	unsigned int irq;
 
 	if (once)
 		return;
@@ -85,64 +83,52 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_NE2000
 	/* INT3 : LAN controller (RTL8019AS) */
-	irq = M32R_IRQ_INT3;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_oaks32r_irq(M32R_IRQ_INT3);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_oaks32r_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &oaks32r_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
Index: linux-2.6/arch/m32r/platforms/opsput/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/opsput/setup.c
+++ linux-2.6/arch/m32r/platforms/opsput/setup.c
@@ -298,130 +298,103 @@ static struct hw_interrupt_type opsput_l
 
 void __init init_IRQ(void)
 {
-	struct irq_desc *desc;
-	unsigned int irq;
-
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
-	irq = OPSPUT_LAN_IRQ_LAN;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[OPSPUT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].chip = &opsput_lanpld_irq_type;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].action = 0;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
 	lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_opsput_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	irq = M32R_IRQ_DMA1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_DMA1].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_DMA1].action = 0;
+	irq_desc[M32R_IRQ_DMA1].depth = 1;
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	irq = PLD_IRQ_SIO0_RCV;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_RCV].chip = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	irq = PLD_IRQ_SIO0_SND;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_SND].chip = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	irq = PLD_IRQ_CFIREQ;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	irq = PLD_IRQ_CFC_INSERT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].chip = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	irq = PLD_IRQ_CFC_EJECT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].chip = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
 
@@ -436,20 +409,18 @@ void __init init_IRQ(void)
 	 * INT1# is used for UART, MMC, CF Controller in FPGA.
 	 * We enable it here.
 	 */
-	icr_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
 	enable_opsput_irq(M32R_IRQ_INT1);
 
 #if defined(CONFIG_USB)
 	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
 
-	irq = OPSPUT_LCD_IRQ_USB_INT1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
-	lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
-	disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].chip = &opsput_lcdpld_irq_type;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+    disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
 #endif
 	/*
 	 * INT2# is used for BAT, USB, AUDIO
@@ -462,12 +433,10 @@ void __init init_IRQ(void)
 	/*
 	 * INT3# is used for AR
 	 */
-	irq = M32R_IRQ_INT3;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &opsput_lanpld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;	/* disable nested irq */
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].chip = &opsput_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_opsput_irq(M32R_IRQ_INT3);
 #endif /* CONFIG_VIDEO_M32R_AR */
Index: linux-2.6/arch/m32r/platforms/usrv/setup.c
===================================================================
--- linux-2.6.orig/arch/m32r/platforms/usrv/setup.c
+++ linux-2.6/arch/m32r/platforms/usrv/setup.c
@@ -149,8 +149,6 @@ void __init init_IRQ(void)
 {
 	static int once = 0;
 	int i;
-	struct irq_desc *desc;
-	unsigned int irq;
 
 	if (once)
 		return;
@@ -158,65 +156,53 @@ void __init init_IRQ(void)
 		once++;
 
 	/* MFT2 : system timer */
-	irq = M32R_IRQ_MFT2;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #if defined(CONFIG_SERIAL_M32R_SIO)
 	/* SIO0_R : uart receive data */
-	irq = M32R_IRQ_SIO0_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	irq = M32R_IRQ_SIO0_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	irq = M32R_IRQ_SIO1_R;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	irq = M32R_IRQ_SIO1_S;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &mappi_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].chip = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
 #endif  /* CONFIG_SERIAL_M32R_SIO */
 
 	/* INT#67-#71: CFC#0 IREQ on PLD */
 	for (i = 0 ; i < CONFIG_M32R_CFC_NUM ; i++ ) {
-		irq = PLD_IRQ_CF0 + i;
-		desc = irq_desc(irq);
-		desc->status = IRQ_DISABLED;
-		desc->chip = &m32700ut_pld_irq_type;
-		desc->action = 0;
-		desc->depth = 1;
+		irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
+		irq_desc[PLD_IRQ_CF0 + i].chip = &m32700ut_pld_irq_type;
+		irq_desc[PLD_IRQ_CF0 + i].action = 0;
+		irq_desc[PLD_IRQ_CF0 + i].depth = 1;	/* disable nested irq */
 		pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
 			= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 		disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
@@ -224,23 +210,19 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	/* INT#76: 16552D#0 IREQ on PLD */
-	irq = PLD_IRQ_UART0;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_UART0].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_UART0].action = 0;
+	irq_desc[PLD_IRQ_UART0].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_UART0);
 
 	/* INT#77: 16552D#1 IREQ on PLD */
-	irq = PLD_IRQ_UART1;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_UART1].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_UART1].action = 0;
+	irq_desc[PLD_IRQ_UART1].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_UART1);
@@ -248,12 +230,10 @@ void __init init_IRQ(void)
 
 #if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
 	/* INT#80: AK4524 IREQ on PLD */
-	irq = PLD_IRQ_SNDINT;
-	desc = irq_desc(irq);
-	desc->status = IRQ_DISABLED;
-	desc->chip = &m32700ut_pld_irq_type;
-	desc->action = 0;
-	desc->depth = 1;
+	irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SNDINT].chip = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SNDINT].action = 0;
+	irq_desc[PLD_IRQ_SNDINT].depth = 1;	/* disable nested irq */
 	pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
 		= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
Index: linux-2.6/arch/m68knommu/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m68knommu/kernel/irq.c
+++ linux-2.6/arch/m68knommu/kernel/irq.c
@@ -23,7 +23,7 @@ asmlinkage void do_IRQ(int irq, struct p
 	struct pt_regs *oldregs = set_irq_regs(regs);
 
 	irq_enter();
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 
 	set_irq_regs(oldregs);
@@ -48,12 +48,10 @@ void __init init_IRQ(void)
 	init_vectors();
 
 	for (irq = 0; (irq < NR_IRQS); irq++) {
-		struct irq_desc *desc = irq_desc(irq);
-
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-		desc->chip = &m_irq_chip;
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = NULL;
+		irq_desc[irq].depth = 1;
+		irq_desc[irq].chip = &m_irq_chip;
 	}
 }
 
@@ -66,13 +64,11 @@ int show_interrupts(struct seq_file *p,
 		seq_puts(p, "           CPU0\n");
 
 	if (irq < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(irq);
-
-		ap = desc->action;
+		ap = irq_desc[irq].action;
 		if (ap) {
 			seq_printf(p, "%3d: ", irq);
 			seq_printf(p, "%10u ", kstat_irqs(irq));
-			seq_printf(p, "%14s  ", desc->chip->name);
+			seq_printf(p, "%14s  ", irq_desc[irq].chip->name);
 
 			seq_printf(p, "%s", ap->name);
 			for (ap = ap->next; ap; ap = ap->next)
Index: linux-2.6/arch/mips/au1000/common/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/au1000/common/irq.c
+++ linux-2.6/arch/mips/au1000/common/irq.c
@@ -224,7 +224,7 @@ static inline void mask_and_ack_level_ir
 
 static void end_irq(unsigned int irq_nr)
 {
-	if (!(irq_desc(irq_nr)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		local_enable_irq(irq_nr);
 
 #if defined(CONFIG_MIPS_PB1000)
Index: linux-2.6/arch/mips/dec/ioasic-irq.c
===================================================================
--- linux-2.6.orig/arch/mips/dec/ioasic-irq.c
+++ linux-2.6/arch/mips/dec/ioasic-irq.c
@@ -57,7 +57,7 @@ static inline void ack_ioasic_irq(unsign
 
 static inline void end_ioasic_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		unmask_ioasic_irq(irq);
 }
 
Index: linux-2.6/arch/mips/emma2rh/markeins/irq_markeins.c
===================================================================
--- linux-2.6.orig/arch/mips/emma2rh/markeins/irq_markeins.c
+++ linux-2.6/arch/mips/emma2rh/markeins/irq_markeins.c
@@ -110,7 +110,7 @@ static void emma2rh_gpio_irq_ack(unsigne
 
 static void emma2rh_gpio_irq_end(unsigned int irq)
 {
-	if (!(irq_desc(irq)status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
 }
 
Index: linux-2.6/arch/mips/kernel/irq-gic.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/irq-gic.c
+++ linux-2.6/arch/mips/kernel/irq-gic.c
@@ -187,7 +187,7 @@ static void gic_set_affinity(unsigned in
 		set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
 
 	}
-	irq_desc(irq)->affinity = cpumask;
+	irq_desc[irq].affinity = cpumask;
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 }
Index: linux-2.6/arch/mips/kernel/irq-msc01.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/irq-msc01.c
+++ linux-2.6/arch/mips/kernel/irq-msc01.c
@@ -79,7 +79,7 @@ static void edge_mask_and_ack_msc_irq(un
  */
 static void end_msc_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		unmask_msc_irq(irq);
 }
 
Index: linux-2.6/arch/mips/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/irq.c
+++ linux-2.6/arch/mips/kernel/irq.c
@@ -99,10 +99,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
@@ -112,7 +110,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->name);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -120,7 +118,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_putc(p, '\n');
 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
Index: linux-2.6/arch/mips/kernel/smtc.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/smtc.c
+++ linux-2.6/arch/mips/kernel/smtc.c
@@ -663,7 +663,7 @@ void smtc_forward_irq(unsigned int irq)
 	 * and efficiency, we just pick the easiest one to find.
 	 */
 
-	target = first_cpu(irq_desc(irq)->affinity);
+	target = first_cpu(irq_desc[irq].affinity);
 
 	/*
 	 * We depend on the platform code to have correctly processed
Index: linux-2.6/arch/mips/mti-malta/malta-smtc.c
===================================================================
--- linux-2.6.orig/arch/mips/mti-malta/malta-smtc.c
+++ linux-2.6/arch/mips/mti-malta/malta-smtc.c
@@ -138,7 +138,7 @@ void plat_set_irq_affinity(unsigned int
 		if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))
 			cpu_clear(cpu, tmask);
 	}
-	irq_desc(irq)->affinity = tmask;
+	irq_desc[irq].affinity = tmask;
 
 	if (cpus_empty(tmask))
 		/*
Index: linux-2.6/arch/mips/sgi-ip32/ip32-irq.c
===================================================================
--- linux-2.6.orig/arch/mips/sgi-ip32/ip32-irq.c
+++ linux-2.6/arch/mips/sgi-ip32/ip32-irq.c
@@ -157,7 +157,7 @@ static void crime_level_mask_and_ack_irq
 
 static void crime_level_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq).status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		crime_enable_irq(irq);
 }
 
@@ -186,7 +186,7 @@ static void crime_edge_mask_and_ack_irq(
 
 static void crime_edge_end_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		crime_enable_irq(irq);
 }
 
@@ -227,7 +227,7 @@ static void disable_macepci_irq(unsigned
 
 static void end_macepci_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_macepci_irq(irq);
 }
 
@@ -340,7 +340,7 @@ static void mask_and_ack_maceisa_irq(uns
 
 static void end_maceisa_irq(unsigned irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
 		enable_maceisa_irq(irq);
 }
 
@@ -376,7 +376,7 @@ static void disable_mace_irq(unsigned in
 
 static void end_mace_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_mace_irq(irq);
 }
 
Index: linux-2.6/arch/mips/sibyte/bcm1480/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/bcm1480/irq.c
+++ linux-2.6/arch/mips/sibyte/bcm1480/irq.c
@@ -113,7 +113,7 @@ static void bcm1480_set_affinity(unsigne
 {
 	int i = 0, old_cpu, cpu, int_on, k;
 	u64 cur_ints;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 	unsigned int irq_dirty;
 
@@ -225,8 +225,9 @@ static void ack_bcm1480_irq(unsigned int
 
 static void end_bcm1480_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+	}
 }
 
 
Index: linux-2.6/arch/mips/sibyte/sb1250/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/sb1250/irq.c
+++ linux-2.6/arch/mips/sibyte/sb1250/irq.c
@@ -107,7 +107,7 @@ static void sb1250_set_affinity(unsigned
 {
 	int i = 0, old_cpu, cpu, int_on;
 	u64 cur_ints;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 
 	i = first_cpu(mask);
@@ -209,8 +209,9 @@ static void ack_sb1250_irq(unsigned int
 
 static void end_sb1250_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
+	}
 }
 
 
Index: linux-2.6/arch/mips/sni/a20r.c
===================================================================
--- linux-2.6.orig/arch/mips/sni/a20r.c
+++ linux-2.6/arch/mips/sni/a20r.c
@@ -181,7 +181,7 @@ static inline void mask_a20r_irq(unsigne
 
 static void end_a20r_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 		a20r_ack_hwint();
 		unmask_a20r_irq(irq);
 	}
Index: linux-2.6/arch/mips/sni/pcimt.c
===================================================================
--- linux-2.6.orig/arch/mips/sni/pcimt.c
+++ linux-2.6/arch/mips/sni/pcimt.c
@@ -209,7 +209,7 @@ void disable_pcimt_irq(unsigned int irq)
 
 static void end_pcimt_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_pcimt_irq(irq);
 }
 
Index: linux-2.6/arch/mips/sni/pcit.c
===================================================================
--- linux-2.6.orig/arch/mips/sni/pcit.c
+++ linux-2.6/arch/mips/sni/pcit.c
@@ -171,7 +171,7 @@ void disable_pcit_irq(unsigned int irq)
 
 void end_pcit_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_pcit_irq(irq);
 }
 
Index: linux-2.6/arch/mips/sni/rm200.c
===================================================================
--- linux-2.6.orig/arch/mips/sni/rm200.c
+++ linux-2.6/arch/mips/sni/rm200.c
@@ -443,7 +443,7 @@ void disable_rm200_irq(unsigned int irq)
 
 void end_rm200_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_rm200_irq(irq);
 }
 
Index: linux-2.6/arch/mips/vr41xx/common/icu.c
===================================================================
--- linux-2.6.orig/arch/mips/vr41xx/common/icu.c
+++ linux-2.6/arch/mips/vr41xx/common/icu.c
@@ -154,7 +154,7 @@ static inline uint16_t icu2_clear(uint8_
 
 void vr41xx_enable_piuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(PIU_IRQ);
+	struct irq_desc *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -169,7 +169,7 @@ EXPORT_SYMBOL(vr41xx_enable_piuint);
 
 void vr41xx_disable_piuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(PIU_IRQ);
+	struct irq_desc *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -184,7 +184,7 @@ EXPORT_SYMBOL(vr41xx_disable_piuint);
 
 void vr41xx_enable_aiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(AIU_IRQ);
+	struct irq_desc *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(vr41xx_enable_aiuint);
 
 void vr41xx_disable_aiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(AIU_IRQ);
+	struct irq_desc *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -214,7 +214,7 @@ EXPORT_SYMBOL(vr41xx_disable_aiuint);
 
 void vr41xx_enable_kiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(KIU_IRQ);
+	struct irq_desc *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -229,7 +229,7 @@ EXPORT_SYMBOL(vr41xx_enable_kiuint);
 
 void vr41xx_disable_kiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(KIU_IRQ);
+	struct irq_desc *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(vr41xx_disable_kiuint);
 
 void vr41xx_enable_macint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(ETHERNET_IRQ);
+	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -256,7 +256,7 @@ EXPORT_SYMBOL(vr41xx_enable_macint);
 
 void vr41xx_disable_macint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(ETHERNET_IRQ);
+	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -268,7 +268,7 @@ EXPORT_SYMBOL(vr41xx_disable_macint);
 
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(DSIU_IRQ);
+	struct irq_desc *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -280,7 +280,7 @@ EXPORT_SYMBOL(vr41xx_enable_dsiuint);
 
 void vr41xx_disable_dsiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(DSIU_IRQ);
+	struct irq_desc *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(vr41xx_disable_dsiuint);
 
 void vr41xx_enable_firint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(FIR_IRQ);
+	struct irq_desc *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -304,7 +304,7 @@ EXPORT_SYMBOL(vr41xx_enable_firint);
 
 void vr41xx_disable_firint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(FIR_IRQ);
+	struct irq_desc *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
@@ -316,7 +316,7 @@ EXPORT_SYMBOL(vr41xx_disable_firint);
 
 void vr41xx_enable_pciint(void)
 {
-	struct irq_desc *desc = irq_desc(PCI_IRQ);
+	struct irq_desc *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -332,7 +332,7 @@ EXPORT_SYMBOL(vr41xx_enable_pciint);
 
 void vr41xx_disable_pciint(void)
 {
-	struct irq_desc *desc = irq_desc(PCI_IRQ);
+	struct irq_desc *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -348,7 +348,7 @@ EXPORT_SYMBOL(vr41xx_disable_pciint);
 
 void vr41xx_enable_scuint(void)
 {
-	struct irq_desc *desc = irq_desc(SCU_IRQ);
+	struct irq_desc *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -364,7 +364,7 @@ EXPORT_SYMBOL(vr41xx_enable_scuint);
 
 void vr41xx_disable_scuint(void)
 {
-	struct irq_desc *desc = irq_desc(SCU_IRQ);
+	struct irq_desc *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(vr41xx_disable_scuint);
 
 void vr41xx_enable_csiint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(CSI_IRQ);
+	struct irq_desc *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -396,7 +396,7 @@ EXPORT_SYMBOL(vr41xx_enable_csiint);
 
 void vr41xx_disable_csiint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc(CSI_IRQ);
+	struct irq_desc *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -412,7 +412,7 @@ EXPORT_SYMBOL(vr41xx_disable_csiint);
 
 void vr41xx_enable_bcuint(void)
 {
-	struct irq_desc *desc = irq_desc(BCU_IRQ);
+	struct irq_desc *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -428,7 +428,7 @@ EXPORT_SYMBOL(vr41xx_enable_bcuint);
 
 void vr41xx_disable_bcuint(void)
 {
-	struct irq_desc *desc = irq_desc(BCU_IRQ);
+	struct irq_desc *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -480,7 +480,7 @@ static struct irq_chip sysint2_irq_type
 
 static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	uint16_t intassign0, intassign1;
 	unsigned int pin;
 
@@ -540,7 +540,7 @@ static inline int set_sysint1_assign(uns
 
 static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 	uint16_t intassign2, intassign3;
 	unsigned int pin;
 
Index: linux-2.6/arch/mips/vr41xx/common/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/vr41xx/common/irq.c
+++ linux-2.6/arch/mips/vr41xx/common/irq.c
@@ -72,7 +72,7 @@ static void irq_dispatch(unsigned int ir
 	cascade = irq_cascade + irq;
 	if (cascade->get_irq != NULL) {
 		unsigned int source_irq = irq;
-		desc = irq_desc(source_irq);
+		desc = irq_desc + source_irq;
 		if (desc->chip->mask_ack)
 			desc->chip->mask_ack(source_irq);
 		else {
Index: linux-2.6/arch/mn10300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/mn10300/kernel/irq.c
+++ linux-2.6/arch/mn10300/kernel/irq.c
@@ -125,7 +125,7 @@ void __init init_IRQ(void)
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++)
-		if (irq_desc(irq)->chip == &no_irq_type)
+		if (irq_desc[irq].chip == &no_irq_type)
 			set_irq_chip_and_handler(irq, &mn10300_cpu_pic,
 						 handle_edge_irq);
 	unit_init_IRQ();
@@ -183,7 +183,6 @@ int show_interrupts(struct seq_file *p,
 	int i = *(loff_t *) v, j, cpu;
 	struct irqaction *action;
 	unsigned long flags;
-	struct irq_desc *desc;
 
 	switch (i) {
 		/* display column title bar naming CPUs */
@@ -197,15 +196,13 @@ int show_interrupts(struct seq_file *p,
 
 		/* display information rows, one per active CPU */
 	case 1 ... NR_IRQS - 1:
-		desc = irq_desc(i);
-		spin_lock_irqsave(&desc->lock, flags);
-
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
 				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-			seq_printf(p, " %14s.%u", desc->chip->name,
+			seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
 				   (GxICR(i) & GxICR_LEVEL) >>
 				   GxICR_LEVEL_SHIFT);
 			seq_printf(p, "  %s", action->name);
@@ -218,7 +215,7 @@ int show_interrupts(struct seq_file *p,
 			seq_putc(p, '\n');
 		}
 
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 		break;
 
 		/* polish off with NMI and error counters */
Index: linux-2.6/arch/parisc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/irq.c
+++ linux-2.6/arch/parisc/kernel/irq.c
@@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq,
 	if (CHECK_IRQ_PER_CPU(irq)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
-		irq_desc(irq)->affinity = CPU_MASK_ALL;
+		irq_desc[irq].affinity = CPU_MASK_ALL;
 		return -EINVAL;
 	}
 
@@ -136,7 +136,7 @@ static void cpu_set_affinity_irq(unsigne
 	if (cpu_check_affinity(irq, &dest))
 		return;
 
-	irq_desc(irq)->affinity = dest;
+	irq_desc[irq].affinity = dest;
 }
 #endif
 
@@ -175,10 +175,9 @@ int show_interrupts(struct seq_file *p,
 
 	if (i < NR_IRQS) {
 		struct irqaction *action;
-		struct irq_desc *desc = irq_desc(i);
 
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
@@ -189,7 +188,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
 
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 #ifndef PARISC_IRQ_CR16_COUNTS
 		seq_printf(p, "  %s", action->name);
 
@@ -221,7 +220,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
  skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 
 	return 0;
@@ -239,16 +238,14 @@ int show_interrupts(struct seq_file *p,
 
 int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
-	struct irq_desc *desc = irq_desc(irq);
-
-	if (desc->action)
+	if (irq_desc[irq].action)
 		return -EBUSY;
-	if (desc->chip != &cpu_interrupt_type)
+	if (irq_desc[irq].chip != &cpu_interrupt_type)
 		return -EBUSY;
 
 	if (type) {
-		desc->chip = type;
-		desc->chip_data = data;
+		irq_desc[irq].chip = type;
+		irq_desc[irq].chip_data = data;
 		cpu_interrupt_type.enable(irq);
 	}
 	return 0;
@@ -298,7 +295,7 @@ int txn_alloc_irq(unsigned int bits_wide
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-	irq_desc(irq)->affinity = cpumask_of_cpu(cpu);
+	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
 #endif
 
 	return cpu_data[cpu].txn_addr;
@@ -342,7 +339,6 @@ void do_cpu_irq_mask(struct pt_regs *reg
 	int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
 	cpumask_t dest;
-	struct irq_desc *desc;
 #endif
 
 	old_regs = set_irq_regs(regs);
@@ -355,9 +351,8 @@ void do_cpu_irq_mask(struct pt_regs *reg
 	irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-	desc = irq_desc(irq);
-	dest = desc->affinity;
-	if (CHECK_IRQ_PER_CPU(desc->status) &&
+	dest = irq_desc[irq].affinity;
+	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
 	    !cpu_isset(smp_processor_id(), dest)) {
 		int cpu = first_cpu(dest);
 
@@ -398,14 +393,14 @@ static void claim_cpu_irqs(void)
 {
 	int i;
 	for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
-		irq_desc(i)->chip = &cpu_interrupt_type;
+		irq_desc[i].chip = &cpu_interrupt_type;
 	}
 
-	irq_desc(TIMER_IRQ)->action = &timer_action;
-	irq_desc(TIMER_IRQ)->status = IRQ_PER_CPU;
+	irq_desc[TIMER_IRQ].action = &timer_action;
+	irq_desc[TIMER_IRQ].status = IRQ_PER_CPU;
 #ifdef CONFIG_SMP
-	irq_desc(IPI_IRQ)->action = &ipi_action;
-	irq_desc(IPI_IRQ)->status = IRQ_PER_CPU;
+	irq_desc[IPI_IRQ].action = &ipi_action;
+	irq_desc[IPI_IRQ].status = IRQ_PER_CPU;
 #endif
 }
 
Index: linux-2.6/arch/powerpc/include/asm/irq.h
===================================================================
--- linux-2.6.orig/arch/powerpc/include/asm/irq.h
+++ linux-2.6/arch/powerpc/include/asm/irq.h
@@ -17,7 +17,7 @@
 #include <asm/atomic.h>
 
 
-#define get_irq_desc(irq) (irq_desc(irq))
+#define get_irq_desc(irq) (&irq_desc[(irq)])
 
 /* Define a way to iterate across irqs. */
 #define for_each_irq(i) \
Index: linux-2.6/arch/powerpc/kernel/crash.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/crash.c
+++ linux-2.6/arch/powerpc/kernel/crash.c
@@ -373,7 +373,7 @@ void default_machine_crash_shutdown(stru
 	hard_irq_disable();
 
 	for_each_irq(i) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = irq_desc + i;
 
 		if (desc->status & IRQ_INPROGRESS)
 			desc->chip->eoi(i);
Index: linux-2.6/arch/powerpc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/irq.c
+++ linux-2.6/arch/powerpc/kernel/irq.c
@@ -84,7 +84,7 @@ extern int tau_interrupts(int);
 #endif /* CONFIG_PPC32 */
 
 #ifdef CONFIG_PPC64
-EXPORT_SYMBOL(irq_descX);
+EXPORT_SYMBOL(irq_desc);
 
 int distribute_irqs = 1;
 
@@ -227,19 +227,18 @@ void fixup_irqs(cpumask_t map)
 
 	for_each_irq(irq) {
 		cpumask_t mask;
-		struct irq_desc *desc = irq_desc(irq);
 
-		if (desc->status & IRQ_PER_CPU)
+		if (irq_desc[irq].status & IRQ_PER_CPU)
 			continue;
 
-		cpus_and(mask, desc->affinity, map);
+		cpus_and(mask, irq_desc[irq].affinity, map);
 		if (any_online_cpu(mask) == NR_CPUS) {
 			printk("Breaking affinity for irq %i\n", irq);
 			mask = map;
 		}
-		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, mask);
-		else if (desc->action && !(warned++))
+		if (irq_desc[irq].chip->set_affinity)
+			irq_desc[irq].chip->set_affinity(irq, mask);
+		else if (irq_desc[irq].action && !(warned++))
 			printk("Cannot set affinity for irq %i\n", irq);
 	}
 
@@ -289,7 +288,7 @@ void do_IRQ(struct pt_regs *regs)
 		curtp = current_thread_info();
 		irqtp = hardirq_ctx[smp_processor_id()];
 		if (curtp != irqtp) {
-			struct irq_desc *desc = irq_desc(irq);
+			struct irq_desc *desc = irq_desc + irq;
 			void *handler = desc->handle_irq;
 			unsigned long saved_sp_limit = current->thread.ksp_limit;
 			if (handler == NULL)
Index: linux-2.6/arch/powerpc/platforms/8xx/m8xx_setup.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ linux-2.6/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -223,7 +223,7 @@ static void cpm_cascade(unsigned int irq
 	int cascade_irq;
 
 	if ((cascade_irq = cpm_get_irq()) >= 0) {
-		struct irq_desc *cdesc = irq_desc(cascade_irq);
+		struct irq_desc *cdesc = irq_desc + cascade_irq;
 
 		generic_handle_irq(cascade_irq);
 		cdesc->chip->eoi(cascade_irq);
Index: linux-2.6/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/powermac/pic.c
+++ linux-2.6/arch/powerpc/platforms/powermac/pic.c
@@ -153,7 +153,7 @@ static unsigned int pmac_startup_irq(uns
         int i = src >> 5;
 
   	spin_lock_irqsave(&pmac_pic_lock, flags);
-	if ((irq_desc(virq)->status & IRQ_LEVEL) == 0)
+	if ((irq_desc[virq].status & IRQ_LEVEL) == 0)
 		out_le32(&pmac_irq_hw[i]->ack, bit);
         __set_bit(src, ppc_cached_irq_mask);
         __pmac_set_irq_mask(src, 0);
@@ -221,7 +221,7 @@ static irqreturn_t gatwick_action(int cp
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq, irq_desc(irq));
+		__do_IRQ(irq, &irq_desc[irq]);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
Index: linux-2.6/arch/powerpc/platforms/pseries/eeh_driver.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/eeh_driver.c
+++ linux-2.6/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -70,7 +70,7 @@ static int irq_in_use(unsigned int irq)
 {
 	int rc = 0;
 	unsigned long flags;
-   struct irq_desc *desc = irq_desc(irq);
+   struct irq_desc *desc = irq_desc + irq;
 
 	spin_lock_irqsave(&desc->lock, flags);
 	if (desc->action)
Index: linux-2.6/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/xics.c
+++ linux-2.6/arch/powerpc/platforms/pseries/xics.c
@@ -205,7 +205,7 @@ static int get_irq_server(unsigned int v
 {
 	int server;
 	/* For the moment only implement delivery to all cpus or one cpu */
-	cpumask_t cpumask = irq_desc(virq)->affinity;
+	cpumask_t cpumask = irq_desc[virq].affinity;
 	cpumask_t tmp = CPU_MASK_NONE;
 
 	if (! cpu_isset(default_server, cpu_online_map))
@@ -808,7 +808,7 @@ void xics_migrate_irqs_away(void)
 		       virq, cpu);
 
 		/* Reset affinity to all cpus */
-		irq_desc(virq)->affinity = CPU_MASK_ALL;
+		irq_desc[virq].affinity = CPU_MASK_ALL;
 		desc->chip->set_affinity(virq, CPU_MASK_ALL);
 unlock:
 		spin_unlock_irqrestore(&desc->lock, flags);
Index: linux-2.6/arch/powerpc/sysdev/cpm2_pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/cpm2_pic.c
+++ linux-2.6/arch/powerpc/sysdev/cpm2_pic.c
@@ -117,10 +117,9 @@ static void cpm2_end_irq(unsigned int vi
 {
 	int	bit, word;
 	unsigned int irq_nr = virq_to_hw(virq);
-	struct irq_desc *desc = irq_desc(irq_nr);
 
-	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
-			&& desc->action) {
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+			&& irq_desc[irq_nr].action) {
 
 		bit = irq_to_siubit[irq_nr];
 		word = irq_to_siureg[irq_nr];
Index: linux-2.6/arch/powerpc/sysdev/mpic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/mpic.c
+++ linux-2.6/arch/powerpc/sysdev/mpic.c
@@ -575,7 +575,7 @@ static struct mpic *mpic_find(unsigned i
 	if (irq < NUM_ISA_INTERRUPTS)
 		return NULL;
 
-	mpic = irq_desc(irq)->chip_data;
+	mpic = irq_desc[irq].chip_data;
 
 	if (is_ipi)
 		*is_ipi = (src >= mpic->ipi_vecs[0] &&
@@ -599,14 +599,14 @@ static inline u32 mpic_physmask(u32 cpum
 /* Get the mpic structure from the IPI number */
 static inline struct mpic * mpic_from_ipi(unsigned int ipi)
 {
-	return irq_desc(ipi)->chip_data;
+	return irq_desc[ipi].chip_data;
 }
 #endif
 
 /* Get the mpic structure from the irq number */
 static inline struct mpic * mpic_from_irq(unsigned int irq)
 {
-	return irq_desc(irq)->chip_data;
+	return irq_desc[irq].chip_data;
 }
 
 /* Send an EOI */
@@ -697,7 +697,7 @@ static void mpic_unmask_ht_irq(unsigned
 
 	mpic_unmask_irq(irq);
 
-	if (irq_desc(irq)->status & IRQ_LEVEL)
+	if (irq_desc[irq].status & IRQ_LEVEL)
 		mpic_ht_end_irq(mpic, src);
 }
 
@@ -707,7 +707,7 @@ static unsigned int mpic_startup_ht_irq(
 	unsigned int src = mpic_irq_to_hw(irq);
 
 	mpic_unmask_irq(irq);
-	mpic_startup_ht_interrupt(mpic, src, irq_desc(irq)->status);
+	mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
 
 	return 0;
 }
@@ -717,7 +717,7 @@ static void mpic_shutdown_ht_irq(unsigne
 	struct mpic *mpic = mpic_from_irq(irq);
 	unsigned int src = mpic_irq_to_hw(irq);
 
-	mpic_shutdown_ht_interrupt(mpic, src, irq_desc(irq)->status);
+	mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
 	mpic_mask_irq(irq);
 }
 
@@ -734,7 +734,7 @@ static void mpic_end_ht_irq(unsigned int
 	 * latched another edge interrupt coming in anyway
 	 */
 
-	if (irq_desc(irq)->status & IRQ_LEVEL)
+	if (irq_desc[irq].status & IRQ_LEVEL)
 		mpic_ht_end_irq(mpic, src);
 	mpic_eoi(mpic);
 }
@@ -1368,7 +1368,7 @@ void mpic_setup_this_cpu(void)
  	/* let the mpic know we want intrs. default affinity is 0xffffffff
 	 * until changed via /proc. That's how it's done on x86. If we want
 	 * it differently, then we should make sure we also change the default
-	 * values of irq_desc()->affinity in irq.c.
+	 * values of irq_desc[].affinity in irq.c.
  	 */
 	if (distribute_irqs) {
 	 	for (i = 0; i < mpic->num_sources ; i++)
Index: linux-2.6/arch/powerpc/sysdev/qe_lib/qe_ic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ linux-2.6/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -189,7 +189,7 @@ static inline void qe_ic_write(volatile
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
 {
-	return irq_desc(virq)->chip_data;
+	return irq_desc[virq].chip_data;
 }
 
 #define virq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
Index: linux-2.6/arch/sh/boards/mach-cayman/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-cayman/irq.c
+++ linux-2.6/arch/sh/boards/mach-cayman/irq.c
@@ -96,7 +96,7 @@ static void ack_cayman_irq(unsigned int
 
 static void end_cayman_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_cayman_irq(irq);
 }
 
@@ -188,7 +188,7 @@ void init_cayman_irq(void)
 	}
 
 	for (i=0; i<NR_EXT_IRQS; i++) {
-		irq_desc(START_EXT_IRQS + i)->chip = &cayman_irq_type;
+		irq_desc[START_EXT_IRQS + i].chip = &cayman_irq_type;
 	}
 
 	/* Setup the SMSC interrupt */
Index: linux-2.6/arch/sh/boards/mach-dreamcast/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-dreamcast/irq.c
+++ linux-2.6/arch/sh/boards/mach-dreamcast/irq.c
@@ -86,7 +86,7 @@ static void ack_systemasic_irq(unsigned
 /* After a IRQ has been ack'd and responded to, it needs to be renabled */
 static void end_systemasic_irq(unsigned int irq)
 {
-        if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
                 enable_systemasic_irq(irq);
 }
 
Index: linux-2.6/arch/sh/boards/mach-dreamcast/setup.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-dreamcast/setup.c
+++ linux-2.6/arch/sh/boards/mach-dreamcast/setup.c
@@ -47,7 +47,7 @@ static void __init dreamcast_setup(char
 
 	/* Assign all virtual IRQs to the System ASIC int. handler */
 	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
-		irq_desc(i)->chip = &systemasic_int;
+		irq_desc[i].chip = &systemasic_int;
 
 	board_time_init = aica_time_init;
 
Index: linux-2.6/arch/sh/boards/mach-microdev/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-microdev/irq.c
+++ linux-2.6/arch/sh/boards/mach-microdev/irq.c
@@ -134,7 +134,7 @@ static void enable_microdev_irq(unsigned
 static void __init make_microdev_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	irq_desc(irq)->chip = &microdev_irq_type;
+	irq_desc[irq].chip = &microdev_irq_type;
 	disable_microdev_irq(irq);
 }
 
@@ -145,7 +145,7 @@ static void mask_and_ack_microdev(unsign
 
 static void end_microdev_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_microdev_irq(irq);
 }
 
Index: linux-2.6/arch/sh/boards/mach-se/7206/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-se/7206/irq.c
+++ linux-2.6/arch/sh/boards/mach-se/7206/irq.c
@@ -90,7 +90,7 @@ static void eoi_se7206_irq(unsigned int
 {
 	unsigned short sts0,sts1;
 
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_se7206_irq(irq);
 	/* FPGA isr clear */
 	sts0 = ctrl_inw(INTSTS0);
Index: linux-2.6/arch/sh/boards/mach-se/7343/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-se/7343/irq.c
+++ linux-2.6/arch/sh/boards/mach-se/7343/irq.c
@@ -45,7 +45,7 @@ static void se7343_irq_demux(unsigned in
 
 	while (intv) {
 		if (intv & 1) {
-			ext_desc = irq_desc(ext_irq);
+			ext_desc = irq_desc + ext_irq;
 			handle_level_irq(ext_irq, ext_desc);
 		}
 		intv >>= 1;
Index: linux-2.6/arch/sh/boards/mach-se/7722/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-se/7722/irq.c
+++ linux-2.6/arch/sh/boards/mach-se/7722/irq.c
@@ -45,7 +45,7 @@ static void se7722_irq_demux(unsigned in
 
 	while (intv) {
 		if (intv & 1) {
-			ext_desc = irq_desc(ext_irq);
+			ext_desc = irq_desc + ext_irq;
 			handle_level_irq(ext_irq, ext_desc);
 		}
 		intv >>= 1;
Index: linux-2.6/arch/sh/boards/mach-systemh/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/boards/mach-systemh/irq.c
+++ linux-2.6/arch/sh/boards/mach-systemh/irq.c
@@ -88,14 +88,14 @@ static void mask_and_ack_systemh(unsigne
 
 static void end_systemh_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_systemh_irq(irq);
 }
 
 void make_systemh_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	irq_desc(irq)->chip = &systemh_irq_type;
+	irq_desc[irq].chip = &systemh_irq_type;
 	disable_systemh_irq(irq);
 }
 
Index: linux-2.6/arch/sh/cchips/hd6446x/hd64461.c
===================================================================
--- linux-2.6.orig/arch/sh/cchips/hd6446x/hd64461.c
+++ linux-2.6/arch/sh/cchips/hd6446x/hd64461.c
@@ -48,7 +48,7 @@ static void mask_and_ack_hd64461(unsigne
 
 static void end_hd64461_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_hd64461_irq(irq);
 }
 
@@ -153,7 +153,7 @@ int __init setup_hd64461(void)
 
 	/*  IRQ 80 -> 95 belongs to HD64461  */
 	for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
-		irq_desc(i)->chip = &hd64461_irq_type;
+		irq_desc[i].chip = &hd64461_irq_type;
 	}
 
 	setup_irq(CONFIG_HD64461_IRQ, &irq0);
Index: linux-2.6/arch/sh/cchips/hd6446x/hd64465/setup.c
===================================================================
--- linux-2.6.orig/arch/sh/cchips/hd6446x/hd64465/setup.c
+++ linux-2.6/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -50,7 +50,7 @@ static void mask_and_ack_hd64465(unsigne
 
 static void end_hd64465_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_hd64465_irq(irq);
 }
 
@@ -164,7 +164,7 @@ static int __init setup_hd64465(void)
 	outw(0xffff, HD64465_REG_NIMR);	/* mask all interrupts */
 
 	for (i = 0; i < HD64465_IRQ_NUM ; i++) {
-		irq_desc(HD64465_IRQ_BASE + i)->chip = &hd64465_irq_type;
+		irq_desc[HD64465_IRQ_BASE + i].chip = &hd64465_irq_type;
 	}
 
 	setup_irq(CONFIG_HD64465_IRQ, &irq0);
Index: linux-2.6/arch/sh/kernel/cpu/irq/imask.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/irq/imask.c
+++ linux-2.6/arch/sh/kernel/cpu/irq/imask.c
@@ -96,7 +96,7 @@ static void mask_and_ack_imask(unsigned
 
 static void end_imask_irq(unsigned int irq)
 {
-	if (!(irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		enable_imask_irq(irq);
 }
 
@@ -108,6 +108,6 @@ static void shutdown_imask_irq(unsigned
 void make_imask_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	irq_desc(irq)->chip = &imask_irq_type;
+	irq_desc[irq].chip = &imask_irq_type;
 	enable_irq(irq);
 }
Index: linux-2.6/arch/sh/kernel/cpu/irq/intc-sh5.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ linux-2.6/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -156,7 +156,7 @@ static void end_intc_irq(unsigned int ir
 void make_intc_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	irq_desc(irq)->chip = &intc_irq_type;
+	irq_desc[irq].chip = &intc_irq_type;
 	disable_intc_irq(irq);
 }
 
@@ -196,7 +196,7 @@ void __init plat_irq_setup(void)
 
 	/* Set default: per-line enable/disable, priority driven ack/eoi */
 	for (i = 0; i < NR_INTC_IRQS; i++)
-		irq_desc(i)->chip = &intc_irq_type;
+		irq_desc[i].chip = &intc_irq_type;
 
 
 	/* Disable all interrupts and set all priorities to 0 to avoid trouble */
Index: linux-2.6/arch/sh/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/irq.c
+++ linux-2.6/arch/sh/kernel/irq.c
@@ -45,24 +45,22 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < sh_mv.mv_nr_irqs) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		seq_printf(p, " %14s", desc->chip->name);
-		seq_printf(p, "-%-8s", desc->name);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == sh_mv.mv_nr_irqs)
 		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
 
Index: linux-2.6/arch/sparc64/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/irq.c
+++ linux-2.6/arch/sparc64/kernel/irq.c
@@ -176,10 +176,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -189,7 +187,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %9s", desc->chip->typename);
+		seq_printf(p, " %9s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -197,7 +195,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -249,7 +247,7 @@ struct irq_handler_data {
 #ifdef CONFIG_SMP
 static int irq_choose_cpu(unsigned int virt_irq)
 {
-	cpumask_t mask = irq_desc(virt_irq)->affinity;
+	cpumask_t mask = irq_desc[virt_irq].affinity;
 	int cpuid;
 
 	if (cpus_equal(mask, CPU_MASK_ALL)) {
@@ -335,7 +333,7 @@ static void sun4u_irq_disable(unsigned i
 static void sun4u_irq_eoi(unsigned int virt_irq)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		return;
@@ -390,7 +388,7 @@ static void sun4v_irq_disable(unsigned i
 static void sun4v_irq_eoi(unsigned int virt_irq)
 {
 	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	struct irq_desc *desc = irq_desc(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
 	int err;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -466,7 +464,7 @@ static void sun4v_virq_disable(unsigned
 
 static void sun4v_virq_eoi(unsigned int virt_irq)
 {
-	struct irq_desc *desc = irq_desc(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
 	unsigned long dev_handle, dev_ino;
 	int err;
 
@@ -524,7 +522,7 @@ void irq_install_pre_handler(int virt_ir
 			     void *arg1, void *arg2)
 {
 	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc(virt_irq);
+	struct irq_desc *desc = irq_desc + virt_irq;
 
 	data->pre_handler = func;
 	data->arg1 = arg1;
@@ -650,7 +648,7 @@ unsigned int sun4v_build_virq(u32 devhan
 	 * especially wrt. locking, we do not let request_irq() enable
 	 * the interrupt.
 	 */
-	desc = irq_desc(virt_irq);
+	desc = irq_desc + virt_irq;
 	desc->status |= IRQ_NOAUTOEN;
 
 	set_irq_chip_data(virt_irq, data);
@@ -738,7 +736,7 @@ void handler_irq(int irq, struct pt_regs
 		virt_irq = bucket_get_virt_irq(bucket_pa);
 		bucket_clear_chain_pa(bucket_pa);
 
-		desc = irq_desc(virt_irq);
+		desc = irq_desc + virt_irq;
 
 		desc->handle_irq(virt_irq, desc);
 
@@ -784,16 +782,15 @@ void fixup_irqs(void)
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
 		unsigned long flags;
-		struct irq_desc *desc = irq_desc(irq);
 
-		spin_lock_irqsave(&desc->lock, flags);
-		if (desc->action &&
-		    !(desc->status & IRQ_PER_CPU)) {
-			if (desc->chip->set_affinity)
-				desc->chip->set_affinity(irq,
-					desc->affinity);
+		spin_lock_irqsave(&irq_desc[irq].lock, flags);
+		if (irq_desc[irq].action &&
+		    !(irq_desc[irq].status & IRQ_PER_CPU)) {
+			if (irq_desc[irq].chip->set_affinity)
+				irq_desc[irq].chip->set_affinity(irq,
+					irq_desc[irq].affinity);
 		}
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
 	}
 }
 #endif
@@ -1035,5 +1032,5 @@ void __init init_IRQ(void)
 			     : "i" (PSTATE_IE)
 			     : "g1");
 
-	irq_desc(0)->action = &timer_irq_action;
+	irq_desc[0].action = &timer_irq_action;
 }
Index: linux-2.6/arch/sparc64/kernel/pci_msi.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/pci_msi.c
+++ linux-2.6/arch/sparc64/kernel/pci_msi.c
@@ -33,7 +33,7 @@ static irqreturn_t sparc64_msiq_interrup
 			unsigned int virt_irq;
 
 			virt_irq = pbm->msi_irq_table[msi - pbm->msi_first];
-			desc = irq_desc(virt_irq);
+			desc = irq_desc + virt_irq;
 
 			desc->handle_irq(virt_irq, desc);
 		}
Index: linux-2.6/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/irq.c
+++ linux-2.6/arch/um/kernel/irq.c
@@ -33,10 +33,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -46,7 +44,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -54,7 +52,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS)
 		seq_putc(p, '\n');
 
@@ -334,7 +332,7 @@ unsigned int do_IRQ(int irq, struct uml_
 {
 	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
 	irq_enter();
-	__do_IRQ(irq, irq_desc(irq));
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 	set_irq_regs(old_regs);
 	return 1;
@@ -390,20 +388,17 @@ static struct hw_interrupt_type SIGVTALR
 void __init init_IRQ(void)
 {
 	int i;
-	struct irq_desc *desc;
 
-	desc  = irq_desc(TIMER_IRQ);
-	desc->status = IRQ_DISABLED;
-	desc->action = NULL;
-	desc->depth = 1;
-	desc->chip = &SIGVTALRM_irq_type;
+	irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
+	irq_desc[TIMER_IRQ].action = NULL;
+	irq_desc[TIMER_IRQ].depth = 1;
+	irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
 	enable_irq(TIMER_IRQ);
 	for (i = 1; i < NR_IRQS; i++) {
-		desc = irq_desc(i);
-		desc->status = IRQ_DISABLED;
-		desc->action = NULL;
-		desc->depth = 1;
-		desc->chip = &normal_irq_type;
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &normal_irq_type;
 		enable_irq(i);
 	}
 }
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -557,7 +557,7 @@ static void set_ioapic_affinity_irq(unsi
 	 */
 	dest = SET_APIC_LOGICAL_ID(dest);
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	spin_lock_irqsave(&ioapic_lock, flags);
 	__target_IO_APIC_irq(irq, dest, cfg->vector);
 	desc->affinity = mask;
@@ -1376,9 +1376,9 @@ static void ioapic_register_intr(int irq
 
 	/* first time to use this irq_desc */
 	if (irq < 16)
-		desc = irq_desc(irq);
+		desc = to_irq_desc(irq);
 	else
-		desc = irq_desc_with_new(irq);
+		desc = to_irq_desc_with_new(irq);
 
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 	    trigger == IOAPIC_LEVEL)
@@ -2256,7 +2256,7 @@ static void migrate_ioapic_irq(int irq,
 	cpus_and(tmp, cfg->domain, mask);
 	dest = cpu_mask_to_apicid(tmp);
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	modify_ioapic_rte = desc->status & IRQ_LEVEL;
 	if (modify_ioapic_rte) {
 		spin_lock_irqsave(&ioapic_lock, flags);
@@ -2285,7 +2285,7 @@ static void migrate_ioapic_irq(int irq,
 static int migrate_irq_remapped_level(int irq)
 {
 	int ret = -1;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	mask_IO_APIC_irq(irq);
 
@@ -2340,7 +2340,7 @@ static void ir_irq_migration(struct work
  */
 static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	if (desc->status & IRQ_LEVEL) {
 		desc->status |= IRQ_MOVE_PENDING;
@@ -2369,7 +2369,7 @@ asmlinkage void smp_irq_move_cleanup_int
 		struct irq_cfg *cfg;
 		irq = __get_cpu_var(vector_irq)[vector];
 
-		desc = irq_desc(irq);
+		desc = to_irq_desc(irq);
 		if (!desc)
 			continue;
 
@@ -2426,7 +2426,7 @@ static void ack_x2apic_edge(unsigned int
 
 static void ack_apic_edge(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	irq_complete_move(irq);
 	move_native_irq(irq, desc);
@@ -2444,7 +2444,7 @@ static void ack_apic_level(unsigned int
 	int i;
 #endif
 	int do_unmask_irq = 0;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	irq_complete_move(irq);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -2585,7 +2585,7 @@ static inline void init_IO_APIC_traps(vo
 			if (irq < 16)
 				make_8259A_irq(irq);
 			else {
-				desc = irq_desc(irq);
+				desc = to_irq_desc(irq);
 				/* Strange. Oh, well.. */
 				desc->chip = &no_irq_chip;
 			}
@@ -2629,7 +2629,7 @@ static void lapic_register_intr(int irq)
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->status &= ~IRQ_LEVEL;
 	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
 				      "edge");
@@ -3189,7 +3189,7 @@ static void set_msi_irq_affinity(unsigne
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
 	write_msi_msg(irq, &msg);
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->affinity = mask;
 }
 
@@ -3240,7 +3240,7 @@ static void ir_set_msi_irq_affinity(unsi
 		cfg->move_in_progress = 0;
 	}
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif
@@ -3315,7 +3315,7 @@ static int setup_msi_irq(struct pci_dev
 
 #ifdef CONFIG_INTR_REMAP
 	if (irq_remapped(irq)) {
-		struct irq_desc *desc = irq_desc(irq);
+		struct irq_desc *desc = to_irq_desc(irq);
 		/*
 		 * irq migration in process context
 		 */
@@ -3469,7 +3469,7 @@ static void dmar_msi_set_affinity(unsign
 
 	dmar_msi_write(irq, &msg);
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif /* CONFIG_SMP */
@@ -3541,7 +3541,7 @@ static void set_ht_irq_affinity(unsigned
 	dest = cpu_mask_to_apicid(tmp);
 
 	target_ht_irq(irq, dest, cfg->vector);
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->affinity = mask;
 }
 #endif
Index: linux-2.6/arch/x86/kernel/irq_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_32.c
+++ linux-2.6/arch/x86/kernel/irq_32.c
@@ -235,7 +235,7 @@ unsigned int do_IRQ(struct pt_regs *regs
 
 	overflow = check_stack_overflow();
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (unlikely(!desc)) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n",
 					__func__, irq, vector, smp_processor_id());
@@ -284,7 +284,7 @@ int show_interrupts(struct seq_file *p,
 	if (i == nr_irqs)
 		tail = 1;
 	else
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 #endif
 
 	if (i == 0) {
Index: linux-2.6/arch/x86/kernel/irq_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irq_64.c
+++ linux-2.6/arch/x86/kernel/irq_64.c
@@ -89,7 +89,7 @@ int show_interrupts(struct seq_file *p,
 	if (i == nr_irqs)
 		tail = 1;
 	else
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 #endif
 
 	if (i == 0) {
@@ -223,7 +223,7 @@ asmlinkage unsigned int do_IRQ(struct pt
 	stack_overflow_check(regs);
 #endif
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (likely(desc))
 		generic_handle_irq_desc(irq, desc);
 	else {
Index: linux-2.6/arch/x86/kernel/irqinit_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irqinit_32.c
+++ linux-2.6/arch/x86/kernel/irqinit_32.c
@@ -70,7 +70,7 @@ void __init init_ISA_irqs (void)
 	 */
 	for (i = 0; i < 16; i++) {
 		/* first time call this irq_desc */
-		struct irq_desc *desc = irq_desc_with_new(i);
+		struct irq_desc *desc = to_irq_desc_with_new(i);
 
 		desc->status = IRQ_DISABLED;
 		desc->action = NULL;
Index: linux-2.6/arch/x86/kernel/irqinit_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/irqinit_64.c
+++ linux-2.6/arch/x86/kernel/irqinit_64.c
@@ -144,7 +144,7 @@ static void __init init_ISA_irqs (void)
 
 	for (i = 0; i < 16; i++) {
 		/* first time call this irq_desc */
-		struct irq_desc *desc = irq_desc_with_new(i);
+		struct irq_desc *desc = to_irq_desc_with_new(i);
 
 		desc->status = IRQ_DISABLED;
 		desc->action = NULL;
Index: linux-2.6/arch/x86/kernel/visws_quirks.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/visws_quirks.c
+++ linux-2.6/arch/x86/kernel/visws_quirks.c
@@ -484,7 +484,7 @@ static void disable_cobalt_irq(unsigned
 static unsigned int startup_cobalt_irq(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	spin_lock_irqsave(&cobalt_lock, flags);
 	if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
@@ -507,7 +507,7 @@ static void ack_cobalt_irq(unsigned int
 static void end_cobalt_irq(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	spin_lock_irqsave(&cobalt_lock, flags);
 	if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
@@ -628,7 +628,7 @@ static irqreturn_t piix4_master_intr(int
 
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 
-	desc = irq_desc(realirq);
+	desc = to_irq_desc(realirq);
 
 	/*
 	 * handle this 'virtual interrupt' as a Cobalt one now.
@@ -664,7 +664,7 @@ void init_VISWS_APIC_irqs(void)
 	int i;
 
 	for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 
 		desc->status = IRQ_DISABLED;
 		desc->action = 0;
Index: linux-2.6/arch/x86/mach-voyager/voyager_smp.c
===================================================================
--- linux-2.6.orig/arch/x86/mach-voyager/voyager_smp.c
+++ linux-2.6/arch/x86/mach-voyager/voyager_smp.c
@@ -1481,7 +1481,7 @@ static void disable_local_vic_irq(unsign
  * the interrupt off to another CPU */
 static void before_handle_vic_irq(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc(irq);
+	irq_desc_t *desc = to_irq_desc(irq);
 	__u8 cpu = smp_processor_id();
 
 	_raw_spin_lock(&vic_irq_lock);
@@ -1516,7 +1516,7 @@ static void before_handle_vic_irq(unsign
 /* Finish the VIC interrupt: basically mask */
 static void after_handle_vic_irq(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc(irq);
+	irq_desc_t *desc = to_irq_desc(irq);
 
 	_raw_spin_lock(&vic_irq_lock);
 	{
Index: linux-2.6/arch/xtensa/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/xtensa/kernel/irq.c
+++ linux-2.6/arch/xtensa/kernel/irq.c
@@ -44,7 +44,7 @@ void ack_bad_irq(unsigned int irq)
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = irq_desc + irq;
 
 	if (irq >= NR_IRQS) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
@@ -90,10 +90,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -103,7 +101,7 @@ int show_interrupts(struct seq_file *p,
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", desc->chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -111,7 +109,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 skip:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
Index: linux-2.6/drivers/char/random.c
===================================================================
--- linux-2.6.orig/drivers/char/random.c
+++ linux-2.6/drivers/char/random.c
@@ -588,7 +588,7 @@ static struct timer_rand_state *get_time
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 
 	if (!desc)
 		return NULL;
@@ -600,7 +600,7 @@ static void set_timer_rand_state(unsigne
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 
 	if (!desc)
 		return;
Index: linux-2.6/drivers/gpio/gpiolib.c
===================================================================
--- linux-2.6.orig/drivers/gpio/gpiolib.c
+++ linux-2.6/drivers/gpio/gpiolib.c
@@ -1058,7 +1058,7 @@ static void gpiolib_dbg_show(struct seq_
 
 		if (!is_out) {
 			int		irq = gpio_to_irq(gpio);
-			struct irq_desc	*desc = irq_desc(irq);
+			struct irq_desc	*desc = to_irq_desc(irq);
 
 			/* This races with request_irq(), set_irq_type(),
 			 * and set_irq_wake() ... but those are "rare".
Index: linux-2.6/drivers/mfd/asic3.c
===================================================================
--- linux-2.6.orig/drivers/mfd/asic3.c
+++ linux-2.6/drivers/mfd/asic3.c
@@ -124,7 +124,7 @@ static void asic3_irq_demux(unsigned int
 					irqnr = asic->irq_base +
 						(ASIC3_GPIOS_PER_BANK * bank)
 						+ i;
-					desc = irq_desc(irqnr);
+					desc = to_irq_desc(irqnr);
 					desc->handle_irq(irqnr, desc);
 					if (asic->irq_bothedge[bank] & bit)
 						asic3_irq_flip_edge(asic, base,
@@ -137,7 +137,7 @@ static void asic3_irq_demux(unsigned int
 		for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
 			/* They start at bit 4 and go up */
 			if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
-				desc = irq_desc(asic->irq_base + i);
+				desc = to_irq_desc(asic->irq_base + i);
 				desc->handle_irq(asic->irq_base + i,
 						 desc);
 			}
Index: linux-2.6/drivers/mfd/htc-egpio.c
===================================================================
--- linux-2.6.orig/drivers/mfd/htc-egpio.c
+++ linux-2.6/drivers/mfd/htc-egpio.c
@@ -112,7 +112,7 @@ static void egpio_handler(unsigned int i
 		/* Run irq handler */
 		pr_debug("got IRQ %d\n", irqpin);
 		irq = ei->irq_start + irqpin;
-		desc = irq_desc(irq);
+		desc = to_irq_desc(irq);
 		desc->handle_irq(irq, desc);
 	}
 }
Index: linux-2.6/drivers/parisc/dino.c
===================================================================
--- linux-2.6.orig/drivers/parisc/dino.c
+++ linux-2.6/drivers/parisc/dino.c
@@ -298,7 +298,7 @@ struct pci_port_ops dino_port_ops = {
 
 static void dino_disable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	struct dino_device *dino_dev = desc->chip_data;
 	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
@@ -311,7 +311,7 @@ static void dino_disable_irq(unsigned in
 
 static void dino_enable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	struct dino_device *dino_dev = desc->chip_data;
 	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 	u32 tmp;
@@ -389,7 +389,7 @@ ilr_again:
 	do {
 		int local_irq = __ffs(mask);
 		int irq = dino_dev->global_irq[local_irq];
-		struct irq_desc *desc = irq_desc(irq);
+		struct irq_desc *desc = to_irq_desc(irq);
 		DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
 			__func__, irq, intr_dev, mask);
 		__do_IRQ(irq, desc);
Index: linux-2.6/drivers/parisc/eisa.c
===================================================================
--- linux-2.6.orig/drivers/parisc/eisa.c
+++ linux-2.6/drivers/parisc/eisa.c
@@ -234,7 +234,7 @@ static irqreturn_t eisa_irq(int wax_irq,
 	}
 	spin_unlock_irqrestore(&eisa_irq_lock, flags);
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	__do_IRQ(irq, desc);
    
 	spin_lock_irqsave(&eisa_irq_lock, flags);
@@ -348,10 +348,10 @@ static int __init eisa_probe(struct pari
 	}
 	
 	/* Reserve IRQ2 */
-	irq_desc(2)->action = &irq2_action;
+	to_irq_desc(2)->action = &irq2_action;
 	
 	for (i = 0; i < 16; i++) {
-		irq_desc(i)->chip = &eisa_interrupt_type;
+		to_irq_desc(i)->chip = &eisa_interrupt_type;
 	}
 	
 	EISA_bus = 1;
Index: linux-2.6/drivers/parisc/gsc.c
===================================================================
--- linux-2.6.orig/drivers/parisc/gsc.c
+++ linux-2.6/drivers/parisc/gsc.c
@@ -87,7 +87,7 @@ irqreturn_t gsc_asic_intr(int gsc_asic_i
 	do {
 		int local_irq = __ffs(irr);
 		unsigned int irq = gsc_asic->global_irq[local_irq];
-		struct irq_desc *desc = irq_desc(irq);
+		struct irq_desc *desc = to_irq_desc(irq);
 		__do_IRQ(irq, desc);
 		irr &= ~(1 << local_irq);
 	} while (irr);
@@ -109,7 +109,7 @@ int gsc_find_local_irq(unsigned int irq,
 
 static void gsc_asic_disable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	struct gsc_asic *irq_dev = desc->chip_data;
 	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
 	u32 imr;
@@ -125,7 +125,7 @@ static void gsc_asic_disable_irq(unsigne
 
 static void gsc_asic_enable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	struct gsc_asic *irq_dev = desc->chip_data;
 	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
 	u32 imr;
@@ -167,7 +167,7 @@ int gsc_assign_irq(struct hw_interrupt_t
 	if (irq > GSC_IRQ_MAX)
 		return NO_IRQ;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->chip = type;
 	desc->chip_data = data;
 	return irq++;
Index: linux-2.6/drivers/parisc/iosapic.c
===================================================================
--- linux-2.6.orig/drivers/parisc/iosapic.c
+++ linux-2.6/drivers/parisc/iosapic.c
@@ -619,7 +619,7 @@ iosapic_set_irt_data( struct vector_info
 
 static struct vector_info *iosapic_get_vector(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	return desc->chip_data;
 }
Index: linux-2.6/drivers/parisc/superio.c
===================================================================
--- linux-2.6.orig/drivers/parisc/superio.c
+++ linux-2.6/drivers/parisc/superio.c
@@ -140,7 +140,7 @@ superio_interrupt(int parent_irq, void *
 	}
 
 	/* Call the appropriate device's interrupt */
-	desc = irq_desc(local_irq);
+	desc = to_irq_desc(local_irq);
 	__do_IRQ(local_irq, desc);
 
 	/* set EOI - forces a new interrupt if a lower priority device
@@ -365,7 +365,7 @@ int superio_fixup_irq(struct pci_dev *pc
 #endif
 
 	for (i = 0; i < 16; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 
 		desc->chip = &superio_interrupt_type;
 	}
Index: linux-2.6/drivers/pci/intr_remapping.c
===================================================================
--- linux-2.6.orig/drivers/pci/intr_remapping.c
+++ linux-2.6/drivers/pci/intr_remapping.c
@@ -64,7 +64,7 @@ static struct irq_2_iommu *irq_2_iommu(u
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 
 	BUG_ON(!desc);
 
@@ -76,7 +76,7 @@ static struct irq_2_iommu *irq_2_iommu_w
 	struct irq_desc *desc;
 	struct irq_2_iommu *irq_iommu;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 
 	BUG_ON(!desc);
 
Index: linux-2.6/drivers/pcmcia/hd64465_ss.c
===================================================================
--- linux-2.6.orig/drivers/pcmcia/hd64465_ss.c
+++ linux-2.6/drivers/pcmcia/hd64465_ss.c
@@ -241,7 +241,7 @@ static void hs_map_irq(hs_socket_t *sp,
 	if (irq >= HS_NUM_MAPPED_IRQS)
 	    return;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
     	hs_mapped_irq[irq].sock = sp;
 	/* insert ourselves as the irq controller */
 	hs_mapped_irq[irq].old_handler = desc->chip;
@@ -261,7 +261,7 @@ static void hs_unmap_irq(hs_socket_t *sp
 	if (irq >= HS_NUM_MAPPED_IRQS)
 	    return;
 		
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	/* restore the original irq controller */
 	desc->chip = hs_mapped_irq[irq].old_handler;
 }
Index: linux-2.6/drivers/xen/events.c
===================================================================
--- linux-2.6.orig/drivers/xen/events.c
+++ linux-2.6/drivers/xen/events.c
@@ -125,7 +125,7 @@ static void bind_evtchn_to_cpu(unsigned
 
 	BUG_ON(irq == -1);
 #ifdef CONFIG_SMP
-	irq_desc(irq)->affinity = cpumask_of_cpu(cpu);
+	to_irq_desc(irq)->affinity = cpumask_of_cpu(cpu);
 #endif
 
 	__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
@@ -140,7 +140,7 @@ static void init_evtchn_cpu_bindings(voi
 	int i;
 	/* By default all event channels notify CPU#0. */
 	for (i = 0; i < nr_irqs; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 		desc->affinity = cpumask_of_cpu(0);
 	}
 #endif
@@ -640,7 +640,7 @@ static void ack_dynirq(unsigned int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
 
-	move_native_irq(irq, irq_desc(irq));
+	move_native_irq(irq, to_irq_desc(irq));
 
 	if (VALID_EVTCHN(evtchn))
 		clear_evtchn(evtchn);
Index: linux-2.6/include/asm-mips/irq.h
===================================================================
--- linux-2.6.orig/include/asm-mips/irq.h
+++ linux-2.6/include/asm-mips/irq.h
@@ -65,7 +65,7 @@ extern void smtc_forward_irq(unsigned in
  */
 #define IRQ_AFFINITY_HOOK(irq)						\
 do {									\
-    if (!cpu_isset(smp_processor_id(), irq_desc(irq)->affinity)) {	\
+    if (!cpu_isset(smp_processor_id(), irq_desc[irq].affinity)) {	\
 	smtc_forward_irq(irq);						\
 	irq_exit();							\
 	return;								\
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -194,21 +194,21 @@ struct irq_desc {
 	const char		*name;
 } ____cacheline_internodealigned_in_smp;
 
-extern struct irq_desc *irq_desc(unsigned int irq);
-extern struct irq_desc *irq_desc_with_new(unsigned int irq);
+extern struct irq_desc *to_irq_desc(unsigned int irq);
+extern struct irq_desc *to_irq_desc_with_new(unsigned int irq);
 
 #ifndef CONFIG_HAVE_SPARSE_IRQ
 
 #ifndef CONFIG_HAVE_DYN_ARRAY
 /* could be removed if we get rid of all irq_desc reference */
-extern struct irq_desc irq_descX[NR_IRQS];
+extern struct irq_desc irq_desc[NR_IRQS];
 #else
-extern struct irq_desc *irq_descX;
+extern struct irq_desc *irq_desc;
 #endif
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 #define for_each_irq_desc(irq, desc)		\
-	for (irq = 0, desc = irq_descX; irq < nr_irqs; irq++, desc = &irq_descX[irq])
+	for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc = &irq_desc[irq])
 #endif
 
 #else
@@ -280,7 +280,7 @@ static inline int irq_balancing_disabled
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	return desc->status & IRQ_NO_BALANCING_MASK;
 }
 
@@ -325,7 +325,7 @@ static inline void generic_handle_irq_de
 
 static inline void generic_handle_irq(unsigned int irq)
 {
-	generic_handle_irq_desc(irq, irq_desc(irq));
+	generic_handle_irq_desc(irq, to_irq_desc(irq));
 }
 
 /* Handling of unhandled and spurious interrupts: */
@@ -362,7 +362,7 @@ static inline void __set_irq_handler_unl
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->handle_irq = handler;
 }
 
@@ -397,7 +397,7 @@ extern void destroy_irq(unsigned int irq
 /* Test to see if a driver has successfully requested an irq */
 static inline int irq_has_action(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	return desc->action != NULL;
 }
 
@@ -412,10 +412,10 @@ extern int set_irq_chip_data(unsigned in
 extern int set_irq_type(unsigned int irq, unsigned int type);
 extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
 
-#define get_irq_chip(irq)	(irq_desc(irq)->chip)
-#define get_irq_chip_data(irq)	(irq_desc(irq)->chip_data)
-#define get_irq_data(irq)	(irq_desc(irq)->handler_data)
-#define get_irq_msi(irq)	(irq_desc(irq)->msi_desc)
+#define get_irq_chip(irq)	(to_irq_desc(irq)->chip)
+#define get_irq_chip_data(irq)	(to_irq_desc(irq)->chip_data)
+#define get_irq_data(irq)	(to_irq_desc(irq)->handler_data)
+#define get_irq_msi(irq)	(to_irq_desc(irq)->msi_desc)
 
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
Index: linux-2.6/kernel/irq/autoprobe.c
===================================================================
--- linux-2.6.orig/kernel/irq/autoprobe.c
+++ linux-2.6/kernel/irq/autoprobe.c
@@ -39,7 +39,7 @@ unsigned long probe_irq_on(void)
 	 * flush such a longstanding irq before considering it as spurious.
 	 */
 	for (i = nr_irqs-1; i > 0; i--) {
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 		if (!desc)
 			continue;
 
@@ -71,7 +71,7 @@ unsigned long probe_irq_on(void)
 	 * happened in the previous stage, it may have masked itself)
 	 */
 	for (i = nr_irqs-1; i > 0; i--) {
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 		if (!desc)
 			continue;
 
@@ -96,7 +96,7 @@ unsigned long probe_irq_on(void)
 	for (i = 0; i < nr_irqs; i++) {
 		unsigned int status;
 
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 		if (!desc)
 			continue;
 		spin_lock_irq(&desc->lock);
@@ -137,7 +137,7 @@ unsigned int probe_irq_mask(unsigned lon
 
 	mask = 0;
 	for (i = 0; i < nr_irqs; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 		unsigned int status;
 
 		if (!desc)
@@ -182,7 +182,7 @@ int probe_irq_off(unsigned long val)
 	int i, irq_found = 0, nr_irqs = 0;
 
 	for (i = 0; i < nr_irqs; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 		unsigned int status;
 
 		if (!desc)
Index: linux-2.6/kernel/irq/chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/chip.c
+++ linux-2.6/kernel/irq/chip.c
@@ -28,7 +28,7 @@ void dynamic_irq_init(unsigned int irq)
 	unsigned long flags;
 
 	/* first time to use this irq_desc */
-	desc = irq_desc_with_new(irq);
+	desc = to_irq_desc_with_new(irq);
 	if (!desc) {
 		WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
 		return;
@@ -61,7 +61,7 @@ void dynamic_irq_cleanup(unsigned int ir
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq);
 		return;
@@ -93,7 +93,7 @@ int set_irq_chip(unsigned int irq, struc
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
 		return -EINVAL;
@@ -102,7 +102,7 @@ int set_irq_chip(unsigned int irq, struc
 	if (!chip)
 		chip = &no_irq_chip;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	spin_lock_irqsave(&desc->lock, flags);
 	irq_chip_set_defaults(chip);
 	desc->chip = chip;
@@ -123,7 +123,7 @@ int set_irq_type(unsigned int irq, unsig
 	unsigned long flags;
 	int ret = -ENXIO;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
 		return -ENODEV;
@@ -150,7 +150,7 @@ int set_irq_data(unsigned int irq, void
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR
 		       "Trying to install controller data for IRQ%d\n", irq);
@@ -176,7 +176,7 @@ int set_irq_msi(unsigned int irq, struct
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR
 		       "Trying to install msi data for IRQ%d\n", irq);
@@ -203,7 +203,7 @@ int set_irq_chip_data(unsigned int irq,
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR
 		       "Trying to install chip data for IRQ%d\n", irq);
@@ -230,7 +230,7 @@ static void default_enable(unsigned int
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->chip->unmask(irq);
 	desc->status &= ~IRQ_MASKED;
 }
@@ -249,7 +249,7 @@ static unsigned int default_startup(unsi
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->chip->enable(irq);
 
 	return 0;
@@ -262,7 +262,7 @@ static void default_shutdown(unsigned in
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->chip->mask(irq);
 	desc->status |= IRQ_MASKED;
 }
@@ -554,7 +554,7 @@ __set_irq_handler(unsigned int irq, irq_
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR
 		       "Trying to install type control for IRQ%d\n", irq);
@@ -618,7 +618,7 @@ void __init set_irq_noprobe(unsigned int
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
 
@@ -635,7 +635,7 @@ void __init set_irq_probe(unsigned int i
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc) {
 		printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
 
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -153,7 +153,7 @@ early_param("nr_irq_desc", parse_nr_irq_
 
 DEFINE_DYN_ARRAY(irq_descX, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work);
 
-struct irq_desc *irq_desc(unsigned int irq)
+struct irq_desc *to_irq_desc(unsigned int irq)
 {
 	struct irq_desc *desc;
 
@@ -166,7 +166,7 @@ struct irq_desc *irq_desc(unsigned int i
 	}
 	return NULL;
 }
-struct irq_desc *irq_desc_with_new(unsigned int irq)
+struct irq_desc *to_irq_desc_with_new(unsigned int irq)
 {
 	struct irq_desc *desc, *desc_pri;
 	int i;
@@ -245,20 +245,20 @@ struct irq_desc *irq_desc_with_new(unsig
 }
 #else
 
-struct irq_desc *irq_descX;
-DEFINE_DYN_ARRAY(irq_descX, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
+struct irq_desc *irq_desc;
+DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
 
 #endif
 
 #else
 
-struct irq_desc irq_descX[NR_IRQS] __cacheline_aligned_in_smp = {
+struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS-1] = {
 		.status = IRQ_DISABLED,
 		.chip = &no_irq_chip,
 		.handle_irq = handle_bad_irq,
 		.depth = 1,
-		.lock = __SPIN_LOCK_UNLOCKED(irq_descX->lock),
+		.lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
 #ifdef CONFIG_SMP
 		.affinity = CPU_MASK_ALL
 #endif
@@ -268,16 +268,16 @@ struct irq_desc irq_descX[NR_IRQS] __cac
 #endif
 
 #ifndef CONFIG_HAVE_SPARSE_IRQ
-struct irq_desc *irq_desc(unsigned int irq)
+struct irq_desc *to_irq_desc(unsigned int irq)
 {
 	if (irq < nr_irqs)
-		return &irq_descX[irq];
+		return &irq_desc[irq];
 
 	return NULL;
 }
-struct irq_desc *irq_desc_with_new(unsigned int irq)
+struct irq_desc *to_irq_desc_with_new(unsigned int irq)
 {
-	return irq_desc(irq);
+	return to_irq_desc(irq);
 }
 #endif
 
@@ -289,7 +289,7 @@ static void ack_bad(unsigned int irq)
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	print_irq_desc(irq, desc);
 	ack_bad_irq(irq);
 }
@@ -494,7 +494,7 @@ void early_init_irq_lock_class(void)
 
 unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	return desc->kstat_irqs[cpu];
 }
 EXPORT_SYMBOL(kstat_irqs_cpu);
Index: linux-2.6/kernel/irq/manage.c
===================================================================
--- linux-2.6.orig/kernel/irq/manage.c
+++ linux-2.6/kernel/irq/manage.c
@@ -31,7 +31,7 @@ cpumask_t irq_default_affinity = CPU_MAS
  */
 void synchronize_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	unsigned int status;
 
 	if (!desc)
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(synchronize_irq);
  */
 int irq_can_set_affinity(unsigned int irq)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||
 	    !desc->chip->set_affinity)
@@ -81,7 +81,7 @@ int irq_can_set_affinity(unsigned int ir
  */
 int irq_set_affinity(unsigned int irq, cpumask_t cpumask)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	if (!desc->chip->set_affinity)
 		return -EINVAL;
@@ -116,7 +116,7 @@ int irq_select_affinity(unsigned int irq
 
 	cpus_and(mask, cpu_online_map, irq_default_affinity);
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	desc->affinity = mask;
 	desc->chip->set_affinity(irq, mask);
 
@@ -142,7 +142,7 @@ void disable_irq_nosync(unsigned int irq
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return;
 
@@ -171,7 +171,7 @@ void disable_irq(unsigned int irq)
 {
 	struct irq_desc *desc;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return;
 
@@ -215,7 +215,7 @@ void enable_irq(unsigned int irq)
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return;
 
@@ -227,7 +227,7 @@ EXPORT_SYMBOL(enable_irq);
 
 int set_irq_wake_real(unsigned int irq, unsigned int on)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	int ret = -ENXIO;
 
 	if (desc->chip->set_wake)
@@ -250,7 +250,7 @@ int set_irq_wake_real(unsigned int irq,
  */
 int set_irq_wake(unsigned int irq, unsigned int on)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	unsigned long flags;
 	int ret = 0;
 
@@ -293,7 +293,7 @@ int can_request_irq(unsigned int irq, un
 	struct irq_desc *desc;
 	struct irqaction *action;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return 0;
 
@@ -357,7 +357,7 @@ int setup_irq(unsigned int irq, struct i
 	int shared = 0;
 	int ret;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return -EINVAL;
 
@@ -513,7 +513,7 @@ void free_irq(unsigned int irq, void *de
 
 	WARN_ON(in_interrupt());
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return;
 
@@ -629,7 +629,7 @@ int request_irq(unsigned int irq, irq_ha
 	if ((irqflags & IRQF_SHARED) && !dev_id)
 		return -EINVAL;
 
-	desc = irq_desc(irq);
+	desc = to_irq_desc(irq);
 	if (!desc)
 		return -EINVAL;
 
Index: linux-2.6/kernel/irq/migration.c
===================================================================
--- linux-2.6.orig/kernel/irq/migration.c
+++ linux-2.6/kernel/irq/migration.c
@@ -3,7 +3,7 @@
 
 void set_pending_irq(unsigned int irq, cpumask_t mask)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&desc->lock, flags);
Index: linux-2.6/kernel/irq/proc.c
===================================================================
--- linux-2.6.orig/kernel/irq/proc.c
+++ linux-2.6/kernel/irq/proc.c
@@ -19,7 +19,7 @@ static struct proc_dir_entry *root_irq_d
 
 static int irq_affinity_proc_show(struct seq_file *m, void *v)
 {
-	struct irq_desc *desc = irq_desc((long)m->private);
+	struct irq_desc *desc = to_irq_desc((long)m->private);
 	cpumask_t *mask = &desc->affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -43,7 +43,7 @@ static ssize_t irq_affinity_proc_write(s
 	cpumask_t new_value;
 	int err;
 
-	if (!irq_desc(irq)->chip->set_affinity || no_irq_affinity ||
+	if (!to_irq_desc(irq)->chip->set_affinity || no_irq_affinity ||
 	    irq_balancing_disabled(irq))
 		return -EIO;
 
@@ -132,7 +132,7 @@ static const struct file_operations defa
 static int irq_spurious_read(char *page, char **start, off_t off,
 				  int count, int *eof, void *data)
 {
-	struct irq_desc *desc = irq_desc((long) data);
+	struct irq_desc *desc = to_irq_desc((long) data);
 	return sprintf(page, "count %u\n"
 			     "unhandled %u\n"
 			     "last_unhandled %u ms\n",
@@ -145,7 +145,7 @@ static int irq_spurious_read(char *page,
 
 static int name_unique(unsigned int irq, struct irqaction *new_action)
 {
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 	struct irqaction *action;
 	unsigned long flags;
 	int ret = 1;
@@ -165,7 +165,7 @@ static int name_unique(unsigned int irq,
 void register_handler_proc(unsigned int irq, struct irqaction *action)
 {
 	char name [MAX_NAMELEN];
-	struct irq_desc *desc = irq_desc(irq);
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	if (!desc->dir || action->dir || !action->name ||
 					!name_unique(irq, action))
@@ -214,7 +214,7 @@ void register_irq_proc(unsigned int irq,
 void unregister_handler_proc(unsigned int irq, struct irqaction *action)
 {
 	if (action->dir) {
-		struct irq_desc *desc = irq_desc(irq);
+		struct irq_desc *desc = to_irq_desc(irq);
 		remove_proc_entry(action->dir->name, desc->dir);
 	}
 }
Index: linux-2.6/kernel/irq/resend.c
===================================================================
--- linux-2.6.orig/kernel/irq/resend.c
+++ linux-2.6/kernel/irq/resend.c
@@ -36,7 +36,7 @@ static void resend_irqs(unsigned long ar
 	while (!bitmap_empty(irqs_resend, nr_irqs)) {
 		irq = find_first_bit(irqs_resend, nr_irqs);
 		clear_bit(irq, irqs_resend);
-		desc = irq_desc(irq);
+		desc = to_irq_desc(irq);
 		local_irq_disable();
 		desc->handle_irq(irq, desc);
 		local_irq_enable();
Index: linux-2.6/kernel/irq/spurious.c
===================================================================
--- linux-2.6.orig/kernel/irq/spurious.c
+++ linux-2.6/kernel/irq/spurious.c
@@ -97,7 +97,7 @@ static int misrouted_irq(int irq)
 		if (i == irq)	/* Already tried */
 			continue;
 
-		desc = irq_desc(i);
+		desc = to_irq_desc(i);
 		if (try_one_irq(i, desc))
 			ok = 1;
 	}
@@ -109,7 +109,7 @@ static void poll_spurious_irqs(unsigned
 {
 	int i;
 	for (i = 1; i < nr_irqs; i++) {
-		struct irq_desc *desc = irq_desc(i);
+		struct irq_desc *desc = to_irq_desc(i);
 		unsigned int status;
 
 		/* Racy but it doesn't matter */
Index: linux-2.6/arch/mips/sgi-ip22/ip22-int.c
===================================================================
--- linux-2.6.orig/arch/mips/sgi-ip22/ip22-int.c
+++ linux-2.6/arch/mips/sgi-ip22/ip22-int.c
@@ -164,7 +164,7 @@ static void indy_buserror_irq(void)
 	int irq = SGI_BUSERR_IRQ;
 
 	irq_enter();
-	kstat_irqs_this_cpu(irq_desc(irq))++;
+	kstat_irqs_this_cpu(&irq_desc[irq])++;
 	ip22_be_interrupt(irq);
 	irq_exit();
 }
Index: linux-2.6/arch/mips/sgi-ip22/ip22-time.c
===================================================================
--- linux-2.6.orig/arch/mips/sgi-ip22/ip22-time.c
+++ linux-2.6/arch/mips/sgi-ip22/ip22-time.c
@@ -186,7 +186,7 @@ void indy_8254timer_irq(void)
 	char c;
 
 	irq_enter();
-	kstat_irqs_this_cpu(irq_desc(irq))++;
+	kstat_irqs_this_cpu(&irq_desc[irq])++;
 	printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
 	ArcRead(0, &c, 1, &cnt);
 	ArcEnterInteractiveMode();
Index: linux-2.6/arch/mips/sibyte/bcm1480/smp.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/bcm1480/smp.c
+++ linux-2.6/arch/mips/sibyte/bcm1480/smp.c
@@ -180,7 +180,7 @@ void bcm1480_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	irq_desc(K_BCM1480_INT_MBOX_0_0).kstat_irqs[cpu]++;
+	irq_desc[K_BCM1480_INT_MBOX_0_0].kstat_irqs[cpu]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
 
Index: linux-2.6/arch/mips/sibyte/sb1250/smp.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/sb1250/smp.c
+++ linux-2.6/arch/mips/sibyte/sb1250/smp.c
@@ -168,7 +168,7 @@ void sb1250_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	irq_desc(K_INT_MBOX_0)->kstat_irqs[cpu]++;
+	irq_desc[K_INT_MBOX_0].kstat_irqs[cpu]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 
Index: linux-2.6/arch/sparc64/kernel/time.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/time.c
+++ linux-2.6/arch/sparc64/kernel/time.c
@@ -943,7 +943,7 @@ void timer_interrupt(int irq, struct pt_
 
 	irq_enter();
 
-	irq_desc(0)->kstat_irqs[0]++;
+	irq_desc[0].kstat_irqs[0]++;
 
 	if (unlikely(!evt->event_handler)) {
 		printk(KERN_WARNING

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] x86: apic - unify lapic_resume - fix
  2008-08-18  4:12 ` [PATCH] x86: apic - unify lapic_resume - fix Yinghai Lu
  2008-08-18  4:12   ` [PATCH 1/2] x86: make HAVE_SPARSE_IRQ support selectable Yinghai Lu
@ 2008-08-18  7:25   ` Ingo Molnar
  1 sibling, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2008-08-18  7:25 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

applied to tip/x86/apic, thanks.

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] irq: rename irq_desc() to to_irq_desc()
  2008-08-18  4:12     ` [PATCH 2/2] irq: rename irq_desc() to to_irq_desc() Yinghai Lu
@ 2008-08-18  7:37       ` Ingo Molnar
  2008-08-18 18:14         ` Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-18  7:37 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> So could revert back to use irq_desc[] for other arch except x86
> 
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

great!

could we get rid of the remaining non-x86 arch changes too, please? 

- __do_IRQ(): why is the change needed? Architectures that want to use 
  sparse IRQs should first properly convert to genirq (i.e. should get 
  rid of their __do_IRQ() use).

- kstat_cpu / kstat_irqs_cpu: seems unnecessary now?

- create_irq prototype return value change: cannot we limit the irq 
  space to 0..INT_MAX, and leave the prototype alone?

- create_irq(int) argument change: how about introducing a new 
  create_irq_nr(int) variant, while the create_irq(void) function would 
  just call create_irq_nr(0) ?

	Ingo

diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index c626a82..b5348ae 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -89,7 +89,7 @@ show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(irq));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
 #endif
 		seq_printf(p, " %14s", irq_desc[irq].chip->typename);
 		seq_printf(p, "  %c%s",
@@ -156,6 +156,6 @@ handle_irq(int irq)
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 }
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index e16aeb6..2c0852c 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned long vector,
 		smp_percpu_timer_interrupt(regs);
 		cpu = smp_processor_id();
 		if (cpu != boot_cpuid) {
-		        kstat_cpu(cpu).irqs[RTC_IRQ]++;
+			irq_desc[RTC_IRQ].kstat_irqs[cpu]++;
 		} else {
 			handle_irq(RTC_IRQ);
 		}
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index f88efb1..26a1185 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -69,22 +69,24 @@ int show_interrupts(struct seq_file *p, void *v)
 	}
 
 	if (i < NR_IRQS) {
-		spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_desc(i);
+
+		spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto unlock;
 
 		seq_printf(p, "%3d: ", i);
 		for_each_present_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
-		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+		seq_printf(p, " %10s", desc->chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (i == NR_IRQS) {
 #ifdef CONFIG_ARCH_ACORN
 		show_fiq_list(p, v);
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index 63ef112..ace5bad 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -125,7 +125,7 @@ void __init iop13xx_msi_init(void)
 /*
  * Dynamic irq allocate and deallocation
  */
-int create_irq(void)
+unsigned int create_irq(unsigned not_used)
 {
 	int irq, pos;
 
@@ -173,7 +173,7 @@ static struct irq_chip iop13xx_msi_chip = {
 
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
-	int id, irq = create_irq();
+	int id, irq = create_irq(0);
 	struct msi_msg msg;
 
 	if (irq < 0)
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
index 38260d5..5118872 100644
--- a/arch/arm/mach-ns9xxx/irq.c
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -63,7 +63,6 @@ static struct irq_chip ns9xxx_chip = {
 #else
 static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int cpu = smp_processor_id();
 	struct irqaction *action;
 	irqreturn_t action_ret;
 
@@ -72,7 +71,7 @@ static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
 	BUG_ON(desc->status & IRQ_INPROGRESS);
 
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_irqs_this_cpu(desc)++;
 
 	action = desc->action;
 	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
diff --git a/arch/avr32/kernel/irq.c b/arch/avr32/kernel/irq.c
index a8e767d..b75a957 100644
--- a/arch/avr32/kernel/irq.c
+++ b/arch/avr32/kernel/irq.c
@@ -51,22 +51,24 @@ int show_interrupts(struct seq_file *p, void *v)
 	}
 
 	if (i < NR_IRQS) {
-		spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_desc(i);
+
+		spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto unlock;
 
 		seq_printf(p, "%3d: ", i);
 		for_each_online_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
-		seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+		seq_printf(p, " %8s", desc->chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 
 		seq_putc(p, '\n');
 	unlock:
-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		spin_unlock_irqrestore(&desc->lock, flags);
 	}
 
 	return 0;
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 0b26ae2..08ad8ad 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -989,7 +989,7 @@ static int __init stamp_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 689b69c..66e770d 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -1024,7 +1024,7 @@ static int __init stamp_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index ed2b0b8..49b02ec 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -418,7 +418,7 @@ static int __init cm_bf533_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 079389c..0b9c3a6 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -426,7 +426,7 @@ static int __init ezkit_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 13ae495..1bb6d18 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -627,7 +627,7 @@ static int __init stamp_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 01b63e2..6f57f09 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -733,7 +733,7 @@ static int __init stamp_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index bc6fede..8cdc0ad 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -540,7 +540,7 @@ static int __init ezkit_init(void)
 	spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_desc(PATA_INT)->status |= IRQ_NOAUTOEN;
 #endif
 	return 0;
 }
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index 2dfac8c..a2746de 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -66,7 +66,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
@@ -99,7 +99,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 		printk("do_IRQ: stack overflow: %lX\n", sp);
 		show_stack(NULL, (unsigned long *)sp);
 	}
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
         irq_exit();
 	set_irq_regs(old_regs);
 }
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 73abae7..af3e824 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
 			seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 			seq_printf(p, "  %s", action->name);
 			for (action = action->next;
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
index ef4f004..221c4cd 100644
--- a/arch/h8300/kernel/irq.c
+++ b/arch/h8300/kernel/irq.c
@@ -176,7 +176,7 @@ void __init init_IRQ(void)
 asmlinkage void do_IRQ(int irq)
 {
 	irq_enter();
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 }
 
@@ -196,7 +196,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 5c4674a..031e02e 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -407,7 +407,7 @@ iosapic_end_level_irq (unsigned int irq)
 		iosapic_eoi(rte->iosapic->addr, vec);
 
 	if (unlikely(do_unmask_irq)) {
-		move_masked_irq(irq);
+		move_masked_irq(irq, &irq_desc[irq]);
 		unmask_irq(irq);
 	}
 }
@@ -452,7 +452,7 @@ iosapic_ack_edge_irq (unsigned int irq)
 	irq_desc_t *idesc = irq_desc + irq;
 
 	irq_complete_move(irq);
-	move_native_irq(irq);
+	move_native_irq(irq, idesc);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
@@ -532,7 +532,7 @@ iosapic_reassign_vector (int irq)
 	int new_irq;
 
 	if (iosapic_intr_info[irq].count) {
-		new_irq = create_irq();
+		new_irq = create_irq(0);
 		if (new_irq < 0)
 			panic("%s: out of interrupt vectors!\n", __func__);
 		printk(KERN_INFO "Reassigning vector %d to %d\n",
@@ -783,7 +783,7 @@ iosapic_register_intr (unsigned int gsi,
 			goto unlock_iosapic_lock;
 		}
 	} else
-		irq = create_irq();
+		irq = create_irq(0);
 
 	/* If vector is running out, we try to find a sharable vector */
 	if (irq < 0) {
@@ -922,7 +922,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 		delivery = IOSAPIC_PMI;
 		break;
 	      case ACPI_INTERRUPT_INIT:
-		irq = create_irq();
+		irq = create_irq(0);
 		if (irq < 0)
 			panic("%s: out of interrupt vectors!\n", __func__);
 		vector = irq_to_vector(irq);
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 7fd18f5..4140d51 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -80,7 +80,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j) {
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 		}
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 28d3d48..96f7571 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -403,7 +403,7 @@ void destroy_and_reserve_irq(unsigned int irq)
 /*
  * Dynamic irq allocate and deallocation for MSI
  */
-int create_irq(void)
+unsigned int create_irq(unsigned int not_used)
 {
 	unsigned long flags;
 	int irq, vector, cpu;
@@ -495,9 +495,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_this_cpu.irqs[vector]++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_this_cpu.irqs[vector]++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		else {
 			int irq = local_vector_to_irq(vector);
 
@@ -553,9 +553,9 @@ void ia64_process_pending_intr(void)
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_this_cpu.irqs[vector]++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_this_cpu.irqs[vector]++;
+			kstat_irqs_this_cpu(&irq_desc[vector])++;
 		else {
 			struct pt_regs *old_regs = set_irq_regs(NULL);
 			int irq = local_vector_to_irq(vector);
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 60c6ef6..924293f 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -84,7 +84,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 	int	irq, vector;
 	cpumask_t mask;
 
-	irq = create_irq();
+	irq = create_irq(0);
 	if (irq < 0)
 		return irq;
 
@@ -120,7 +120,7 @@ void ia64_teardown_msi_irq(unsigned int irq)
 static void ia64_ack_msi_irq(unsigned int irq)
 {
 	irq_complete_move(irq);
-	move_native_irq(irq);
+	move_native_irq(irq, &irq_desc[irq]);
 	ia64_eoi();
 }
 
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 96c31b4..50ddcf3 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -110,7 +110,7 @@ static void sn_ack_irq(unsigned int irq)
 	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_native_irq(irq);
+	move_native_irq(irq, &irq_desc[irq]);
 }
 
 static void sn_end_irq(unsigned int irq)
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 83f190f..a6739fa 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -83,7 +83,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
 	if (provider == NULL || provider->dma_map_consistent == NULL)
 		return -EINVAL;
 
-	irq = create_irq();
+	irq = create_irq(0);
 	if (irq < 0)
 		return irq;
 
@@ -210,7 +210,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
 
 static void sn_ack_msi_irq(unsigned int irq)
 {
-	move_native_irq(irq);
+	move_native_irq(irq, &irq_desc[irq]);
 	ia64_eoi();
 }
 
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
index d0c5b0b..09d16ea 100644
--- a/arch/m32r/kernel/irq.c
+++ b/arch/m32r/kernel/irq.c
@@ -52,7 +52,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
@@ -84,7 +84,7 @@ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 	set_irq_regs(old_regs);
 
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index ded7dd2..d8aebfc 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -46,6 +46,8 @@
 #include <asm/q40ints.h>
 #endif
 
+int nr_irqs = NR_IRQS;
+
 extern u32 auto_irqhandler_fixup[];
 extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68knommu/kernel/irq.c
index bba1bb4..7d565f1 100644
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68knommu/kernel/irq.c
@@ -23,7 +23,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 	struct pt_regs *oldregs = set_irq_regs(regs);
 
 	irq_enter();
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 
 	set_irq_regs(oldregs);
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 4b4007b..7b845ba 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -108,7 +108,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index f6d9bf4..6794c76 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -164,7 +164,7 @@ static void indy_buserror_irq(void)
 	int irq = SGI_BUSERR_IRQ;
 
 	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
+	kstat_irqs_this_cpu(&irq_desc[irq])++;
 	ip22_be_interrupt(irq);
 	irq_exit();
 }
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index 10e5054..f744b2e 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -186,7 +186,7 @@ void indy_8254timer_irq(void)
 	char c;
 
 	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
+	kstat_irqs_this_cpu(&irq_desc[irq])++;
 	printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
 	ArcRead(0, &c, 1, &cnt);
 	ArcEnterInteractiveMode();
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index bd9eeb4..6f09896 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -180,7 +180,7 @@ void bcm1480_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
+	irq_desc[K_BCM1480_INT_MBOX_0_0].kstat_irqs[cpu]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
 
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index 0734b93..dd0e55e 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -168,7 +168,7 @@ void sb1250_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	kstat_this_cpu.irqs[K_INT_MBOX_0]++;
+	irq_desc[K_INT_MBOX_0].kstat_irqs[cpu]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index 761c434..87ecf9d 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -197,12 +197,11 @@ int show_interrupts(struct seq_file *p, void *v)
 		/* display information rows, one per active CPU */
 	case 1 ... NR_IRQS - 1:
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
-
 		action = irq_desc[i].action;
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
 			seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
 				   (GxICR(i) & GxICR_LEVEL) >>
 				   GxICR_LEVEL_SHIFT);
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 23ef950..8672b27 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -183,7 +183,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #else
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
@@ -363,7 +363,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
 		goto set_out;
 	}
 #endif
-	__do_IRQ(irq);
+	__do_IRQ(irq, irq_desc);
 
  out:
 	irq_exit();
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index d972dec..93870a6 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -190,7 +190,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #else
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif /* CONFIG_SMP */
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 2d5bb22..490b619 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -254,7 +254,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
 		goto out_eoi;
 	}
 
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_irqs_this_cpu(desc)++;
 
 	/* Mark the IRQ currently in progress.*/
 	desc->status |= IRQ_INPROGRESS;
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 6d149ae..e3d44d5 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -221,7 +221,7 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id)
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq);
+		__do_IRQ(irq, &irq_desc[irq]);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index e7c5bfb..14eb549 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -17,6 +17,8 @@
 #include <linux/proc_fs.h>
 #include <linux/profile.h>
 
+int nr_irqs = NR_IRQS;
+
 /*
  * show_interrupts is needed by /proc/interrupts.
  */
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 64b7690..0080a16 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p, void *v)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 93e1d1c..059598b 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -55,6 +55,9 @@
 #define SMP_NOP2
 #define SMP_NOP3
 #endif /* SMP */
+
+int nr_irqs = NR_IRQS;
+
 unsigned long __raw_local_irq_save(void)
 {
 	unsigned long retval;
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 9b6689d..fc0fd8b 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -185,7 +185,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
 		seq_printf(p, " %9s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index cc16fdc..db211ac 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -16,6 +16,7 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/timex.h>
@@ -942,7 +943,7 @@ void timer_interrupt(int irq, struct pt_regs *regs)
 
 	irq_enter();
 
-	kstat_this_cpu.irqs[0]++;
+	irq_desc[0].kstat_irqs[0]++;
 
 	if (unlikely(!evt->event_handler)) {
 		printk(KERN_WARNING
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 3d7aad0..a2ff0ea 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -42,7 +42,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
@@ -332,7 +332,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
 	irq_enter();
-	__do_IRQ(irq);
+	__do_IRQ(irq, &irq_desc[irq]);
 	irq_exit();
 	set_irq_regs(old_regs);
 	return 1;

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] irq: rename irq_desc() to to_irq_desc()
  2008-08-18  7:37       ` Ingo Molnar
@ 2008-08-18 18:14         ` Yinghai Lu
  0 siblings, 0 replies; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18 18:14 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 947 bytes --]

On Mon, Aug 18, 2008 at 12:37 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>> So could revert back to use irq_desc[] for other arch except x86
>>
>> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>
> great!
>
> could we get rid of the remaining non-x86 arch changes too, please?
>
> - __do_IRQ(): why is the change needed? Architectures that want to use
>  sparse IRQs should first properly convert to genirq (i.e. should get
>  rid of their __do_IRQ() use).

please check attacch patch

>
> - kstat_cpu / kstat_irqs_cpu: seems unnecessary now?

that is needed

>
> - create_irq prototype return value change: cannot we limit the irq
>  space to 0..INT_MAX, and leave the prototype alone?
>
> - create_irq(int) argument change: how about introducing a new
>  create_irq_nr(int) variant, while the create_irq(void) function would
>  just call create_irq_nr(0) ?

will send out another patch later

YH

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: irq_desc__to_irq_desc_fix1.patch --]
[-- Type: text/x-patch; name=irq_desc__to_irq_desc_fix1.patch, Size: 13889 bytes --]

[PATCH] irq: rename irq_desc() to to_irq_desc() - fix

some left overs.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/alpha/kernel/irq.c               |    2 +-
 arch/arm/kernel/irq.c                 |   10 ++++------
 arch/avr32/kernel/irq.c               |    8 +++-----
 arch/cris/kernel/irq.c                |    2 +-
 arch/h8300/kernel/irq.c               |    2 +-
 arch/ia64/kernel/iosapic.c            |    2 +-
 arch/ia64/kernel/msi_ia64.c           |    2 +-
 arch/ia64/sn/kernel/irq.c             |    2 +-
 arch/ia64/sn/kernel/msi_sn.c          |    2 +-
 arch/m32r/kernel/irq.c                |    2 +-
 arch/m68knommu/kernel/irq.c           |    2 +-
 arch/parisc/kernel/irq.c              |    2 +-
 arch/powerpc/platforms/powermac/pic.c |    2 +-
 arch/um/kernel/irq.c                  |    2 +-
 arch/x86/kernel/io_apic.c             |    4 +---
 drivers/parisc/dino.c                 |    3 +--
 drivers/parisc/eisa.c                 |    4 +---
 drivers/parisc/gsc.c                  |    3 +--
 drivers/parisc/superio.c              |    4 +---
 drivers/xen/events.c                  |    2 +-
 include/linux/irq.h                   |   10 +++++-----
 kernel/irq/handle.c                   |    3 ++-
 kernel/irq/migration.c                |    4 +++-
 23 files changed, 35 insertions(+), 44 deletions(-)

Index: linux-2.6/arch/alpha/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq.c
+++ linux-2.6/arch/alpha/kernel/irq.c
@@ -156,6 +156,6 @@ handle_irq(int irq)
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 }
Index: linux-2.6/arch/arm/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/irq.c
+++ linux-2.6/arch/arm/kernel/irq.c
@@ -69,24 +69,22 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 
 		seq_printf(p, "%3d: ", i);
 		for_each_present_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %10s", desc->chip->name ? : "-");
+		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 #ifdef CONFIG_ARCH_ACORN
 		show_fiq_list(p, v);
Index: linux-2.6/arch/avr32/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/avr32/kernel/irq.c
+++ linux-2.6/arch/avr32/kernel/irq.c
@@ -51,10 +51,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 
@@ -68,7 +66,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 	unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 
 	return 0;
Index: linux-2.6/arch/cris/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/kernel/irq.c
+++ linux-2.6/arch/cris/kernel/irq.c
@@ -99,7 +99,7 @@ asmlinkage void do_IRQ(int irq, struct p
 		printk("do_IRQ: stack overflow: %lX\n", sp);
 		show_stack(NULL, (unsigned long *)sp);
 	}
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
         irq_exit();
 	set_irq_regs(old_regs);
 }
Index: linux-2.6/arch/h8300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/irq.c
+++ linux-2.6/arch/h8300/kernel/irq.c
@@ -176,7 +176,7 @@ void __init init_IRQ(void)
 asmlinkage void do_IRQ(int irq)
 {
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 }
 
Index: linux-2.6/arch/ia64/kernel/iosapic.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/iosapic.c
+++ linux-2.6/arch/ia64/kernel/iosapic.c
@@ -452,7 +452,7 @@ iosapic_ack_edge_irq (unsigned int irq)
 	irq_desc_t *idesc = irq_desc + irq;
 
 	irq_complete_move(irq);
-	move_native_irq(irq, idesc);
+	move_native_irq(irq);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
Index: linux-2.6/arch/ia64/kernel/msi_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/msi_ia64.c
+++ linux-2.6/arch/ia64/kernel/msi_ia64.c
@@ -120,7 +120,7 @@ void ia64_teardown_msi_irq(unsigned int
 static void ia64_ack_msi_irq(unsigned int irq)
 {
 	irq_complete_move(irq);
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/irq.c
+++ linux-2.6/arch/ia64/sn/kernel/irq.c
@@ -110,7 +110,7 @@ static void sn_ack_irq(unsigned int irq)
 	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 }
 
 static void sn_end_irq(unsigned int irq)
Index: linux-2.6/arch/ia64/sn/kernel/msi_sn.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/msi_sn.c
+++ linux-2.6/arch/ia64/sn/kernel/msi_sn.c
@@ -210,7 +210,7 @@ static void sn_set_msi_irq_affinity(unsi
 
 static void sn_ack_msi_irq(unsigned int irq)
 {
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/m32r/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/irq.c
+++ linux-2.6/arch/m32r/kernel/irq.c
@@ -84,7 +84,7 @@ asmlinkage unsigned int do_IRQ(int irq,
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 
Index: linux-2.6/arch/m68knommu/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m68knommu/kernel/irq.c
+++ linux-2.6/arch/m68knommu/kernel/irq.c
@@ -23,7 +23,7 @@ asmlinkage void do_IRQ(int irq, struct p
 	struct pt_regs *oldregs = set_irq_regs(regs);
 
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 
 	set_irq_regs(oldregs);
Index: linux-2.6/arch/parisc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/irq.c
+++ linux-2.6/arch/parisc/kernel/irq.c
@@ -363,7 +363,7 @@ void do_cpu_irq_mask(struct pt_regs *reg
 		goto set_out;
 	}
 #endif
-	__do_IRQ(irq, irq_desc);
+	__do_IRQ(irq);
 
  out:
 	irq_exit();
Index: linux-2.6/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/powermac/pic.c
+++ linux-2.6/arch/powerpc/platforms/powermac/pic.c
@@ -221,7 +221,7 @@ static irqreturn_t gatwick_action(int cp
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq, &irq_desc[irq]);
+		__do_IRQ(irq);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
Index: linux-2.6/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/irq.c
+++ linux-2.6/arch/um/kernel/irq.c
@@ -332,7 +332,7 @@ unsigned int do_IRQ(int irq, struct uml_
 {
 	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 	return 1;
Index: linux-2.6/drivers/parisc/dino.c
===================================================================
--- linux-2.6.orig/drivers/parisc/dino.c
+++ linux-2.6/drivers/parisc/dino.c
@@ -389,10 +389,9 @@ ilr_again:
 	do {
 		int local_irq = __ffs(mask);
 		int irq = dino_dev->global_irq[local_irq];
-		struct irq_desc *desc = to_irq_desc(irq);
 		DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
 			__func__, irq, intr_dev, mask);
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 		mask &= ~(1 << local_irq);
 	} while (mask);
 
Index: linux-2.6/drivers/parisc/eisa.c
===================================================================
--- linux-2.6.orig/drivers/parisc/eisa.c
+++ linux-2.6/drivers/parisc/eisa.c
@@ -202,7 +202,6 @@ static irqreturn_t eisa_irq(int wax_irq,
 {
 	int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
 	unsigned long flags;
-	struct irq_desc *desc;
         
 	spin_lock_irqsave(&eisa_irq_lock, flags);
 	/* read IRR command */
@@ -234,8 +233,7 @@ static irqreturn_t eisa_irq(int wax_irq,
 	}
 	spin_unlock_irqrestore(&eisa_irq_lock, flags);
 
-	desc = to_irq_desc(irq);
-	__do_IRQ(irq, desc);
+	__do_IRQ(irq);
    
 	spin_lock_irqsave(&eisa_irq_lock, flags);
 	/* unmask */
Index: linux-2.6/drivers/parisc/gsc.c
===================================================================
--- linux-2.6.orig/drivers/parisc/gsc.c
+++ linux-2.6/drivers/parisc/gsc.c
@@ -87,8 +87,7 @@ irqreturn_t gsc_asic_intr(int gsc_asic_i
 	do {
 		int local_irq = __ffs(irr);
 		unsigned int irq = gsc_asic->global_irq[local_irq];
-		struct irq_desc *desc = to_irq_desc(irq);
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 		irr &= ~(1 << local_irq);
 	} while (irr);
 
Index: linux-2.6/drivers/parisc/superio.c
===================================================================
--- linux-2.6.orig/drivers/parisc/superio.c
+++ linux-2.6/drivers/parisc/superio.c
@@ -99,7 +99,6 @@ superio_interrupt(int parent_irq, void *
 {
 	u8 results;
 	u8 local_irq;
-	struct irq_desc *desc;
 
 	/* Poll the 8259 to see if there's an interrupt. */
 	outb (OCW3_POLL,IC_PIC1+0);
@@ -140,8 +139,7 @@ superio_interrupt(int parent_irq, void *
 	}
 
 	/* Call the appropriate device's interrupt */
-	desc = to_irq_desc(local_irq);
-	__do_IRQ(local_irq, desc);
+	__do_IRQ(local_irq);
 
 	/* set EOI - forces a new interrupt if a lower priority device
 	 * still needs service.
Index: linux-2.6/drivers/xen/events.c
===================================================================
--- linux-2.6.orig/drivers/xen/events.c
+++ linux-2.6/drivers/xen/events.c
@@ -640,7 +640,7 @@ static void ack_dynirq(unsigned int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
 
-	move_native_irq(irq, to_irq_desc(irq));
+	move_native_irq(irq);
 
 	if (VALID_EVTCHN(evtchn))
 		clear_evtchn(evtchn);
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -244,7 +244,7 @@ extern int setup_irq(unsigned int irq, s
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 
 void set_pending_irq(unsigned int irq, cpumask_t mask);
-void move_native_irq(int irq, struct irq_desc *desc);
+void move_native_irq(int irq);
 void move_masked_irq(int irq, struct irq_desc *desc);
 
 #else /* CONFIG_GENERIC_PENDING_IRQ */
@@ -253,7 +253,7 @@ static inline void move_irq(int irq)
 {
 }
 
-static inline void move_native_irq(int irq, struct irq_desc *desc)
+static inline void move_native_irq(int irq)
 {
 }
 
@@ -269,7 +269,7 @@ static inline void set_pending_irq(unsig
 
 #else /* CONFIG_SMP */
 
-#define move_native_irq(x, y)
+#define move_native_irq(x)
 #define move_masked_irq(x, y)
 
 #endif /* CONFIG_SMP */
@@ -302,7 +302,7 @@ extern void handle_bad_irq(unsigned int
  * Monolithic do_IRQ implementation.
  */
 #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern unsigned int __do_IRQ(unsigned int irq, struct irq_desc *desc);
+extern unsigned int __do_IRQ(unsigned int irq);
 #endif
 
 /*
@@ -319,7 +319,7 @@ static inline void generic_handle_irq_de
 	if (likely(desc->handle_irq))
 		desc->handle_irq(irq, desc);
 	else
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 #endif
 }
 
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -385,10 +385,11 @@ irqreturn_t handle_IRQ_event(unsigned in
  * This is the original x86 implementation which is used for every
  * interrupt type.
  */
-unsigned int __do_IRQ(unsigned int irq, struct irq_desc *desc)
+unsigned int __do_IRQ(unsigned int irq)
 {
 	struct irqaction *action;
 	unsigned int status;
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	kstat_irqs_this_cpu(desc)++;
 	if (CHECK_IRQ_PER_CPU(desc->status)) {
Index: linux-2.6/kernel/irq/migration.c
===================================================================
--- linux-2.6.orig/kernel/irq/migration.c
+++ linux-2.6/kernel/irq/migration.c
@@ -57,8 +57,10 @@ void move_masked_irq(int irq, struct irq
 	cpus_clear(desc->pending_mask);
 }
 
-void move_native_irq(int irq, struct irq_desc *desc)
+void move_native_irq(int irq)
 {
+	struct irq_desc *desc = to_irq_desc(irq);
+
 	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
 		return;
 
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -2426,10 +2426,8 @@ static void ack_x2apic_edge(unsigned int
 
 static void ack_apic_edge(unsigned int irq)
 {
-	struct irq_desc *desc = to_irq_desc(irq);
-
 	irq_complete_move(irq);
-	move_native_irq(irq, desc);
+	move_native_irq(irq);
 	ack_APIC_irq();
 }
 

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] irq: rename irq_desc() to to_irq_desc() - fix
       [not found] <no>
                   ` (2 preceding siblings ...)
  2008-08-18  4:12 ` [PATCH] x86: apic - unify lapic_resume - fix Yinghai Lu
@ 2008-08-18 20:44 ` Yinghai Lu
  2008-08-18 20:44   ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #2 Yinghai Lu
  2010-04-15  9:02 ` [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset Tanmay Upadhyay
                   ` (34 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18 20:44 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

some left overs.
__do_IRQ not take desc as parameter

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/alpha/kernel/irq.c               |    2 +-
 arch/arm/kernel/irq.c                 |   10 ++++------
 arch/avr32/kernel/irq.c               |    8 +++-----
 arch/cris/kernel/irq.c                |    2 +-
 arch/h8300/kernel/irq.c               |    2 +-
 arch/ia64/kernel/iosapic.c            |    2 +-
 arch/ia64/kernel/msi_ia64.c           |    2 +-
 arch/ia64/sn/kernel/irq.c             |    2 +-
 arch/ia64/sn/kernel/msi_sn.c          |    2 +-
 arch/m32r/kernel/irq.c                |    2 +-
 arch/m68knommu/kernel/irq.c           |    2 +-
 arch/parisc/kernel/irq.c              |    2 +-
 arch/powerpc/platforms/powermac/pic.c |    2 +-
 arch/um/kernel/irq.c                  |    2 +-
 arch/x86/kernel/io_apic.c             |    4 +---
 drivers/parisc/dino.c                 |    3 +--
 drivers/parisc/eisa.c                 |    4 +---
 drivers/parisc/gsc.c                  |    3 +--
 drivers/parisc/superio.c              |    4 +---
 drivers/xen/events.c                  |    2 +-
 include/linux/irq.h                   |   10 +++++-----
 kernel/irq/handle.c                   |    3 ++-
 kernel/irq/migration.c                |    4 +++-
 23 files changed, 35 insertions(+), 44 deletions(-)

Index: linux-2.6/arch/alpha/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq.c
+++ linux-2.6/arch/alpha/kernel/irq.c
@@ -156,6 +156,6 @@ handle_irq(int irq)
 	 * at IPL 0.
 	 */
 	local_irq_disable();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 }
Index: linux-2.6/arch/arm/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/irq.c
+++ linux-2.6/arch/arm/kernel/irq.c
@@ -69,24 +69,22 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 
 		seq_printf(p, "%3d: ", i);
 		for_each_present_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %10s", desc->chip->name ? : "-");
+		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 
 		seq_putc(p, '\n');
 unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 #ifdef CONFIG_ARCH_ACORN
 		show_fiq_list(p, v);
Index: linux-2.6/arch/avr32/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/avr32/kernel/irq.c
+++ linux-2.6/arch/avr32/kernel/irq.c
@@ -51,10 +51,8 @@ int show_interrupts(struct seq_file *p,
 	}
 
 	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_desc(i);
-
-		spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
 		if (!action)
 			goto unlock;
 
@@ -68,7 +66,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_putc(p, '\n');
 	unlock:
-		spin_unlock_irqrestore(&desc->lock, flags);
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 
 	return 0;
Index: linux-2.6/arch/cris/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/kernel/irq.c
+++ linux-2.6/arch/cris/kernel/irq.c
@@ -99,7 +99,7 @@ asmlinkage void do_IRQ(int irq, struct p
 		printk("do_IRQ: stack overflow: %lX\n", sp);
 		show_stack(NULL, (unsigned long *)sp);
 	}
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
         irq_exit();
 	set_irq_regs(old_regs);
 }
Index: linux-2.6/arch/h8300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/irq.c
+++ linux-2.6/arch/h8300/kernel/irq.c
@@ -176,7 +176,7 @@ void __init init_IRQ(void)
 asmlinkage void do_IRQ(int irq)
 {
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 }
 
Index: linux-2.6/arch/ia64/kernel/iosapic.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/iosapic.c
+++ linux-2.6/arch/ia64/kernel/iosapic.c
@@ -452,7 +452,7 @@ iosapic_ack_edge_irq (unsigned int irq)
 	irq_desc_t *idesc = irq_desc + irq;
 
 	irq_complete_move(irq);
-	move_native_irq(irq, idesc);
+	move_native_irq(irq);
 	/*
 	 * Once we have recorded IRQ_PENDING already, we can mask the
 	 * interrupt for real. This prevents IRQ storms from unhandled
Index: linux-2.6/arch/ia64/kernel/msi_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/msi_ia64.c
+++ linux-2.6/arch/ia64/kernel/msi_ia64.c
@@ -120,7 +120,7 @@ void ia64_teardown_msi_irq(unsigned int
 static void ia64_ack_msi_irq(unsigned int irq)
 {
 	irq_complete_move(irq);
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/irq.c
+++ linux-2.6/arch/ia64/sn/kernel/irq.c
@@ -110,7 +110,7 @@ static void sn_ack_irq(unsigned int irq)
 	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 }
 
 static void sn_end_irq(unsigned int irq)
Index: linux-2.6/arch/ia64/sn/kernel/msi_sn.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/msi_sn.c
+++ linux-2.6/arch/ia64/sn/kernel/msi_sn.c
@@ -210,7 +210,7 @@ static void sn_set_msi_irq_affinity(unsi
 
 static void sn_ack_msi_irq(unsigned int irq)
 {
-	move_native_irq(irq, &irq_desc[irq]);
+	move_native_irq(irq);
 	ia64_eoi();
 }
 
Index: linux-2.6/arch/m32r/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/irq.c
+++ linux-2.6/arch/m32r/kernel/irq.c
@@ -84,7 +84,7 @@ asmlinkage unsigned int do_IRQ(int irq,
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* FIXME M32R */
 #endif
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 
Index: linux-2.6/arch/m68knommu/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m68knommu/kernel/irq.c
+++ linux-2.6/arch/m68knommu/kernel/irq.c
@@ -23,7 +23,7 @@ asmlinkage void do_IRQ(int irq, struct p
 	struct pt_regs *oldregs = set_irq_regs(regs);
 
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 
 	set_irq_regs(oldregs);
Index: linux-2.6/arch/parisc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/irq.c
+++ linux-2.6/arch/parisc/kernel/irq.c
@@ -363,7 +363,7 @@ void do_cpu_irq_mask(struct pt_regs *reg
 		goto set_out;
 	}
 #endif
-	__do_IRQ(irq, irq_desc);
+	__do_IRQ(irq);
 
  out:
 	irq_exit();
Index: linux-2.6/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/powermac/pic.c
+++ linux-2.6/arch/powerpc/platforms/powermac/pic.c
@@ -221,7 +221,7 @@ static irqreturn_t gatwick_action(int cp
 			continue;
 		irq += __ilog2(bits);
 		spin_unlock_irqrestore(&pmac_pic_lock, flags);
-		__do_IRQ(irq, &irq_desc[irq]);
+		__do_IRQ(irq);
 		spin_lock_irqsave(&pmac_pic_lock, flags);
 		rc = IRQ_HANDLED;
 	}
Index: linux-2.6/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/irq.c
+++ linux-2.6/arch/um/kernel/irq.c
@@ -332,7 +332,7 @@ unsigned int do_IRQ(int irq, struct uml_
 {
 	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
 	irq_enter();
-	__do_IRQ(irq, &irq_desc[irq]);
+	__do_IRQ(irq);
 	irq_exit();
 	set_irq_regs(old_regs);
 	return 1;
Index: linux-2.6/drivers/parisc/dino.c
===================================================================
--- linux-2.6.orig/drivers/parisc/dino.c
+++ linux-2.6/drivers/parisc/dino.c
@@ -389,10 +389,9 @@ ilr_again:
 	do {
 		int local_irq = __ffs(mask);
 		int irq = dino_dev->global_irq[local_irq];
-		struct irq_desc *desc = to_irq_desc(irq);
 		DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
 			__func__, irq, intr_dev, mask);
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 		mask &= ~(1 << local_irq);
 	} while (mask);
 
Index: linux-2.6/drivers/parisc/eisa.c
===================================================================
--- linux-2.6.orig/drivers/parisc/eisa.c
+++ linux-2.6/drivers/parisc/eisa.c
@@ -202,7 +202,6 @@ static irqreturn_t eisa_irq(int wax_irq,
 {
 	int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
 	unsigned long flags;
-	struct irq_desc *desc;
         
 	spin_lock_irqsave(&eisa_irq_lock, flags);
 	/* read IRR command */
@@ -234,8 +233,7 @@ static irqreturn_t eisa_irq(int wax_irq,
 	}
 	spin_unlock_irqrestore(&eisa_irq_lock, flags);
 
-	desc = to_irq_desc(irq);
-	__do_IRQ(irq, desc);
+	__do_IRQ(irq);
    
 	spin_lock_irqsave(&eisa_irq_lock, flags);
 	/* unmask */
Index: linux-2.6/drivers/parisc/gsc.c
===================================================================
--- linux-2.6.orig/drivers/parisc/gsc.c
+++ linux-2.6/drivers/parisc/gsc.c
@@ -87,8 +87,7 @@ irqreturn_t gsc_asic_intr(int gsc_asic_i
 	do {
 		int local_irq = __ffs(irr);
 		unsigned int irq = gsc_asic->global_irq[local_irq];
-		struct irq_desc *desc = to_irq_desc(irq);
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 		irr &= ~(1 << local_irq);
 	} while (irr);
 
Index: linux-2.6/drivers/parisc/superio.c
===================================================================
--- linux-2.6.orig/drivers/parisc/superio.c
+++ linux-2.6/drivers/parisc/superio.c
@@ -99,7 +99,6 @@ superio_interrupt(int parent_irq, void *
 {
 	u8 results;
 	u8 local_irq;
-	struct irq_desc *desc;
 
 	/* Poll the 8259 to see if there's an interrupt. */
 	outb (OCW3_POLL,IC_PIC1+0);
@@ -140,8 +139,7 @@ superio_interrupt(int parent_irq, void *
 	}
 
 	/* Call the appropriate device's interrupt */
-	desc = to_irq_desc(local_irq);
-	__do_IRQ(local_irq, desc);
+	__do_IRQ(local_irq);
 
 	/* set EOI - forces a new interrupt if a lower priority device
 	 * still needs service.
Index: linux-2.6/drivers/xen/events.c
===================================================================
--- linux-2.6.orig/drivers/xen/events.c
+++ linux-2.6/drivers/xen/events.c
@@ -640,7 +640,7 @@ static void ack_dynirq(unsigned int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
 
-	move_native_irq(irq, to_irq_desc(irq));
+	move_native_irq(irq);
 
 	if (VALID_EVTCHN(evtchn))
 		clear_evtchn(evtchn);
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -244,7 +244,7 @@ extern int setup_irq(unsigned int irq, s
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 
 void set_pending_irq(unsigned int irq, cpumask_t mask);
-void move_native_irq(int irq, struct irq_desc *desc);
+void move_native_irq(int irq);
 void move_masked_irq(int irq, struct irq_desc *desc);
 
 #else /* CONFIG_GENERIC_PENDING_IRQ */
@@ -253,7 +253,7 @@ static inline void move_irq(int irq)
 {
 }
 
-static inline void move_native_irq(int irq, struct irq_desc *desc)
+static inline void move_native_irq(int irq)
 {
 }
 
@@ -269,7 +269,7 @@ static inline void set_pending_irq(unsig
 
 #else /* CONFIG_SMP */
 
-#define move_native_irq(x, y)
+#define move_native_irq(x)
 #define move_masked_irq(x, y)
 
 #endif /* CONFIG_SMP */
@@ -302,7 +302,7 @@ extern void handle_bad_irq(unsigned int
  * Monolithic do_IRQ implementation.
  */
 #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern unsigned int __do_IRQ(unsigned int irq, struct irq_desc *desc);
+extern unsigned int __do_IRQ(unsigned int irq);
 #endif
 
 /*
@@ -319,7 +319,7 @@ static inline void generic_handle_irq_de
 	if (likely(desc->handle_irq))
 		desc->handle_irq(irq, desc);
 	else
-		__do_IRQ(irq, desc);
+		__do_IRQ(irq);
 #endif
 }
 
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -385,10 +385,11 @@ irqreturn_t handle_IRQ_event(unsigned in
  * This is the original x86 implementation which is used for every
  * interrupt type.
  */
-unsigned int __do_IRQ(unsigned int irq, struct irq_desc *desc)
+unsigned int __do_IRQ(unsigned int irq)
 {
 	struct irqaction *action;
 	unsigned int status;
+	struct irq_desc *desc = to_irq_desc(irq);
 
 	kstat_irqs_this_cpu(desc)++;
 	if (CHECK_IRQ_PER_CPU(desc->status)) {
Index: linux-2.6/kernel/irq/migration.c
===================================================================
--- linux-2.6.orig/kernel/irq/migration.c
+++ linux-2.6/kernel/irq/migration.c
@@ -57,8 +57,10 @@ void move_masked_irq(int irq, struct irq
 	cpus_clear(desc->pending_mask);
 }
 
-void move_native_irq(int irq, struct irq_desc *desc)
+void move_native_irq(int irq)
 {
+	struct irq_desc *desc = to_irq_desc(irq);
+
 	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
 		return;
 
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -2426,10 +2426,8 @@ static void ack_x2apic_edge(unsigned int
 
 static void ack_apic_edge(unsigned int irq)
 {
-	struct irq_desc *desc = to_irq_desc(irq);
-
 	irq_complete_move(irq);
-	move_native_irq(irq, desc);
+	move_native_irq(irq);
 	ack_APIC_irq();
 }
 

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #2
  2008-08-18 20:44 ` [PATCH] irq: rename irq_desc() to to_irq_desc() " Yinghai Lu
@ 2008-08-18 20:44   ` Yinghai Lu
  2008-08-18 20:44     ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3 Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18 20:44 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

kstat_irqs related, so only CONFIG_DYN_ARRAY/SPARSE_IRQ will have kstat_irqs in irq_desc

other arch still have kstat_irqs in kstat

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/alpha/kernel/irq.c                 |    2 +-
 arch/alpha/kernel/irq_alpha.c           |    2 +-
 arch/arm/kernel/irq.c                   |    2 +-
 arch/arm/mach-ns9xxx/irq.c              |    3 ++-
 arch/avr32/kernel/irq.c                 |    4 ++--
 arch/cris/kernel/irq.c                  |    2 +-
 arch/frv/kernel/irq.c                   |    2 +-
 arch/h8300/kernel/irq.c                 |    2 +-
 arch/ia64/kernel/irq.c                  |    2 +-
 arch/ia64/kernel/irq_ia64.c             |    8 ++++----
 arch/m32r/kernel/irq.c                  |    2 +-
 arch/mips/kernel/irq.c                  |    2 +-
 arch/mips/sgi-ip22/ip22-int.c           |    2 +-
 arch/mips/sgi-ip22/ip22-time.c          |    2 +-
 arch/mips/sibyte/bcm1480/smp.c          |    2 +-
 arch/mips/sibyte/sb1250/smp.c           |    2 +-
 arch/mn10300/kernel/irq.c               |    2 +-
 arch/parisc/kernel/irq.c                |    2 +-
 arch/powerpc/kernel/irq.c               |    2 +-
 arch/powerpc/platforms/cell/interrupt.c |    2 +-
 arch/sh/kernel/irq.c                    |    2 +-
 arch/sparc64/kernel/irq.c               |    2 +-
 arch/sparc64/kernel/time.c              |    3 +--
 arch/um/kernel/irq.c                    |    2 +-
 arch/xtensa/kernel/irq.c                |    2 +-
 include/linux/irq.h                     |    5 +++++
 include/linux/kernel_stat.h             |    4 ++--
 kernel/irq/chip.c                       |   20 ++++++++++++++++++++
 kernel/irq/handle.c                     |   10 ++++++++++
 29 files changed, 67 insertions(+), 32 deletions(-)

Index: linux-2.6/arch/alpha/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq.c
+++ linux-2.6/arch/alpha/kernel/irq.c
@@ -89,7 +89,7 @@ show_interrupts(struct seq_file *p, void
 		seq_printf(p, "%10u ", kstat_irqs(irq));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]);
 #endif
 		seq_printf(p, " %14s", irq_desc[irq].chip->typename);
 		seq_printf(p, "  %c%s",
Index: linux-2.6/arch/alpha/kernel/irq_alpha.c
===================================================================
--- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c
+++ linux-2.6/arch/alpha/kernel/irq_alpha.c
@@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned l
 		smp_percpu_timer_interrupt(regs);
 		cpu = smp_processor_id();
 		if (cpu != boot_cpuid) {
-			irq_desc[RTC_IRQ].kstat_irqs[cpu]++;
+		        kstat_cpu(cpu).irqs[RTC_IRQ]++;
 		} else {
 			handle_irq(RTC_IRQ);
 		}
Index: linux-2.6/arch/arm/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/irq.c
+++ linux-2.6/arch/arm/kernel/irq.c
@@ -76,7 +76,7 @@ int show_interrupts(struct seq_file *p,
 
 		seq_printf(p, "%3d: ", i);
 		for_each_present_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
 		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
Index: linux-2.6/arch/arm/mach-ns9xxx/irq.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-ns9xxx/irq.c
+++ linux-2.6/arch/arm/mach-ns9xxx/irq.c
@@ -63,6 +63,7 @@ static struct irq_chip ns9xxx_chip = {
 #else
 static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
 {
+	unsigned int cpu = smp_processor_id();
 	struct irqaction *action;
 	irqreturn_t action_ret;
 
@@ -71,7 +72,7 @@ static void handle_prio_irq(unsigned int
 	BUG_ON(desc->status & IRQ_INPROGRESS);
 
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-	kstat_irqs_this_cpu(desc)++;
+	kstat_cpu(cpu).irqs[irq]++;
 
 	action = desc->action;
 	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
Index: linux-2.6/arch/avr32/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/avr32/kernel/irq.c
+++ linux-2.6/arch/avr32/kernel/irq.c
@@ -58,8 +58,8 @@ int show_interrupts(struct seq_file *p,
 
 		seq_printf(p, "%3d: ", i);
 		for_each_online_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %8s", desc->chip->name ? : "-");
+			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+		seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
Index: linux-2.6/arch/cris/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/cris/kernel/irq.c
+++ linux-2.6/arch/cris/kernel/irq.c
@@ -66,7 +66,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/frv/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/frv/kernel/irq.c
+++ linux-2.6/arch/frv/kernel/irq.c
@@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p,
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+				seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
 			seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 			seq_printf(p, "  %s", action->name);
 			for (action = action->next;
Index: linux-2.6/arch/h8300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/h8300/kernel/irq.c
+++ linux-2.6/arch/h8300/kernel/irq.c
@@ -196,7 +196,7 @@ int show_interrupts(struct seq_file *p,
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+		seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/ia64/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq.c
+++ linux-2.6/arch/ia64/kernel/irq.c
@@ -80,7 +80,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j) {
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 		}
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
Index: linux-2.6/arch/ia64/kernel/irq_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq_ia64.c
+++ linux-2.6/arch/ia64/kernel/irq_ia64.c
@@ -495,9 +495,9 @@ ia64_handle_irq (ia64_vector vector, str
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_irqs_this_cpu(&irq_desc[vector])++;
+			kstat_this_cpu.irqs[vector]++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_irqs_this_cpu(&irq_desc[vector])++;
+			kstat_this_cpu.irqs[vector]++;
 		else {
 			int irq = local_vector_to_irq(vector);
 
@@ -553,9 +553,9 @@ void ia64_process_pending_intr(void)
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_irqs_this_cpu(&irq_desc[vector])++;
+			kstat_this_cpu.irqs[vector]++;
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_irqs_this_cpu(&irq_desc[vector])++;
+			kstat_this_cpu.irqs[vector]++;
 		else {
 			struct pt_regs *old_regs = set_irq_regs(NULL);
 			int irq = local_vector_to_irq(vector);
Index: linux-2.6/arch/m32r/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/m32r/kernel/irq.c
+++ linux-2.6/arch/m32r/kernel/irq.c
@@ -52,7 +52,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/mips/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/irq.c
+++ linux-2.6/arch/mips/kernel/irq.c
@@ -108,7 +108,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/mips/sgi-ip22/ip22-int.c
===================================================================
--- linux-2.6.orig/arch/mips/sgi-ip22/ip22-int.c
+++ linux-2.6/arch/mips/sgi-ip22/ip22-int.c
@@ -164,7 +164,7 @@ static void indy_buserror_irq(void)
 	int irq = SGI_BUSERR_IRQ;
 
 	irq_enter();
-	kstat_irqs_this_cpu(&irq_desc[irq])++;
+	kstat_this_cpu.irqs[irq]++;
 	ip22_be_interrupt(irq);
 	irq_exit();
 }
Index: linux-2.6/arch/mips/sgi-ip22/ip22-time.c
===================================================================
--- linux-2.6.orig/arch/mips/sgi-ip22/ip22-time.c
+++ linux-2.6/arch/mips/sgi-ip22/ip22-time.c
@@ -186,7 +186,7 @@ void indy_8254timer_irq(void)
 	char c;
 
 	irq_enter();
-	kstat_irqs_this_cpu(&irq_desc[irq])++;
+	kstat_this_cpu.irqs[irq]++;
 	printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
 	ArcRead(0, &c, 1, &cnt);
 	ArcEnterInteractiveMode();
Index: linux-2.6/arch/mips/sibyte/bcm1480/smp.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/bcm1480/smp.c
+++ linux-2.6/arch/mips/sibyte/bcm1480/smp.c
@@ -180,7 +180,7 @@ void bcm1480_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	irq_desc[K_BCM1480_INT_MBOX_0_0].kstat_irqs[cpu]++;
+	kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
 
Index: linux-2.6/arch/mips/sibyte/sb1250/smp.c
===================================================================
--- linux-2.6.orig/arch/mips/sibyte/sb1250/smp.c
+++ linux-2.6/arch/mips/sibyte/sb1250/smp.c
@@ -168,7 +168,7 @@ void sb1250_mailbox_interrupt(void)
 	int cpu = smp_processor_id();
 	unsigned int action;
 
-	irq_desc[K_INT_MBOX_0].kstat_irqs[cpu]++;
+	kstat_this_cpu.irqs[K_INT_MBOX_0]++;
 	/* Load the mailbox register to figure out what we're supposed to do */
 	action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
 
Index: linux-2.6/arch/mn10300/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/mn10300/kernel/irq.c
+++ linux-2.6/arch/mn10300/kernel/irq.c
@@ -201,7 +201,7 @@ int show_interrupts(struct seq_file *p,
 		if (action) {
 			seq_printf(p, "%3d: ", i);
 			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+				seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
 			seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
 				   (GxICR(i) & GxICR_LEVEL) >>
 				   GxICR_LEVEL_SHIFT);
Index: linux-2.6/arch/parisc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/parisc/kernel/irq.c
+++ linux-2.6/arch/parisc/kernel/irq.c
@@ -183,7 +183,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #else
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
Index: linux-2.6/arch/powerpc/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/irq.c
+++ linux-2.6/arch/powerpc/kernel/irq.c
@@ -190,7 +190,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #else
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif /* CONFIG_SMP */
Index: linux-2.6/arch/powerpc/platforms/cell/interrupt.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/interrupt.c
+++ linux-2.6/arch/powerpc/platforms/cell/interrupt.c
@@ -254,7 +254,7 @@ static void handle_iic_irq(unsigned int
 		goto out_eoi;
 	}
 
-	kstat_irqs_this_cpu(desc)++;
+	kstat_cpu(cpu).irqs[irq]++;
 
 	/* Mark the IRQ currently in progress.*/
 	desc->status |= IRQ_INPROGRESS;
Index: linux-2.6/arch/sh/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/sh/kernel/irq.c
+++ linux-2.6/arch/sh/kernel/irq.c
@@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p,
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
 		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/sparc64/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/irq.c
+++ linux-2.6/arch/sparc64/kernel/irq.c
@@ -185,7 +185,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %9s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/sparc64/kernel/time.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/time.c
+++ linux-2.6/arch/sparc64/kernel/time.c
@@ -16,7 +16,6 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/timex.h>
@@ -943,7 +942,7 @@ void timer_interrupt(int irq, struct pt_
 
 	irq_enter();
 
-	irq_desc[0].kstat_irqs[0]++;
+	kstat_this_cpu.irqs[0]++;
 
 	if (unlikely(!evt->event_handler)) {
 		printk(KERN_WARNING
Index: linux-2.6/arch/um/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/irq.c
+++ linux-2.6/arch/um/kernel/irq.c
@@ -42,7 +42,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/arch/xtensa/kernel/irq.c
===================================================================
--- linux-2.6.orig/arch/xtensa/kernel/irq.c
+++ linux-2.6/arch/xtensa/kernel/irq.c
@@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p,
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->typename);
 		seq_printf(p, "  %s", action->name);
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -219,8 +219,13 @@ extern struct irq_desc *irq_descX;
 
 #endif
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
 #define kstat_irqs_this_cpu(DESC) \
 	((DESC)->kstat_irqs[smp_processor_id()])
+#else
+#define kstat_irqs_this_cpu(irq) \
+	kstat_this_cpu.irqs[irq]
+#endif
 
 /*
  * Migration helpers for obsolete names, they will go away:
Index: linux-2.6/include/linux/kernel_stat.h
===================================================================
--- linux-2.6.orig/include/linux/kernel_stat.h
+++ linux-2.6/include/linux/kernel_stat.h
@@ -28,7 +28,7 @@ struct cpu_usage_stat {
 
 struct kernel_stat {
 	struct cpu_usage_stat	cpustat;
-#ifndef CONFIG_GENRIC_HARDIRQS
+#ifndef CONFIG_HAVE_DYN_ARRAY
        unsigned int irqs[NR_IRQS];
 #endif
 };
@@ -41,7 +41,7 @@ DECLARE_PER_CPU(struct kernel_stat, ksta
 
 extern unsigned long long nr_context_switches(void);
 
-#ifndef CONFIG_GENERIC_HARDIRQS
+#ifndef CONFIG_HAVE_DYN_ARRAY
 static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
        return kstat_cpu(cpu).irqs[irq];
Index: linux-2.6/kernel/irq/chip.c
===================================================================
--- linux-2.6.orig/kernel/irq/chip.c
+++ linux-2.6/kernel/irq/chip.c
@@ -326,7 +326,11 @@ handle_simple_irq(unsigned int irq, stru
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 		goto out_unlock;
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 
 	action = desc->action;
 	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
@@ -367,7 +371,11 @@ handle_level_irq(unsigned int irq, struc
 	if (unlikely(desc->status & IRQ_INPROGRESS))
 		goto out_unlock;
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 
 	/*
 	 * If its disabled or no action available
@@ -414,7 +422,11 @@ handle_fasteoi_irq(unsigned int irq, str
 		goto out;
 
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 
 	/*
 	 * If its disabled or no action available
@@ -479,7 +491,11 @@ handle_edge_irq(unsigned int irq, struct
 		goto out_unlock;
 	}
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 
 	/* Start handling the irq */
 	desc->chip->ack(irq);
@@ -534,7 +550,11 @@ handle_percpu_irq(unsigned int irq, stru
 {
 	irqreturn_t action_ret;
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 
 	if (desc->chip->ack)
 		desc->chip->ack(irq);
Index: linux-2.6/kernel/irq/handle.c
===================================================================
--- linux-2.6.orig/kernel/irq/handle.c
+++ linux-2.6/kernel/irq/handle.c
@@ -34,7 +34,11 @@ void
 handle_bad_irq(unsigned int irq, struct irq_desc *desc)
 {
 	print_irq_desc(irq, desc);
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 	ack_bad_irq(irq);
 }
 
@@ -391,7 +395,11 @@ unsigned int __do_IRQ(unsigned int irq)
 	unsigned int status;
 	struct irq_desc *desc = to_irq_desc(irq);
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
 	kstat_irqs_this_cpu(desc)++;
+#else
+	kstat_irqs_this_cpu(irq)++;
+#endif
 	if (CHECK_IRQ_PER_CPU(desc->status)) {
 		irqreturn_t action_ret;
 
@@ -493,10 +501,12 @@ void early_init_irq_lock_class(void)
 }
 #endif
 
+#ifdef CONFIG_HAVE_DYN_ARRAY
 unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
 	struct irq_desc *desc = to_irq_desc(irq);
 	return desc->kstat_irqs[cpu];
 }
+#endif
 EXPORT_SYMBOL(kstat_irqs_cpu);
 

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3
  2008-08-18 20:44   ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #2 Yinghai Lu
@ 2008-08-18 20:44     ` Yinghai Lu
  2008-08-19  0:11       ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-18 20:44 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
  Cc: linux-kernel, Yinghai Lu

add create_irq_nr, and retore create_irq to old

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>

---
 arch/arm/mach-iop13xx/msi.c  |    4 ++--
 arch/ia64/kernel/iosapic.c   |    6 +++---
 arch/ia64/kernel/irq_ia64.c  |    2 +-
 arch/ia64/kernel/msi_ia64.c  |    2 +-
 arch/ia64/sn/kernel/msi_sn.c |    2 +-
 arch/x86/kernel/io_apic.c    |   18 +++++++++++++++---
 drivers/pci/htirq.c          |    2 +-
 drivers/pci/intel-iommu.c    |    2 +-
 include/linux/irq.h          |    3 ++-
 9 files changed, 27 insertions(+), 14 deletions(-)

Index: linux-2.6/arch/arm/mach-iop13xx/msi.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-iop13xx/msi.c
+++ linux-2.6/arch/arm/mach-iop13xx/msi.c
@@ -125,7 +125,7 @@ void __init iop13xx_msi_init(void)
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq(unsigned not_used)
+int create_irq(void)
 {
 	int irq, pos;
 
@@ -173,7 +173,7 @@ static struct irq_chip iop13xx_msi_chip
 
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
-	int id, irq = create_irq(0);
+	int id, irq = create_irq();
 	struct msi_msg msg;
 
 	if (irq < 0)
Index: linux-2.6/arch/ia64/kernel/iosapic.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/iosapic.c
+++ linux-2.6/arch/ia64/kernel/iosapic.c
@@ -532,7 +532,7 @@ iosapic_reassign_vector (int irq)
 	int new_irq;
 
 	if (iosapic_intr_info[irq].count) {
-		new_irq = create_irq(0);
+		new_irq = create_irq();
 		if (new_irq < 0)
 			panic("%s: out of interrupt vectors!\n", __func__);
 		printk(KERN_INFO "Reassigning vector %d to %d\n",
@@ -783,7 +783,7 @@ iosapic_register_intr (unsigned int gsi,
 			goto unlock_iosapic_lock;
 		}
 	} else
-		irq = create_irq(0);
+		irq = create_irq();
 
 	/* If vector is running out, we try to find a sharable vector */
 	if (irq < 0) {
@@ -922,7 +922,7 @@ iosapic_register_platform_intr (u32 int_
 		delivery = IOSAPIC_PMI;
 		break;
 	      case ACPI_INTERRUPT_INIT:
-		irq = create_irq(0);
+		irq = create_irq();
 		if (irq < 0)
 			panic("%s: out of interrupt vectors!\n", __func__);
 		vector = irq_to_vector(irq);
Index: linux-2.6/arch/ia64/kernel/irq_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/irq_ia64.c
+++ linux-2.6/arch/ia64/kernel/irq_ia64.c
@@ -403,7 +403,7 @@ void destroy_and_reserve_irq(unsigned in
 /*
  * Dynamic irq allocate and deallocation for MSI
  */
-unsigned int create_irq(unsigned int not_used)
+int create_irq(void)
 {
 	unsigned long flags;
 	int irq, vector, cpu;
Index: linux-2.6/arch/ia64/kernel/msi_ia64.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/msi_ia64.c
+++ linux-2.6/arch/ia64/kernel/msi_ia64.c
@@ -84,7 +84,7 @@ int ia64_setup_msi_irq(struct pci_dev *p
 	int	irq, vector;
 	cpumask_t mask;
 
-	irq = create_irq(0);
+	irq = create_irq();
 	if (irq < 0)
 		return irq;
 
Index: linux-2.6/arch/ia64/sn/kernel/msi_sn.c
===================================================================
--- linux-2.6.orig/arch/ia64/sn/kernel/msi_sn.c
+++ linux-2.6/arch/ia64/sn/kernel/msi_sn.c
@@ -83,7 +83,7 @@ int sn_setup_msi_irq(struct pci_dev *pde
 	if (provider == NULL || provider->dma_map_consistent == NULL)
 		return -EINVAL;
 
-	irq = create_irq(0);
+	irq = create_irq();
 	if (irq < 0)
 		return irq;
 
Index: linux-2.6/arch/x86/kernel/io_apic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/io_apic.c
+++ linux-2.6/arch/x86/kernel/io_apic.c
@@ -3039,7 +3039,7 @@ device_initcall(ioapic_init_sysfs);
 /*
  * Dynamic irq allocate and deallocation
  */
-unsigned int create_irq(unsigned int irq_want)
+unsigned int create_irq_nr(unsigned int irq_want)
 {
 	/* Allocate an unused irq */
 	unsigned int irq;
@@ -3074,6 +3074,18 @@ unsigned int create_irq(unsigned int irq
 	return irq;
 }
 
+int create_irq(void)
+{
+	int irq;
+
+	irq = create_irq_nr(nr_irqs - 1);
+
+	if (irq == 0)
+		irq = -1;
+
+	return irq;
+}
+
 void destroy_irq(unsigned int irq)
 {
 	unsigned long flags;
@@ -3346,7 +3358,7 @@ int arch_setup_msi_irq(struct pci_dev *d
 
 	irq_want = build_irq_for_pci_dev(dev) + 0x100;
 
-	irq = create_irq(irq_want);
+	irq = create_irq_nr(irq_want);
 	if (irq == 0)
 		return -1;
 
@@ -3388,7 +3400,7 @@ int arch_setup_msi_irqs(struct pci_dev *
 	irq_want = build_irq_for_pci_dev(dev) + 0x100;
 	sub_handle = 0;
 	list_for_each_entry(desc, &dev->msi_list, list) {
-		irq = create_irq(irq_want--);
+		irq = create_irq_nr(irq_want--);
 		if (irq == 0)
 			return -1;
 #ifdef CONFIG_INTR_REMAP
Index: linux-2.6/drivers/pci/htirq.c
===================================================================
--- linux-2.6.orig/drivers/pci/htirq.c
+++ linux-2.6/drivers/pci/htirq.c
@@ -139,7 +139,7 @@ int __ht_create_irq(struct pci_dev *dev,
 	cfg->msg.address_hi = 0xffffffff;
 
 	irq_want= build_irq_for_pci_dev(dev);
-	irq = create_irq(irq_want + idx);
+	irq = create_irq_nr(irq_want + idx);
 	if (irq == 0) {
 		kfree(cfg);
 		return -EBUSY;
Index: linux-2.6/drivers/pci/intel-iommu.c
===================================================================
--- linux-2.6.orig/drivers/pci/intel-iommu.c
+++ linux-2.6/drivers/pci/intel-iommu.c
@@ -915,7 +915,7 @@ int dmar_set_interrupt(struct intel_iomm
 {
 	int irq, ret;
 
-	irq = create_irq(0);
+	irq = create_irq();
 	if (!irq) {
 		printk(KERN_ERR "IOMMU: no free vectors\n");
 		return -EINVAL;
Index: linux-2.6/include/linux/irq.h
===================================================================
--- linux-2.6.orig/include/linux/irq.h
+++ linux-2.6/include/linux/irq.h
@@ -396,7 +396,8 @@ extern void set_irq_noprobe(unsigned int
 extern void set_irq_probe(unsigned int irq);
 
 /* Handle dynamic irq creation and destruction */
-extern unsigned int create_irq(unsigned int irq_want);
+extern unsigned int create_irq_nr(unsigned int irq_want);
+extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
 
 /* Test to see if a driver has successfully requested an irq */

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3
  2008-08-18 20:44     ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3 Yinghai Lu
@ 2008-08-19  0:11       ` Ingo Molnar
  2008-08-19  0:38         ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-19  0:11 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> add create_irq_nr, and retore create_irq to old

applied all 3 patches to tip/irq/sparseirq - thanks Yinghai!

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3
  2008-08-19  0:11       ` Ingo Molnar
@ 2008-08-19  0:38         ` Ingo Molnar
  2008-08-19  0:48           ` Yinghai Lu
  0 siblings, 1 reply; 206+ messages in thread
From: Ingo Molnar @ 2008-08-19  0:38 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel


* Ingo Molnar <mingo@elte.hu> wrote:

> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> 
> > add create_irq_nr, and retore create_irq to old
> 
> applied all 3 patches to tip/irq/sparseirq - thanks Yinghai!

build fix for tip/master, from tip/x86/spinlocks. I merged that branch 
into tip/irq/sparseirq and applied this fix.

	Ingo

------------>
>From 1f73df742c77472d2e14e47b8c568218952af1d7 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Tue, 19 Aug 2008 02:33:39 +0200
Subject: [PATCH] irq: build fix

fix:

 arch/x86/xen/spinlock.c: In function 'xen_spin_lock_slow':
 arch/x86/xen/spinlock.c:90: error: 'struct kernel_stat' has no member named 'irqs'

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/xen/spinlock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 8dc4d31..dc21378 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -87,7 +87,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock)
 
 	/* block until irq becomes pending */
 	xen_poll_irq(irq);
-	kstat_this_cpu.irqs[irq]++;
+	kstat_irqs_this_cpu(&irq_desc[irq])++;
 
 out:
 	unspinning_lock(xl);

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3
  2008-08-19  0:38         ` Ingo Molnar
@ 2008-08-19  0:48           ` Yinghai Lu
  2008-08-19  1:16             ` Ingo Molnar
  0 siblings, 1 reply; 206+ messages in thread
From: Yinghai Lu @ 2008-08-19  0:48 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel

On Mon, Aug 18, 2008 at 5:38 PM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Ingo Molnar <mingo@elte.hu> wrote:
>
>> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>>
>> > add create_irq_nr, and retore create_irq to old
>>
>> applied all 3 patches to tip/irq/sparseirq - thanks Yinghai!
>
> build fix for tip/master, from tip/x86/spinlocks. I merged that branch
> into tip/irq/sparseirq and applied this fix.
>
>        Ingo
>
> ------------>
> From 1f73df742c77472d2e14e47b8c568218952af1d7 Mon Sep 17 00:00:00 2001
> From: Ingo Molnar <mingo@elte.hu>
> Date: Tue, 19 Aug 2008 02:33:39 +0200
> Subject: [PATCH] irq: build fix
>
> fix:
>
>  arch/x86/xen/spinlock.c: In function 'xen_spin_lock_slow':
>  arch/x86/xen/spinlock.c:90: error: 'struct kernel_stat' has no member named 'irqs'
>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
> ---
>  arch/x86/xen/spinlock.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
> index 8dc4d31..dc21378 100644
> --- a/arch/x86/xen/spinlock.c
> +++ b/arch/x86/xen/spinlock.c
> @@ -87,7 +87,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock)
>
>        /* block until irq becomes pending */
>        xen_poll_irq(irq);
> -       kstat_this_cpu.irqs[irq]++;
> +       kstat_irqs_this_cpu(&irq_desc[irq])++;
>
>  out:
>        unspinning_lock(xl);
>

should be

kstat_irqs_this_cpu(to_irq_desc(irq))++;

otherwise when CONFIG_HAVE_SPARSE_IRQ is set, it will fail.

when sparse_irq is set, only have irq_descX list...

YH

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3
  2008-08-19  0:48           ` Yinghai Lu
@ 2008-08-19  1:16             ` Ingo Molnar
  0 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2008-08-19  1:16 UTC (permalink / raw)
  To: Yinghai Lu; +Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, linux-kernel


* Yinghai Lu <yhlu.kernel@gmail.com> wrote:

> > -       kstat_this_cpu.irqs[irq]++;
> > +       kstat_irqs_this_cpu(&irq_desc[irq])++;
> >
> >  out:
> >        unspinning_lock(xl);
> >
> 
> should be
> 
> kstat_irqs_this_cpu(to_irq_desc(irq))++;
> 
> otherwise when CONFIG_HAVE_SPARSE_IRQ is set, it will fail.
> 
> when sparse_irq is set, only have irq_descX list...

ok, fixed it - updated patch below. Build testing just triggered it as 
well.

	Ingo

----------->
>From ba0540e8ae86abbe55b643e230ce276984fbb650 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Tue, 19 Aug 2008 02:33:39 +0200
Subject: [PATCH] irq: build fix

fix:

 arch/x86/xen/spinlock.c: In function 'xen_spin_lock_slow':
 arch/x86/xen/spinlock.c:90: error: 'struct kernel_stat' has no member named 'irqs'

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/xen/spinlock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 8dc4d31..bfb1707 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -87,7 +87,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock)
 
 	/* block until irq becomes pending */
 	xen_poll_irq(irq);
-	kstat_this_cpu.irqs[irq]++;
+	kstat_irqs_this_cpu(to_irq_desc(irq))++;
 
 out:
 	unspinning_lock(xl);

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset
       [not found] <no>
                   ` (3 preceding siblings ...)
  2008-08-18 20:44 ` [PATCH] irq: rename irq_desc() to to_irq_desc() " Yinghai Lu
@ 2010-04-15  9:02 ` Tanmay Upadhyay
  2010-04-20  5:51 ` Tanmay Upadhyay
                   ` (33 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-04-15  9:02 UTC (permalink / raw)
  To: u-boot

There exists PCIe endpoints(not all) that remains in reset state till
PERST# line (A11 on the PCIe connector) is hold low. They come out of
reset only when this line is high.

In case of OpenRD, this line was in tri-state. So, some of the PCIe
devices would never appear on the PCIe bus. This patch makes PERST#
line high while booting to bring such PCIe devices out of reset.

XGI Vollari Z11 GPU and Intel WiFi 4965 are the ones who doesn't care
about this line. Where as Broadcom's BCM970012 won't appear on the PCIe
bus until PERST# is high. With this patch both kinds of device would
appear on the PCIe bus.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
Signed-off-by: Dhaval Vasa <dhaval.vasa@einfochips.com>
---
 board/Marvell/openrd_base/openrd_base.h |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/board/Marvell/openrd_base/openrd_base.h b/board/Marvell/openrd_base/openrd_base.h
index f3daf17..965bd50 100644
--- a/board/Marvell/openrd_base/openrd_base.h
+++ b/board/Marvell/openrd_base/openrd_base.h
@@ -30,10 +30,10 @@
 #ifndef __OPENRD_BASE_H
 #define __OPENRD_BASE_H
 
-#define OPENRD_OE_LOW		(~(1<<28))        /* RS232 / RS485 */
-#define OPENRD_OE_HIGH		(~(1<<2))         /* SD / UART1 */
-#define OPENRD_OE_VAL_LOW		(0)       /* Sel RS232 */
-#define OPENRD_OE_VAL_HIGH		(1 << 2)  /* Sel SD */
+#define OPENRD_OE_LOW		(~((1<<28) | (1<<7)))  /* RS232 / RS485 */
+#define OPENRD_OE_HIGH		(~(1<<2))              /* SD / UART1 */
+#define OPENRD_OE_VAL_LOW		(1<<7)         /* Sel RS232 */
+#define OPENRD_OE_VAL_HIGH		(1 << 2)       /* Sel SD */
 
 /* PHY related */
 #define MV88E1116_LED_FCTRL_REG		10
-- 
1.6.6.1

-- 
_____________________________________________________________________
Disclaimer: This e-mail message and all attachments transmitted with it
are intended solely for the use of the addressee and may contain legally
privileged and confidential information. If the reader of this message
is not the intended recipient, or an employee or agent responsible for
delivering this message to the intended recipient, you are hereby
notified that any dissemination, distribution, copying, or other use of
this message or its attachments is strictly prohibited. If you have
received this message in error, please notify the sender immediately by
replying to this message and please delete it from your computer. Any
views expressed in this message are those of the individual sender
unless otherwise stated.Company has taken enough precautions to prevent
the spread of viruses. However the company accepts no liability for any
damage caused by any virus transmitted by this email.
_____________________________________________________________________
 

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset
       [not found] <no>
                   ` (4 preceding siblings ...)
  2010-04-15  9:02 ` [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset Tanmay Upadhyay
@ 2010-04-20  5:51 ` Tanmay Upadhyay
  2010-04-30  6:49   ` Prafulla Wadaskar
  2010-04-22 13:16 ` [PATCH] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
                   ` (32 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-04-20  5:51 UTC (permalink / raw)
  To: u-boot

There exists PCIe endpoints(not all) that remains in reset state till
PERST# line (A11 on the PCIe connector) is hold low. They come out of
reset only when this line is high.

In case of OpenRD, this line was in tri-state. So, some of the PCIe
devices would never appear on the PCIe bus. This patch makes PERST#
line high while booting to bring such PCIe devices out of reset.

XGI Vollari Z11 GPU and Intel WiFi 4965 are the ones who doesn't care
about this line. Where as Broadcom's BCM970012 won't appear on the PCIe
bus until PERST# is high. With this patch both kinds of device would
appear on the PCIe bus.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
Signed-off-by: Dhaval Vasa <dhaval.vasa@einfochips.com>
---
 board/Marvell/openrd_base/openrd_base.h |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/board/Marvell/openrd_base/openrd_base.h b/board/Marvell/openrd_base/openrd_base.h
index f3daf17..bf75fc6 100644
--- a/board/Marvell/openrd_base/openrd_base.h
+++ b/board/Marvell/openrd_base/openrd_base.h
@@ -30,10 +30,10 @@
 #ifndef __OPENRD_BASE_H
 #define __OPENRD_BASE_H
 
-#define OPENRD_OE_LOW		(~(1<<28))        /* RS232 / RS485 */
-#define OPENRD_OE_HIGH		(~(1<<2))         /* SD / UART1 */
-#define OPENRD_OE_VAL_LOW		(0)       /* Sel RS232 */
-#define OPENRD_OE_VAL_HIGH		(1 << 2)  /* Sel SD */
+#define OPENRD_OE_LOW		(~((1<<28) | (1<<7)))  /* RS232 / RS485, PCIe */
+#define OPENRD_OE_HIGH		(~(1<<2))              /* SD / UART1 */
+#define OPENRD_OE_VAL_LOW	(1<<7)        /* Sel RS232, PCIe out of reset */
+#define OPENRD_OE_VAL_HIGH	(1 << 2)      /* Sel SD */
 
 /* PHY related */
 #define MV88E1116_LED_FCTRL_REG		10
-- 
1.6.6.1

-- 
_____________________________________________________________________
Disclaimer: This e-mail message and all attachments transmitted with it
are intended solely for the use of the addressee and may contain legally
privileged and confidential information. If the reader of this message
is not the intended recipient, or an employee or agent responsible for
delivering this message to the intended recipient, you are hereby
notified that any dissemination, distribution, copying, or other use of
this message or its attachments is strictly prohibited. If you have
received this message in error, please notify the sender immediately by
replying to this message and please delete it from your computer. Any
views expressed in this message are those of the individual sender
unless otherwise stated.Company has taken enough precautions to prevent
the spread of viruses. However the company accepts no liability for any
damage caused by any virus transmitted by this email.
_____________________________________________________________________
 

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH] OpenRD: Enable SD/UART selection for serial port 1
       [not found] <no>
                   ` (5 preceding siblings ...)
  2010-04-20  5:51 ` Tanmay Upadhyay
@ 2010-04-22 13:16 ` Tanmay Upadhyay
  2010-05-04 12:48 ` [U-Boot] [PATCH] OpenRD: Reset PCIe endpoint while boot-up through PERST# Tanmay Upadhyay
                   ` (31 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-04-22 13:16 UTC (permalink / raw)
  To: dhaval.vasa; +Cc: linux-kernel, Tanmay Upadhyay

This patch enables user to use serial port 1 of the OpenRD device for SDIO
or UART(RS232/RS485). The selection can be done through kernel parameter.

By default the port would be used for SDIO. To select RS232 or RS485 mode,
pass string "uart=232" or "uart=485" respectively in the kernel parameters.
"uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 arch/arm/mach-kirkwood/openrd-setup.c |   67 ++++++++++++++++++++++++++++++++-
 1 files changed, 66 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index ad3f1ec..fb4bfad 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -15,6 +15,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -56,16 +58,58 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
+	MPP12_SD_CLK,
+	MPP13_SD_CMD,
+	MPP14_SD_D0,
+	MPP15_SD_D1,
+	MPP16_SD_D2,
+	MPP17_SD_D3,
 	MPP29_GPIO,
 	0
 };
 
+static int sd_uart_selection(void)
+{
+	/* Parse boot_command_line string uart=no/232/485 */
+	char *ptr = strstr(boot_command_line, "uart=");
+
+	/* Default is SD. Change if required, for UART */
+	if (ptr != NULL) {
+		if (!strncmp(ptr + 5, "232", 3)) {
+			/* Configure MPP for UART */
+			openrd_mpp_config[1] = MPP13_UART1_TXD;
+			openrd_mpp_config[2] = MPP14_UART1_RXD;
+
+			return 232;
+		} else if (!strncmp(ptr + 5, "485", 3)) {
+			/* OpenRD-Base doesn't have RS485. Treat is as an
+			 * unknown argument & just have default setting -
+			 * which is SD */
+			if (machine_is_openrd_base())
+				return 0;
+
+			/* Configure MPP for UART */
+			openrd_mpp_config[1] = MPP13_UART1_TXD;
+			openrd_mpp_config[2] = MPP14_UART1_RXD;
+
+			return 485;
+		}
+	}
+	return 0;
+}
+
 static void __init openrd_init(void)
 {
+	int uart1;
+
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
 	kirkwood_init();
+
+	/* This function modifies MPP config according to boot argument */
+	uart1 = sd_uart_selection();
+
 	kirkwood_mpp_conf(openrd_mpp_config);
 
 	kirkwood_uart0_init();
@@ -77,9 +121,30 @@ static void __init openrd_init(void)
 	if (machine_is_openrd_client())
 		kirkwood_ge01_init(&openrd_ge01_data);
 	kirkwood_sata_init(&openrd_sata_data);
-	kirkwood_sdio_init(&openrd_mvsdio_data);
 
 	kirkwood_i2c_init();
+
+	if (!uart1) {
+		/* Select SD
+		 * Pin # 34: 0 => UART1, 1 => SD */
+		writel(readl(GPIO_OUT(34)) | 4, GPIO_OUT(34));
+
+		kirkwood_sdio_init(&openrd_mvsdio_data);
+	} else {
+		/* Select UART1
+		 * Pin # 34: 0 => UART1, 1 => SD */
+		writel(readl(GPIO_OUT(34)) & ~(4), GPIO_OUT(34));
+
+		/* Select RS232 OR RS485
+		 * Pin # 28: 0 => RS232, 1 => RS485 */
+		if (uart1 == 232)
+			writel(readl(GPIO_OUT(28)) & ~(0x10000000),
+				GPIO_OUT(28));
+		else
+			writel(readl(GPIO_OUT(28)) | 0x10000000, GPIO_OUT(28));
+
+		kirkwood_uart1_init();
+	}
 }
 
 static int __init openrd_pci_init(void)
-- 
1.6.6.1

-- 
_____________________________________________________________________
Disclaimer: This e-mail message and all attachments transmitted with it
are intended solely for the use of the addressee and may contain legally
privileged and confidential information. If the reader of this message
is not the intended recipient, or an employee or agent responsible for
delivering this message to the intended recipient, you are hereby
notified that any dissemination, distribution, copying, or other use of
this message or its attachments is strictly prohibited. If you have
received this message in error, please notify the sender immediately by
replying to this message and please delete it from your computer. Any
views expressed in this message are those of the individual sender
unless otherwise stated.Company has taken enough precautions to prevent
the spread of viruses. However the company accepts no liability for any
damage caused by any virus transmitted by this email.
_____________________________________________________________________
 

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset
  2010-04-20  5:51 ` Tanmay Upadhyay
@ 2010-04-30  6:49   ` Prafulla Wadaskar
  0 siblings, 0 replies; 206+ messages in thread
From: Prafulla Wadaskar @ 2010-04-30  6:49 UTC (permalink / raw)
  To: u-boot

 

> -----Original Message-----
> From: Tanmay Upadhyay [mailto:tanmay.upadhyay at einfochips.com] 
> Sent: Tuesday, April 20, 2010 11:21 AM
> To: Prafulla Wadaskar
> Cc: u-boot at lists.denx.de; Tanmay Upadhyay; Dhaval Vasa
> Subject: [PATCH] OpenRD: Bring PCIe endpoint out of reset
> 
> There exists PCIe endpoints(not all) that remains in reset state till
> PERST# line (A11 on the PCIe connector) is hold low. They come out of
> reset only when this line is high.
> 
> In case of OpenRD, this line was in tri-state. So, some of the PCIe
> devices would never appear on the PCIe bus. This patch makes PERST#
> line high while booting to bring such PCIe devices out of reset.
> 
> XGI Vollari Z11 GPU and Intel WiFi 4965 are the ones who doesn't care
> about this line. Where as Broadcom's BCM970012 won't appear 
> on the PCIe
> bus until PERST# is high. With this patch both kinds of device would
> appear on the PCIe bus.

Well, there is some problem indeed on OpenRD board regarding PCIe.
This patch did not helped me to test the hardware that I have.

I have Matrox 550 graphics card on PCIe,
I have enabled respective support in the kernel and tried to bring it up.
This patch did not helped me for successful bring up.

Whereas, if I use u-boot from official release (that comes with board) everything works fine.
And that does not have this patch.

So I think this is not perfect resolution for this problem.
We need to dig more into the issue.

Copying Simon..

Regards..
Prafulla . .

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] OpenRD: Reset PCIe endpoint while boot-up through PERST#
       [not found] <no>
                   ` (6 preceding siblings ...)
  2010-04-22 13:16 ` [PATCH] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
@ 2010-05-04 12:48 ` Tanmay Upadhyay
  2010-06-10  9:12 ` [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate Tanmay Upadhyay
                   ` (30 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-05-04 12:48 UTC (permalink / raw)
  To: u-boot

As per PCIe specifications PERST# line (A11 on the PCIe connector)
should be asserted for minimum 100us. PCIe endpoint comes out of
reset when this line is high.

In case of OpenRD, this line was in tri-state. This might prevent
PCIe devices to appear on the PCIe bus. This patch holds PERST#
line low for 100 us and then sets high while booting.

XGI Vollari Z11 GPU and Intel WiFi 4965 works fine without this fix.
Where as Broadcom's BCM970012 doesn't appear on the PCIe bus without
the fix. There might be few other devices as well which require this.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
Signed-off-by: Dhaval Vasa <dhaval.vasa@einfochips.com>
---
 board/Marvell/openrd_base/openrd_base.c |    4 ++++
 board/Marvell/openrd_base/openrd_base.h |    8 ++++----
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/board/Marvell/openrd_base/openrd_base.c b/board/Marvell/openrd_base/openrd_base.c
index c00a08a..b76047a 100644
--- a/board/Marvell/openrd_base/openrd_base.c
+++ b/board/Marvell/openrd_base/openrd_base.c
@@ -103,6 +103,10 @@ int board_init(void)
 
 	kirkwood_mpp_conf(kwmpp_config);
 
+	/* PERST# should be asserted for at least 100 us */
+	udelay(100);
+	writel(readl(KW_GPIO0_BASE) | (1<<7), KW_GPIO0_BASE);
+
 	/*
 	 * arch number of board
 	 */
diff --git a/board/Marvell/openrd_base/openrd_base.h b/board/Marvell/openrd_base/openrd_base.h
index f3daf17..1655c12 100644
--- a/board/Marvell/openrd_base/openrd_base.h
+++ b/board/Marvell/openrd_base/openrd_base.h
@@ -30,10 +30,10 @@
 #ifndef __OPENRD_BASE_H
 #define __OPENRD_BASE_H
 
-#define OPENRD_OE_LOW		(~(1<<28))        /* RS232 / RS485 */
-#define OPENRD_OE_HIGH		(~(1<<2))         /* SD / UART1 */
-#define OPENRD_OE_VAL_LOW		(0)       /* Sel RS232 */
-#define OPENRD_OE_VAL_HIGH		(1 << 2)  /* Sel SD */
+#define OPENRD_OE_LOW		(~((1<<28) | (1<<7)))  /* RS232 / RS485, PCIe */
+#define OPENRD_OE_HIGH		(~(1<<2))              /* SD / UART1 */
+#define OPENRD_OE_VAL_LOW	0             /* Sel RS232, PCIe reset */
+#define OPENRD_OE_VAL_HIGH	(1 << 2)      /* Sel SD */
 
 /* PHY related */
 #define MV88E1116_LED_FCTRL_REG		10
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
       [not found] <no>
                   ` (7 preceding siblings ...)
  2010-05-04 12:48 ` [U-Boot] [PATCH] OpenRD: Reset PCIe endpoint while boot-up through PERST# Tanmay Upadhyay
@ 2010-06-10  9:12 ` Tanmay Upadhyay
  2010-06-10  9:16   ` Simon Kagstrom
  2010-06-13 11:53   ` Albert ARIBAUD
  2010-08-10  8:29 ` [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
                   ` (29 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-06-10  9:12 UTC (permalink / raw)
  To: u-boot

This patch modifies existing OpenRD-Base support to deal with all
the three OpenRD boards (OpenRD-Base, OpenRD-Client & OpenRD-Ultimate).

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 Makefile                                |    9 +-
 arch/arm/include/asm/mach-types.h       |   13 ++
 board/Marvell/openrd/Makefile           |   65 +++++++++
 board/Marvell/openrd/config.mk          |   33 +++++
 board/Marvell/openrd/kwbimage.cfg       |  168 +++++++++++++++++++++++
 board/Marvell/openrd/openrd.c           |  180 +++++++++++++++++++++++++
 board/Marvell/openrd/openrd.h           |   67 ++++++++++
 board/Marvell/openrd_base/Makefile      |   56 --------
 board/Marvell/openrd_base/config.mk     |   33 -----
 board/Marvell/openrd_base/kwbimage.cfg  |  168 -----------------------
 board/Marvell/openrd_base/openrd_base.c |  160 ----------------------
 board/Marvell/openrd_base/openrd_base.h |   46 -------
 include/configs/openrd_client.h         |  219 +++++++++++++++++++++++++++++++
 include/configs/openrd_ultimate.h       |  219 +++++++++++++++++++++++++++++++
 14 files changed, 972 insertions(+), 464 deletions(-)
 create mode 100644 board/Marvell/openrd/Makefile
 create mode 100644 board/Marvell/openrd/config.mk
 create mode 100644 board/Marvell/openrd/kwbimage.cfg
 create mode 100644 board/Marvell/openrd/openrd.c
 create mode 100644 board/Marvell/openrd/openrd.h
 delete mode 100644 board/Marvell/openrd_base/Makefile
 delete mode 100644 board/Marvell/openrd_base/config.mk
 delete mode 100644 board/Marvell/openrd_base/kwbimage.cfg
 delete mode 100644 board/Marvell/openrd_base/openrd_base.c
 delete mode 100644 board/Marvell/openrd_base/openrd_base.h
 create mode 100644 include/configs/openrd_client.h
 create mode 100644 include/configs/openrd_ultimate.h

diff --git a/Makefile b/Makefile
index c26e491..f12214b 100644
--- a/Makefile
+++ b/Makefile
@@ -3007,8 +3007,15 @@ omap1610h2_cs_autoboot_config:	unconfig
 omap5912osk_config :	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm926ejs omap5912osk ti omap
 
+openrd_ultimate_config \
+openrd_client_config \
 openrd_base_config: unconfig
-	@$(MKCONFIG) $(@:_config=) arm arm926ejs $(@:_config=) Marvell kirkwood
+	@$(MKCONFIG) $(@:_config=) arm arm926ejs openrd Marvell kirkwood
+ifneq ($(SRCTREE),$(OBJTREE))
+	@echo "VARIANT= $(@:_config=)" >> $(OBJTREE)/include/config.mk
+else
+	@echo "VARIANT= $(@:_config=)" >> ./include/config.mk
+endif
 
 xtract_omap730p2 = $(subst _cs0boot,,$(subst _cs3boot,, $(subst _config,,$1)))
 
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
index 940d814..19114b0 100644
--- a/arch/arm/include/asm/mach-types.h
+++ b/arch/arm/include/asm/mach-types.h
@@ -2862,6 +2862,7 @@ extern unsigned int __machine_arch_type;
 #define MACH_TYPE_MATRIX518            2879
 #define MACH_TYPE_TINY_GURNARD         2880
 #define MACH_TYPE_SPEAR1310            2881
+#define MACH_TYPE_OPENRD_ULTIMATE      2884
 
 #ifdef CONFIG_ARCH_EBSA110
 # ifdef machine_arch_type
@@ -37063,6 +37064,18 @@ extern unsigned int __machine_arch_type;
 # define machine_is_spear1310()	(0)
 #endif
 
+#ifdef CONFIG_MACH_OPENRD_ULTIMATE
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type	__machine_arch_type
+# else
+#  define machine_arch_type	MACH_TYPE_OPENRD_ULTIMATE
+# endif
+# define machine_is_openrd_ultimate()	(machine_arch_type == MACH_TYPE_OPENRD_ULTIMATE)
+#else
+# define machine_is_openrd_ultimate()	(0)
+#endif
+
 /*
  * These have not yet been registered
  */
diff --git a/board/Marvell/openrd/Makefile b/board/Marvell/openrd/Makefile
new file mode 100644
index 0000000..96328e7
--- /dev/null
+++ b/board/Marvell/openrd/Makefile
@@ -0,0 +1,65 @@
+#
+# (C) Copyright 2009
+# Net Insight <www.netinsight.net>
+# Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+#
+# Based on sheevaplug:
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+include $(TOPDIR)/config.mk
+
+# Get the board variant (base/client/ultimate) from the .mk file
+ifneq ($(SRCTREE),$(OBJTREE))
+include $(OBJTREE)/include/config.mk
+else
+include $(TOPDIR)/include/config.mk
+endif
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	:= openrd.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+CFLAGS  += -D$(VARIANT)
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/Marvell/openrd/config.mk b/board/Marvell/openrd/config.mk
new file mode 100644
index 0000000..8ae355e
--- /dev/null
+++ b/board/Marvell/openrd/config.mk
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2009
+# Net Insight <www.netinsight.net>
+# Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+#
+# Based on sheevaplug:
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+TEXT_BASE = 0x00600000
+
+# Kirkwood Boot Image configuration file
+KWD_CONFIG = $(SRCTREE)/board/$(BOARDDIR)/kwbimage.cfg
diff --git a/board/Marvell/openrd/kwbimage.cfg b/board/Marvell/openrd/kwbimage.cfg
new file mode 100644
index 0000000..757eb28
--- /dev/null
+++ b/board/Marvell/openrd/kwbimage.cfg
@@ -0,0 +1,168 @@
+#
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+# Refer docs/README.kwimage for more details about how-to configure
+# and create kirkwood boot image
+#
+
+# Boot Media configurations
+BOOT_FROM	nand
+NAND_ECC_MODE	default
+NAND_PAGE_SIZE	0x0800
+
+# SOC registers configuration using bootrom header extension
+# Maximum KWBIMAGE_MAX_CONFIG configurations allowed
+
+# Configure RGMII-0 interface pad voltage to 1.8V
+DATA 0xFFD100e0 0x1b1b1b9b
+
+#Dram initalization for SINGLE x16 CL=5 @ 400MHz
+DATA 0xFFD01400 0x43000c30	# DDR Configuration register
+# bit13-0:  0xc30 (3120 DDR2 clks refresh rate)
+# bit23-14: zero
+# bit24: 1= enable exit self refresh mode on DDR access
+# bit25: 1 required
+# bit29-26: zero
+# bit31-30: 01
+
+DATA 0xFFD01404 0x37543000	# DDR Controller Control Low
+# bit 4:    0=addr/cmd in smame cycle
+# bit 5:    0=clk is driven during self refresh, we don't care for APX
+# bit 6:    0=use recommended falling edge of clk for addr/cmd
+# bit14:    0=input buffer always powered up
+# bit18:    1=cpu lock transaction enabled
+# bit23-20: 5=recommended value for CL=5 and STARTBURST_DEL disabled bit31=0
+# bit27-24: 7= CL+2, STARTBURST sample stages, for freqs 400MHz, unbuffered DIMM
+# bit30-28: 3 required
+# bit31:    0=no additional STARTBURST delay
+
+DATA 0xFFD01408 0x22125451	# DDR Timing (Low) (active cycles value +1)
+# bit3-0:   TRAS lsbs
+# bit7-4:   TRCD
+# bit11- 8: TRP
+# bit15-12: TWR
+# bit19-16: TWTR
+# bit20:    TRAS msb
+# bit23-21: 0x0
+# bit27-24: TRRD
+# bit31-28: TRTP
+
+DATA 0xFFD0140C 0x00000a33	#  DDR Timing (High)
+# bit6-0:   TRFC
+# bit8-7:   TR2R
+# bit10-9:  TR2W
+# bit12-11: TW2W
+# bit31-13: zero required
+
+DATA 0xFFD01410 0x000000cc	#  DDR Address Control
+# bit1-0:   00, Cs0width=x8
+# bit3-2:   11, Cs0size=1Gb
+# bit5-4:   00, Cs1width=x8
+# bit7-6:   11, Cs1size=1Gb
+# bit9-8:   00, Cs2width=nonexistent
+# bit11-10: 00, Cs2size =nonexistent
+# bit13-12: 00, Cs3width=nonexistent
+# bit15-14: 00, Cs3size =nonexistent
+# bit16:    0,  Cs0AddrSel
+# bit17:    0,  Cs1AddrSel
+# bit18:    0,  Cs2AddrSel
+# bit19:    0,  Cs3AddrSel
+# bit31-20: 0 required
+
+DATA 0xFFD01414 0x00000000	#  DDR Open Pages Control
+# bit0:    0,  OpenPage enabled
+# bit31-1: 0 required
+
+DATA 0xFFD01418 0x00000000	#  DDR Operation
+# bit3-0:   0x0, DDR cmd
+# bit31-4:  0 required
+
+DATA 0xFFD0141C 0x00000C52	#  DDR Mode
+# bit2-0:   2, BurstLen=2 required
+# bit3:     0, BurstType=0 required
+# bit6-4:   4, CL=5
+# bit7:     0, TestMode=0 normal
+# bit8:     0, DLL reset=0 normal
+# bit11-9:  6, auto-precharge write recovery ????????????
+# bit12:    0, PD must be zero
+# bit31-13: 0 required
+
+DATA 0xFFD01420 0x00000042	#  DDR Extended Mode
+# bit0:    0,  DDR DLL enabled
+# bit1:    1,  DDR drive strength reduced
+# bit2:    0,  DDR ODT control lsd (disabled)
+# bit5-3:  000, required
+# bit6:    1,  DDR ODT control msb, (disabled)
+# bit9-7:  000, required
+# bit10:   0,  differential DQS enabled
+# bit11:   0, required
+# bit12:   0, DDR output buffer enabled
+# bit31-13: 0 required
+
+DATA 0xFFD01424 0x0000F17F	#  DDR Controller Control High
+# bit2-0:  111, required
+# bit3  :  1  , MBUS Burst Chop disabled
+# bit6-4:  111, required
+# bit7  :  0
+# bit8  :  1  , add writepath sample stage, must be 1 for DDR freq >= 300MHz
+# bit9  :  0  , no half clock cycle addition to dataout
+# bit10 :  0  , 1/4 clock cycle skew enabled for addr/ctl signals
+# bit11 :  0  , 1/4 clock cycle skew disabled for write mesh
+# bit15-12: 1111 required
+# bit31-16: 0    required
+
+DATA 0xFFD01428 0x00085520	# DDR2 ODT Read Timing (default values)
+DATA 0xFFD0147C 0x00008552	# DDR2 ODT Write Timing (default values)
+
+DATA 0xFFD01500 0x00000000	# CS[0]n Base address to 0x0
+DATA 0xFFD01504 0x0FFFFFF1	# CS[0]n Size
+# bit0:    1,  Window enabled
+# bit1:    0,  Write Protect disabled
+# bit3-2:  00, CS0 hit selected
+# bit23-4: ones, required
+# bit31-24: 0x0F, Size (i.e. 256MB)
+
+DATA 0xFFD01508 0x10000000	# CS[1]n Base address to 256Mb
+DATA 0xFFD0150C 0x0FFFFFF5	# CS[1]n Size 256Mb Window enabled for CS1
+
+DATA 0xFFD01514 0x00000000	# CS[2]n Size, window disabled
+DATA 0xFFD0151C 0x00000000	# CS[3]n Size, window disabled
+
+DATA 0xFFD01494 0x00120012	#  DDR ODT Control (Low)
+# bit3-0:   0010, (read) M_ODT[0] is asserted during read from DRAM CS1
+# bit7-4:   0001, (read) M_ODT[1] is asserted during read from DRAM CS0
+# bit19-16: 0010, (write) M_ODT[0] is asserted during write to DRAM CS1.
+# bit23-20: 0001, (write) M_ODT[1] is asserted during write to DRAM CS0.
+DATA 0xFFD01498 0x00000000	#  DDR ODT Control (High)
+
+DATA 0xFFD0149C 0x0000E40f	# CPU ODT Control
+# bit3-0:    1111, internal ODT is asserted during read from DRAM bank 0-3
+# bit11-10:    01, M_DQ, M_DM, and M_DQS I/O buffer ODT Select: 150 ohm
+# bit13-12:    10, M_STARTBURST_IN I/O buffer ODT Select: 75 ohm
+# bit14:        1, M_STARTBURST_IN ODT: Enabled
+# bit15:        1, DDR IO ODT Unit: Use ODT block
+DATA 0xFFD01480 0x00000001	# DDR Initialization Control
+#bit0=1, enable DDR init upon this register write
+
+# End of Header extension
+DATA 0x0 0x0
diff --git a/board/Marvell/openrd/openrd.c b/board/Marvell/openrd/openrd.c
new file mode 100644
index 0000000..0630947
--- /dev/null
+++ b/board/Marvell/openrd/openrd.c
@@ -0,0 +1,180 @@
+/*
+ * Modified Simon's work to deal with all the three variants of
+ * OpenRD boards (OpenRD-Base, OpenRD-Client & OpenRD-Ultimate)
+ *
+ * eInfochips <www.einfochips.com>
+ * Modified-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
+ *
+ * (C) Copyright 2009
+ * Net Insight <www.netinsight.net>
+ * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+ *
+ * Based on sheevaplug.c:
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/arch/kirkwood.h>
+#include <asm/arch/mpp.h>
+#include "openrd.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	/*
+	 * default gpio configuration
+	 * There are maximum 64 gpios controlled through 2 sets of registers
+	 * the  below configuration configures mainly initial LED status
+	 */
+	kw_config_gpio(OPENRD_OE_VAL_LOW,
+			OPENRD_OE_VAL_HIGH,
+			OPENRD_OE_LOW, OPENRD_OE_HIGH);
+
+	/* Multi-Purpose Pins Functionality configuration */
+	u32 kwmpp_config[] = {
+		MPP0_NF_IO2,
+		MPP1_NF_IO3,
+		MPP2_NF_IO4,
+		MPP3_NF_IO5,
+		MPP4_NF_IO6,
+		MPP5_NF_IO7,
+		MPP6_SYSRST_OUTn,
+		MPP7_GPO,
+		MPP8_TW_SDA,
+		MPP9_TW_SCK,
+		MPP10_UART0_TXD,
+		MPP11_UART0_RXD,
+		MPP12_SD_CLK,
+		MPP13_SD_CMD, /* Alt UART1_TXD */
+		MPP14_SD_D0,  /* Alt UART1_RXD */
+		MPP15_SD_D1,
+		MPP16_SD_D2,
+		MPP17_SD_D3,
+		MPP18_NF_IO0,
+		MPP19_NF_IO1,
+		MPP20_GE1_0,
+		MPP21_GE1_1,
+		MPP22_GE1_2,
+		MPP23_GE1_3,
+		MPP24_GE1_4,
+		MPP25_GE1_5,
+		MPP26_GE1_6,
+		MPP27_GE1_7,
+		MPP28_GPIO,
+		MPP29_TSMP9,
+		MPP30_GE1_10,
+		MPP31_GE1_11,
+		MPP32_GE1_12,
+		MPP33_GE1_13,
+		MPP34_GPIO,   /* UART1 / SD sel */
+		MPP35_TDM_CH0_TX_QL,
+		MPP36_TDM_SPI_CS1,
+		MPP37_TDM_CH2_TX_QL,
+		MPP38_TDM_CH2_RX_QL,
+		MPP39_AUDIO_I2SBCLK,
+		MPP40_AUDIO_I2SDO,
+		MPP41_AUDIO_I2SLRC,
+		MPP42_AUDIO_I2SMCLK,
+		MPP43_AUDIO_I2SDI,
+		MPP44_AUDIO_EXTCLK,
+		MPP45_TDM_PCLK,
+		MPP46_TDM_FS,
+		MPP47_TDM_DRX,
+		MPP48_TDM_DTX,
+		MPP49_TDM_CH0_RX_QL,
+		0
+	};
+
+	kirkwood_mpp_conf(kwmpp_config);
+
+	/*
+	 * arch number of board
+	 */
+	gd->bd->bi_arch_number = MACH_TYPE_OPENRD;
+
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+	return 0;
+}
+
+int dram_init(void)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		gd->bd->bi_dram[i].start = kw_sdram_bar(i);
+		gd->bd->bi_dram[i].size = kw_sdram_bs(i);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_RESET_PHY_R
+/* Configure and enable MV88E1116/MV88E1121 PHY */
+void mv_phy_init(char *name)
+{
+	u16 reg;
+	u16 devadr;
+
+	if (miiphy_set_current_dev(name))
+		return;
+
+	/* command to read PHY dev address */
+	if (miiphy_read(name, 0xEE, 0xEE, (u16 *) &devadr)) {
+		printf("Err..%s could not read PHY dev address\n", __func__);
+		return;
+	}
+
+	/*
+	 * Enable RGMII delay on Tx and Rx for CPU port
+	 * Ref: sec 4.7.2 of chip datasheet
+	 */
+	miiphy_write(name, devadr, PGADR_REG, 2);
+	miiphy_read(name, devadr, MAC_CTRL_REG, &reg);
+	reg |= (RGMII_RXTM_CTRL | RGMII_TXTM_CTRL);
+	miiphy_write(name, devadr, MAC_CTRL_REG, reg);
+	miiphy_write(name, devadr, PGADR_REG, 0);
+
+	/* reset the phy */
+	if (!miiphy_reset(name, devadr))
+		printf("%s Initialized on %s\n", PHY_NO, name);
+}
+
+void reset_phy(void)
+{
+	mv_phy_init("egiga0");
+
+#ifdef openrd_client
+	/* Kirkwood ethernet driver is written with the assumption that in case
+	 * of multiple PHYs, their addresses are consecutive. But unfortunately
+	 * in case of OpenRD-Client, PHY addresses are not consecutive.*/
+	miiphy_write("egiga1", 0xEE, 0xEE, 24);
+#endif
+
+#if defined(openrd_client) || defined(openrd_ultimate)
+	/* configure and initialize both PHY's */
+	mv_phy_init("egiga1");
+#endif
+}
+#endif /* CONFIG_RESET_PHY_R */
diff --git a/board/Marvell/openrd/openrd.h b/board/Marvell/openrd/openrd.h
new file mode 100644
index 0000000..8b0cbf8
--- /dev/null
+++ b/board/Marvell/openrd/openrd.h
@@ -0,0 +1,67 @@
+/*
+ * Modified Simon's work to deal with all the three variants of
+ * OpenRD boards (OpenRD-Base, OpenRD-Client & OpenRD-Ultimate)
+ *
+ * eInfochips <www.einfochips.com>
+ * Modified-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
+ *
+ * (C) Copyright 2009
+ * Net Insight <www.netinsight.net>
+ * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+ *
+ * Based on sheevaplug.h:
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __OPENRD_H
+#define __OPENRD_H
+
+#define OPENRD_OE_LOW		(~(1<<28))        /* RS232 / RS485 */
+#define OPENRD_OE_HIGH		(~(1<<2))         /* SD / UART1 */
+#define OPENRD_OE_VAL_LOW		(0)       /* Sel RS232 */
+#define OPENRD_OE_VAL_HIGH		(1 << 2)  /* Sel SD */
+
+/* PHY related */
+#define MAC_CTRL_REG		21
+#define PGADR_REG		22
+#define RGMII_TXTM_CTRL		(1 << 4)
+#define RGMII_RXTM_CTRL		(1 << 5)
+
+#ifdef openrd_base
+#define MACH_TYPE_OPENRD MACH_TYPE_OPENRD_BASE
+#endif
+
+#ifdef openrd_client
+#define MACH_TYPE_OPENRD MACH_TYPE_OPENRD_CLIENT
+#endif
+
+#ifdef openrd_ultimate
+#define MACH_TYPE_OPENRD MACH_TYPE_OPENRD_ULTIMATE
+/* OpenRD-Ultimate uses 88E1121 PHY */
+#define PHY_NO          "88E1121"
+#else
+/* OpenRD-Base & OpenRD-Client uses 88E1116 PHY */
+#define PHY_NO          "88E1116"
+#endif
+
+#endif /* __OPENRD_H */
diff --git a/board/Marvell/openrd_base/Makefile b/board/Marvell/openrd_base/Makefile
deleted file mode 100644
index 3ef0b9b..0000000
--- a/board/Marvell/openrd_base/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# (C) Copyright 2009
-# Net Insight <www.netinsight.net>
-# Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
-#
-# Based on sheevaplug:
-# (C) Copyright 2009
-# Marvell Semiconductor <www.marvell.com>
-# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301 USA
-#
-
-include $(TOPDIR)/config.mk
-
-LIB	= $(obj)lib$(BOARD).a
-
-COBJS	:= openrd_base.o
-
-SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS	:= $(addprefix $(obj),$(COBJS))
-SOBJS	:= $(addprefix $(obj),$(SOBJS))
-
-$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
-	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
-
-clean:
-	rm -f $(SOBJS) $(OBJS)
-
-distclean:	clean
-	rm -f $(LIB) core *.bak .depend
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
diff --git a/board/Marvell/openrd_base/config.mk b/board/Marvell/openrd_base/config.mk
deleted file mode 100644
index 8ae355e..0000000
--- a/board/Marvell/openrd_base/config.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# (C) Copyright 2009
-# Net Insight <www.netinsight.net>
-# Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
-#
-# Based on sheevaplug:
-# (C) Copyright 2009
-# Marvell Semiconductor <www.marvell.com>
-# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301 USA
-#
-
-TEXT_BASE = 0x00600000
-
-# Kirkwood Boot Image configuration file
-KWD_CONFIG = $(SRCTREE)/board/$(BOARDDIR)/kwbimage.cfg
diff --git a/board/Marvell/openrd_base/kwbimage.cfg b/board/Marvell/openrd_base/kwbimage.cfg
deleted file mode 100644
index 757eb28..0000000
--- a/board/Marvell/openrd_base/kwbimage.cfg
+++ /dev/null
@@ -1,168 +0,0 @@
-#
-# (C) Copyright 2009
-# Marvell Semiconductor <www.marvell.com>
-# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301 USA
-#
-# Refer docs/README.kwimage for more details about how-to configure
-# and create kirkwood boot image
-#
-
-# Boot Media configurations
-BOOT_FROM	nand
-NAND_ECC_MODE	default
-NAND_PAGE_SIZE	0x0800
-
-# SOC registers configuration using bootrom header extension
-# Maximum KWBIMAGE_MAX_CONFIG configurations allowed
-
-# Configure RGMII-0 interface pad voltage to 1.8V
-DATA 0xFFD100e0 0x1b1b1b9b
-
-#Dram initalization for SINGLE x16 CL=5 @ 400MHz
-DATA 0xFFD01400 0x43000c30	# DDR Configuration register
-# bit13-0:  0xc30 (3120 DDR2 clks refresh rate)
-# bit23-14: zero
-# bit24: 1= enable exit self refresh mode on DDR access
-# bit25: 1 required
-# bit29-26: zero
-# bit31-30: 01
-
-DATA 0xFFD01404 0x37543000	# DDR Controller Control Low
-# bit 4:    0=addr/cmd in smame cycle
-# bit 5:    0=clk is driven during self refresh, we don't care for APX
-# bit 6:    0=use recommended falling edge of clk for addr/cmd
-# bit14:    0=input buffer always powered up
-# bit18:    1=cpu lock transaction enabled
-# bit23-20: 5=recommended value for CL=5 and STARTBURST_DEL disabled bit31=0
-# bit27-24: 7= CL+2, STARTBURST sample stages, for freqs 400MHz, unbuffered DIMM
-# bit30-28: 3 required
-# bit31:    0=no additional STARTBURST delay
-
-DATA 0xFFD01408 0x22125451	# DDR Timing (Low) (active cycles value +1)
-# bit3-0:   TRAS lsbs
-# bit7-4:   TRCD
-# bit11- 8: TRP
-# bit15-12: TWR
-# bit19-16: TWTR
-# bit20:    TRAS msb
-# bit23-21: 0x0
-# bit27-24: TRRD
-# bit31-28: TRTP
-
-DATA 0xFFD0140C 0x00000a33	#  DDR Timing (High)
-# bit6-0:   TRFC
-# bit8-7:   TR2R
-# bit10-9:  TR2W
-# bit12-11: TW2W
-# bit31-13: zero required
-
-DATA 0xFFD01410 0x000000cc	#  DDR Address Control
-# bit1-0:   00, Cs0width=x8
-# bit3-2:   11, Cs0size=1Gb
-# bit5-4:   00, Cs1width=x8
-# bit7-6:   11, Cs1size=1Gb
-# bit9-8:   00, Cs2width=nonexistent
-# bit11-10: 00, Cs2size =nonexistent
-# bit13-12: 00, Cs3width=nonexistent
-# bit15-14: 00, Cs3size =nonexistent
-# bit16:    0,  Cs0AddrSel
-# bit17:    0,  Cs1AddrSel
-# bit18:    0,  Cs2AddrSel
-# bit19:    0,  Cs3AddrSel
-# bit31-20: 0 required
-
-DATA 0xFFD01414 0x00000000	#  DDR Open Pages Control
-# bit0:    0,  OpenPage enabled
-# bit31-1: 0 required
-
-DATA 0xFFD01418 0x00000000	#  DDR Operation
-# bit3-0:   0x0, DDR cmd
-# bit31-4:  0 required
-
-DATA 0xFFD0141C 0x00000C52	#  DDR Mode
-# bit2-0:   2, BurstLen=2 required
-# bit3:     0, BurstType=0 required
-# bit6-4:   4, CL=5
-# bit7:     0, TestMode=0 normal
-# bit8:     0, DLL reset=0 normal
-# bit11-9:  6, auto-precharge write recovery ????????????
-# bit12:    0, PD must be zero
-# bit31-13: 0 required
-
-DATA 0xFFD01420 0x00000042	#  DDR Extended Mode
-# bit0:    0,  DDR DLL enabled
-# bit1:    1,  DDR drive strength reduced
-# bit2:    0,  DDR ODT control lsd (disabled)
-# bit5-3:  000, required
-# bit6:    1,  DDR ODT control msb, (disabled)
-# bit9-7:  000, required
-# bit10:   0,  differential DQS enabled
-# bit11:   0, required
-# bit12:   0, DDR output buffer enabled
-# bit31-13: 0 required
-
-DATA 0xFFD01424 0x0000F17F	#  DDR Controller Control High
-# bit2-0:  111, required
-# bit3  :  1  , MBUS Burst Chop disabled
-# bit6-4:  111, required
-# bit7  :  0
-# bit8  :  1  , add writepath sample stage, must be 1 for DDR freq >= 300MHz
-# bit9  :  0  , no half clock cycle addition to dataout
-# bit10 :  0  , 1/4 clock cycle skew enabled for addr/ctl signals
-# bit11 :  0  , 1/4 clock cycle skew disabled for write mesh
-# bit15-12: 1111 required
-# bit31-16: 0    required
-
-DATA 0xFFD01428 0x00085520	# DDR2 ODT Read Timing (default values)
-DATA 0xFFD0147C 0x00008552	# DDR2 ODT Write Timing (default values)
-
-DATA 0xFFD01500 0x00000000	# CS[0]n Base address to 0x0
-DATA 0xFFD01504 0x0FFFFFF1	# CS[0]n Size
-# bit0:    1,  Window enabled
-# bit1:    0,  Write Protect disabled
-# bit3-2:  00, CS0 hit selected
-# bit23-4: ones, required
-# bit31-24: 0x0F, Size (i.e. 256MB)
-
-DATA 0xFFD01508 0x10000000	# CS[1]n Base address to 256Mb
-DATA 0xFFD0150C 0x0FFFFFF5	# CS[1]n Size 256Mb Window enabled for CS1
-
-DATA 0xFFD01514 0x00000000	# CS[2]n Size, window disabled
-DATA 0xFFD0151C 0x00000000	# CS[3]n Size, window disabled
-
-DATA 0xFFD01494 0x00120012	#  DDR ODT Control (Low)
-# bit3-0:   0010, (read) M_ODT[0] is asserted during read from DRAM CS1
-# bit7-4:   0001, (read) M_ODT[1] is asserted during read from DRAM CS0
-# bit19-16: 0010, (write) M_ODT[0] is asserted during write to DRAM CS1.
-# bit23-20: 0001, (write) M_ODT[1] is asserted during write to DRAM CS0.
-DATA 0xFFD01498 0x00000000	#  DDR ODT Control (High)
-
-DATA 0xFFD0149C 0x0000E40f	# CPU ODT Control
-# bit3-0:    1111, internal ODT is asserted during read from DRAM bank 0-3
-# bit11-10:    01, M_DQ, M_DM, and M_DQS I/O buffer ODT Select: 150 ohm
-# bit13-12:    10, M_STARTBURST_IN I/O buffer ODT Select: 75 ohm
-# bit14:        1, M_STARTBURST_IN ODT: Enabled
-# bit15:        1, DDR IO ODT Unit: Use ODT block
-DATA 0xFFD01480 0x00000001	# DDR Initialization Control
-#bit0=1, enable DDR init upon this register write
-
-# End of Header extension
-DATA 0x0 0x0
diff --git a/board/Marvell/openrd_base/openrd_base.c b/board/Marvell/openrd_base/openrd_base.c
deleted file mode 100644
index c00a08a..0000000
--- a/board/Marvell/openrd_base/openrd_base.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * (C) Copyright 2009
- * Net Insight <www.netinsight.net>
- * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
- *
- * Based on sheevaplug.c:
- * (C) Copyright 2009
- * Marvell Semiconductor <www.marvell.com>
- * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <common.h>
-#include <miiphy.h>
-#include <asm/arch/kirkwood.h>
-#include <asm/arch/mpp.h>
-#include "openrd_base.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-int board_init(void)
-{
-	/*
-	 * default gpio configuration
-	 * There are maximum 64 gpios controlled through 2 sets of registers
-	 * the  below configuration configures mainly initial LED status
-	 */
-	kw_config_gpio(OPENRD_OE_VAL_LOW,
-			OPENRD_OE_VAL_HIGH,
-			OPENRD_OE_LOW, OPENRD_OE_HIGH);
-
-	/* Multi-Purpose Pins Functionality configuration */
-	u32 kwmpp_config[] = {
-		MPP0_NF_IO2,
-		MPP1_NF_IO3,
-		MPP2_NF_IO4,
-		MPP3_NF_IO5,
-		MPP4_NF_IO6,
-		MPP5_NF_IO7,
-		MPP6_SYSRST_OUTn,
-		MPP7_GPO,
-		MPP8_TW_SDA,
-		MPP9_TW_SCK,
-		MPP10_UART0_TXD,
-		MPP11_UART0_RXD,
-		MPP12_SD_CLK,
-		MPP13_SD_CMD, /* Alt UART1_TXD */
-		MPP14_SD_D0,  /* Alt UART1_RXD */
-		MPP15_SD_D1,
-		MPP16_SD_D2,
-		MPP17_SD_D3,
-		MPP18_NF_IO0,
-		MPP19_NF_IO1,
-		MPP20_GE1_0,
-		MPP21_GE1_1,
-		MPP22_GE1_2,
-		MPP23_GE1_3,
-		MPP24_GE1_4,
-		MPP25_GE1_5,
-		MPP26_GE1_6,
-		MPP27_GE1_7,
-		MPP28_GPIO,
-		MPP29_TSMP9,
-		MPP30_GE1_10,
-		MPP31_GE1_11,
-		MPP32_GE1_12,
-		MPP33_GE1_13,
-		MPP34_GPIO,   /* UART1 / SD sel */
-		MPP35_TDM_CH0_TX_QL,
-		MPP36_TDM_SPI_CS1,
-		MPP37_TDM_CH2_TX_QL,
-		MPP38_TDM_CH2_RX_QL,
-		MPP39_AUDIO_I2SBCLK,
-		MPP40_AUDIO_I2SDO,
-		MPP41_AUDIO_I2SLRC,
-		MPP42_AUDIO_I2SMCLK,
-		MPP43_AUDIO_I2SDI,
-		MPP44_AUDIO_EXTCLK,
-		MPP45_TDM_PCLK,
-		MPP46_TDM_FS,
-		MPP47_TDM_DRX,
-		MPP48_TDM_DTX,
-		MPP49_TDM_CH0_RX_QL,
-		0
-	};
-
-	kirkwood_mpp_conf(kwmpp_config);
-
-	/*
-	 * arch number of board
-	 */
-	gd->bd->bi_arch_number = MACH_TYPE_OPENRD_BASE;
-
-	/* adress of boot parameters */
-	gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
-	return 0;
-}
-
-int dram_init(void)
-{
-	int i;
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-		gd->bd->bi_dram[i].start = kw_sdram_bar(i);
-		gd->bd->bi_dram[i].size = kw_sdram_bs(i);
-	}
-	return 0;
-}
-
-#ifdef CONFIG_RESET_PHY_R
-/* Configure and enable MV88E1116 PHY */
-void reset_phy(void)
-{
-	u16 reg;
-	u16 devadr;
-	char *name = "egiga0";
-
-	if (miiphy_set_current_dev(name))
-		return;
-
-	/* command to read PHY dev address */
-	if (miiphy_read(name, 0xEE, 0xEE, (u16 *) &devadr)) {
-		printf("Err..%s could not read PHY dev address\n",
-			__FUNCTION__);
-		return;
-	}
-
-	/*
-	 * Enable RGMII delay on Tx and Rx for CPU port
-	 * Ref: sec 4.7.2 of chip datasheet
-	 */
-	miiphy_write(name, devadr, MV88E1116_PGADR_REG, 2);
-	miiphy_read(name, devadr, MV88E1116_MAC_CTRL_REG, &reg);
-	reg |= (MV88E1116_RGMII_RXTM_CTRL | MV88E1116_RGMII_TXTM_CTRL);
-	miiphy_write(name, devadr, MV88E1116_MAC_CTRL_REG, reg);
-	miiphy_write(name, devadr, MV88E1116_PGADR_REG, 0);
-
-	/* reset the phy */
-	miiphy_reset(name, devadr);
-
-	printf("88E1116 Initialized on %s\n", name);
-}
-#endif /* CONFIG_RESET_PHY_R */
diff --git a/board/Marvell/openrd_base/openrd_base.h b/board/Marvell/openrd_base/openrd_base.h
deleted file mode 100644
index f3daf17..0000000
--- a/board/Marvell/openrd_base/openrd_base.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * (C) Copyright 2009
- * Net Insight <www.netinsight.net>
- * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
- *
- * Based on sheevaplug.h:
- * (C) Copyright 2009
- * Marvell Semiconductor <www.marvell.com>
- * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#ifndef __OPENRD_BASE_H
-#define __OPENRD_BASE_H
-
-#define OPENRD_OE_LOW		(~(1<<28))        /* RS232 / RS485 */
-#define OPENRD_OE_HIGH		(~(1<<2))         /* SD / UART1 */
-#define OPENRD_OE_VAL_LOW		(0)       /* Sel RS232 */
-#define OPENRD_OE_VAL_HIGH		(1 << 2)  /* Sel SD */
-
-/* PHY related */
-#define MV88E1116_LED_FCTRL_REG		10
-#define MV88E1116_CPRSP_CR3_REG		21
-#define MV88E1116_MAC_CTRL_REG		21
-#define MV88E1116_PGADR_REG		22
-#define MV88E1116_RGMII_TXTM_CTRL	(1 << 4)
-#define MV88E1116_RGMII_RXTM_CTRL	(1 << 5)
-
-#endif /* __OPENRD_BASE_H */
diff --git a/include/configs/openrd_client.h b/include/configs/openrd_client.h
new file mode 100644
index 0000000..d936ffa
--- /dev/null
+++ b/include/configs/openrd_client.h
@@ -0,0 +1,219 @@
+/*
+ * (C) Copyright 2009
+ * Net Insight <www.netinsight.net>
+ * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+ *
+ * Based on sheevaplug.h:
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef _CONFIG_OPENRD_CLIENT_H
+#define _CONFIG_OPENRD_CLIENT_H
+
+/*
+ * Version number information
+ */
+#define CONFIG_IDENT_STRING	"\nOpenRD-Client"
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_MARVELL		1
+#define CONFIG_ARM926EJS	1	/* Basic Architecture */
+#define CONFIG_SHEEVA_88SV131	1	/* CPU Core subversion */
+#define CONFIG_KIRKWOOD		1	/* SOC Family Name */
+#define CONFIG_KW88F6281	1	/* SOC Name */
+#define CONFIG_MACH_OPENRD_CLIENT	/* Machine type */
+
+#define CONFIG_MD5	/* get_random_hex on krikwood needs MD5 support */
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+#define CONFIG_KIRKWOOD_EGIGA_INIT	/* Enable GbePort0/1 for kernel */
+#define CONFIG_KIRKWOOD_RGMII_PAD_1V8	/* Set RGMII Pad voltage to 1.8V */
+#define CONFIG_KIRKWOOD_PCIE_INIT       /* Enable PCIE Port0 for kernel */
+
+/*
+ * CLKs configurations
+ */
+#define CONFIG_SYS_HZ		1000
+
+/*
+ * NS16550 Configuration
+ */
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
+#define CONFIG_SYS_NS16550_CLK		CONFIG_SYS_TCLK
+#define CONFIG_SYS_NS16550_COM1		KW_UART0_BASE
+
+/*
+ * Serial Port configuration
+ * The following definitions let you select what serial you want to use
+ * for your console driver.
+ */
+
+#define CONFIG_CONS_INDEX	1	/*Console on UART0 */
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, \
+					  115200, 230400, 460800, 921600 }
+/* auto boot */
+#define CONFIG_BOOTDELAY	3	/* default enable autoboot */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_CMDLINE_TAG	1	/* enable passing of ATAGs  */
+#define CONFIG_INITRD_TAG	1	/* enable INITRD tag */
+#define CONFIG_SETUP_MEMORY_TAGS 1	/* enable memory tag */
+
+#define	CONFIG_SYS_PROMPT	"Marvell>> "	/* Command Prompt */
+#define	CONFIG_SYS_CBSIZE	1024	/* Console I/O Buff Size */
+#define	CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE \
+		+sizeof(CONFIG_SYS_PROMPT) + 16)	/* Print Buff */
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_AUTOSCRIPT
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_USB
+
+/*
+ * NAND configuration
+ */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_NAND_KIRKWOOD
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define NAND_MAX_CHIPS			1
+#define CONFIG_SYS_NAND_BASE		0xD8000000	/* KW_DEFADR_NANDF */
+#define NAND_ALLOW_ERASE_ALL		1
+#endif
+
+/*
+ *  Environment variables configurations
+ */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_ENV_IS_IN_NAND		1
+#define CONFIG_ENV_SECT_SIZE		0x20000	/* 128K */
+#else
+#define CONFIG_ENV_IS_NOWHERE		1	/* if env in SDRAM */
+#endif
+/*
+ * max 4k env size is enough, but in case of nand
+ * it has to be rounded to sector size
+ */
+#define CONFIG_ENV_SIZE			0x20000	/* 128k */
+#define CONFIG_ENV_ADDR			0x60000
+#define CONFIG_ENV_OFFSET		0x60000	/* env starts here */
+
+/*
+ * Default environment variables
+ */
+#define CONFIG_BOOTCOMMAND		"${x_bootcmd_kernel}; "	\
+	"setenv bootargs ${x_bootargs} ${x_bootargs_root}; "	\
+	"${x_bootcmd_usb}; bootm 0x6400000;"
+
+#define MTDIDS_DEFAULT		"nand0=nand_mtd"
+#define MTDPARTS_DEFAULT	"mtdparts=nand_mtd:0x100000 at 0x000000(uboot),"\
+	"0x400000 at 0x100000(uImage),"\
+	"0x1fb00000 at 0x500000(rootfs)"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	"x_bootargs=console"		\
+	"=ttyS0,115200 "MTDPARTS_DEFAULT " rw ubi.mtd=2,2048\0"		\
+	"x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0"	\
+	"x_bootcmd_usb=usb start\0"					\
+	"x_bootargs_root=root=ubi0:rootfs rootfstype=ubifs\0"		\
+	"mtdids="MTDIDS_DEFAULT"\0"					\
+	"mtdparts="MTDPARTS_DEFAULT"\0"
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN	(1024 * 1024) /* 1MiB for malloc() */
+/* size in bytes reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+
+/*
+ * Other required minimal configurations
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_ARCH_CPU_INIT	/* call arch_cpu_init() */
+#define CONFIG_ARCH_MISC_INIT	/* call arch_misc_init() */
+#define CONFIG_DISPLAY_CPUINFO	/* Display cpu info */
+#define CONFIG_NR_DRAM_BANKS	4
+#define CONFIG_STACKSIZE	0x00100000	/* regular stack- 1M */
+#define CONFIG_SYS_LOAD_ADDR	0x00800000	/* default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00400000	/* 4M */
+#define CONFIG_SYS_MEMTEST_END	0x007fffff	/*(_8M -1) */
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000	/* Rst Vector Adr */
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+
+/*
+ * Ethernet Driver configuration
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_NETCONSOLE	/* include NetConsole support   */
+#define CONFIG_NET_MULTI	/* specify more that one ports available */
+#define	CONFIG_MII		/* expose smi ove miiphy interface */
+#define CONFIG_KIRKWOOD_EGIGA	/* Enable kirkwood Gbe Controller Driver */
+#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN	/* detect link using phy */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS	{1, 1}
+#define CONFIG_PHY_BASE_ADR	0x8
+#define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
+#define CONFIG_RESET_PHY_R	/* use reset_phy() to init mv8831116 PHY */
+#endif /* CONFIG_CMD_NET */
+
+/*
+ * USB/EHCI
+ */
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_EHCI			/* Enable EHCI USB support */
+#define CONFIG_USB_EHCI_KIRKWOOD	/* on Kirkwood platform	*/
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+#define CONFIG_DOS_PARTITION
+#define CONFIG_ISO_PARTITION
+#define CONFIG_SUPPORT_VFAT
+#endif /* CONFIG_CMD_USB */
+
+/*
+ * File system
+ */
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_RBTREE
+#define CONFIG_MTD_DEVICE               /* needed for mtdparts commands */
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_LZO
+
+#endif /* _CONFIG_OPENRD_CLIENT_H */
diff --git a/include/configs/openrd_ultimate.h b/include/configs/openrd_ultimate.h
new file mode 100644
index 0000000..a0e0417
--- /dev/null
+++ b/include/configs/openrd_ultimate.h
@@ -0,0 +1,219 @@
+/*
+ * (C) Copyright 2009
+ * Net Insight <www.netinsight.net>
+ * Written-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
+ *
+ * Based on sheevaplug.h:
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef _CONFIG_OPENRD_ULTIMATE_H
+#define _CONFIG_OPENRD_ULTIMATE_H
+
+/*
+ * Version number information
+ */
+#define CONFIG_IDENT_STRING	"\nOpenRD-Ultimate"
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_MARVELL		1
+#define CONFIG_ARM926EJS	1	/* Basic Architecture */
+#define CONFIG_SHEEVA_88SV131	1	/* CPU Core subversion */
+#define CONFIG_KIRKWOOD		1	/* SOC Family Name */
+#define CONFIG_KW88F6281	1	/* SOC Name */
+#define CONFIG_MACH_OPENRD_ULTIMATE	/* Machine type */
+
+#define CONFIG_MD5	/* get_random_hex on krikwood needs MD5 support */
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+#define CONFIG_KIRKWOOD_EGIGA_INIT	/* Enable GbePort0/1 for kernel */
+#define CONFIG_KIRKWOOD_RGMII_PAD_1V8	/* Set RGMII Pad voltage to 1.8V */
+#define CONFIG_KIRKWOOD_PCIE_INIT       /* Enable PCIE Port0 for kernel */
+
+/*
+ * CLKs configurations
+ */
+#define CONFIG_SYS_HZ		1000
+
+/*
+ * NS16550 Configuration
+ */
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
+#define CONFIG_SYS_NS16550_CLK		CONFIG_SYS_TCLK
+#define CONFIG_SYS_NS16550_COM1		KW_UART0_BASE
+
+/*
+ * Serial Port configuration
+ * The following definitions let you select what serial you want to use
+ * for your console driver.
+ */
+
+#define CONFIG_CONS_INDEX	1	/*Console on UART0 */
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, \
+					  115200, 230400, 460800, 921600 }
+/* auto boot */
+#define CONFIG_BOOTDELAY	3	/* default enable autoboot */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_CMDLINE_TAG	1	/* enable passing of ATAGs  */
+#define CONFIG_INITRD_TAG	1	/* enable INITRD tag */
+#define CONFIG_SETUP_MEMORY_TAGS 1	/* enable memory tag */
+
+#define	CONFIG_SYS_PROMPT	"Marvell>> "	/* Command Prompt */
+#define	CONFIG_SYS_CBSIZE	1024	/* Console I/O Buff Size */
+#define	CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE \
+		+sizeof(CONFIG_SYS_PROMPT) + 16)	/* Print Buff */
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_AUTOSCRIPT
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_USB
+
+/*
+ * NAND configuration
+ */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_NAND_KIRKWOOD
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define NAND_MAX_CHIPS			1
+#define CONFIG_SYS_NAND_BASE		0xD8000000	/* KW_DEFADR_NANDF */
+#define NAND_ALLOW_ERASE_ALL		1
+#endif
+
+/*
+ *  Environment variables configurations
+ */
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_ENV_IS_IN_NAND		1
+#define CONFIG_ENV_SECT_SIZE		0x20000	/* 128K */
+#else
+#define CONFIG_ENV_IS_NOWHERE		1	/* if env in SDRAM */
+#endif
+/*
+ * max 4k env size is enough, but in case of nand
+ * it has to be rounded to sector size
+ */
+#define CONFIG_ENV_SIZE			0x20000	/* 128k */
+#define CONFIG_ENV_ADDR			0x60000
+#define CONFIG_ENV_OFFSET		0x60000	/* env starts here */
+
+/*
+ * Default environment variables
+ */
+#define CONFIG_BOOTCOMMAND		"${x_bootcmd_kernel}; "	\
+	"setenv bootargs ${x_bootargs} ${x_bootargs_root}; "	\
+	"${x_bootcmd_usb}; bootm 0x6400000;"
+
+#define MTDIDS_DEFAULT		"nand0=nand_mtd"
+#define MTDPARTS_DEFAULT	"mtdparts=nand_mtd:0x100000 at 0x000000(uboot),"\
+	"0x400000 at 0x100000(uImage),"\
+	"0x1fb00000 at 0x500000(rootfs)"
+
+#define CONFIG_EXTRA_ENV_SETTINGS	"x_bootargs=console"		\
+	"=ttyS0,115200 "MTDPARTS_DEFAULT " rw ubi.mtd=2,2048\0"		\
+	"x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0"	\
+	"x_bootcmd_usb=usb start\0"					\
+	"x_bootargs_root=root=ubi0:rootfs rootfstype=ubifs\0"		\
+	"mtdids="MTDIDS_DEFAULT"\0"					\
+	"mtdparts="MTDPARTS_DEFAULT"\0"
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN	(1024 * 1024) /* 1MiB for malloc() */
+/* size in bytes reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_SIZE	128
+
+/*
+ * Other required minimal configurations
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_ARCH_CPU_INIT	/* call arch_cpu_init() */
+#define CONFIG_ARCH_MISC_INIT	/* call arch_misc_init() */
+#define CONFIG_DISPLAY_CPUINFO	/* Display cpu info */
+#define CONFIG_NR_DRAM_BANKS	4
+#define CONFIG_STACKSIZE	0x00100000	/* regular stack- 1M */
+#define CONFIG_SYS_LOAD_ADDR	0x00800000	/* default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00400000	/* 4M */
+#define CONFIG_SYS_MEMTEST_END	0x007fffff	/*(_8M -1) */
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000	/* Rst Vector Adr */
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+
+/*
+ * Ethernet Driver configuration
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_NETCONSOLE	/* include NetConsole support   */
+#define CONFIG_NET_MULTI	/* specify more that one ports available */
+#define	CONFIG_MII		/* expose smi ove miiphy interface */
+#define CONFIG_KIRKWOOD_EGIGA	/* Enable kirkwood Gbe Controller Driver */
+#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN	/* detect link using phy */
+#define CONFIG_KIRKWOOD_EGIGA_PORTS	{1, 1}
+#define CONFIG_PHY_BASE_ADR	0
+#define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
+#define CONFIG_RESET_PHY_R	/* use reset_phy() to init mv8831116 PHY */
+#endif /* CONFIG_CMD_NET */
+
+/*
+ * USB/EHCI
+ */
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_EHCI			/* Enable EHCI USB support */
+#define CONFIG_USB_EHCI_KIRKWOOD	/* on Kirkwood platform	*/
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+#define CONFIG_DOS_PARTITION
+#define CONFIG_ISO_PARTITION
+#define CONFIG_SUPPORT_VFAT
+#endif /* CONFIG_CMD_USB */
+
+/*
+ * File system
+ */
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_RBTREE
+#define CONFIG_MTD_DEVICE               /* needed for mtdparts commands */
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_LZO
+
+#endif /* _CONFIG_OPENRD_ULTIMATE_H */
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10  9:12 ` [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate Tanmay Upadhyay
@ 2010-06-10  9:16   ` Simon Kagstrom
  2010-06-10  9:38     ` Tanmay Upadhyay
  2010-06-13 11:53   ` Albert ARIBAUD
  1 sibling, 1 reply; 206+ messages in thread
From: Simon Kagstrom @ 2010-06-10  9:16 UTC (permalink / raw)
  To: u-boot

On Thu, 10 Jun 2010 14:42:24 +0530
Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> wrote:

> This patch modifies existing OpenRD-Base support to deal with all
> the three OpenRD boards (OpenRD-Base, OpenRD-Client & OpenRD-Ultimate).

Yes, that's a good change!

> diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
> index 940d814..19114b0 100644
> --- a/arch/arm/include/asm/mach-types.h
> +++ b/arch/arm/include/asm/mach-types.h
> @@ -2862,6 +2862,7 @@ extern unsigned int __machine_arch_type;
>  #define MACH_TYPE_MATRIX518            2879
>  #define MACH_TYPE_TINY_GURNARD         2880
>  #define MACH_TYPE_SPEAR1310            2881
> +#define MACH_TYPE_OPENRD_ULTIMATE      2884

I don't think this file is supposed to be edited in patches, but rather
synched from arm-linux by Wolfgang from time to time.

> diff --git a/include/configs/openrd_client.h b/include/configs/openrd_client.h
> new file mode 100644
> index 0000000..d936ffa

Perhaps common parts of this...

> diff --git a/include/configs/openrd_ultimate.h b/include/configs/openrd_ultimate.h
> new file mode 100644
> index 0000000..a0e0417

and this and openrd_base.h can be merged into a common file. Most stuff
should be identical, right?

// Simon

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10  9:16   ` Simon Kagstrom
@ 2010-06-10  9:38     ` Tanmay Upadhyay
  2010-06-10 10:25       ` Simon Kagstrom
  0 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-06-10  9:38 UTC (permalink / raw)
  To: u-boot


On 06/10/2010 02:46 PM, Simon Kagstrom wrote:
> On Thu, 10 Jun 2010 14:42:24 +0530
> Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  wrote:
>
>    
>> This patch modifies existing OpenRD-Base support to deal with all
>> the three OpenRD boards (OpenRD-Base, OpenRD-Client&  OpenRD-Ultimate).
>>      
> Yes, that's a good change!
>
>    
>> diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
>> index 940d814..19114b0 100644
>> --- a/arch/arm/include/asm/mach-types.h
>> +++ b/arch/arm/include/asm/mach-types.h
>> @@ -2862,6 +2862,7 @@ extern unsigned int __machine_arch_type;
>>   #define MACH_TYPE_MATRIX518            2879
>>   #define MACH_TYPE_TINY_GURNARD         2880
>>   #define MACH_TYPE_SPEAR1310            2881
>> +#define MACH_TYPE_OPENRD_ULTIMATE      2884
>>      
> I don't think this file is supposed to be edited in patches, but rather
> synched from arm-linux by Wolfgang from time to time.
>
>    
Sorry, I didn't know about that. However, as the number is already 
registered, is that ok to have it here?
>> diff --git a/include/configs/openrd_client.h b/include/configs/openrd_client.h
>> new file mode 100644
>> index 0000000..d936ffa
>>      
> Perhaps common parts of this...
>
>    
>> diff --git a/include/configs/openrd_ultimate.h b/include/configs/openrd_ultimate.h
>> new file mode 100644
>> index 0000000..a0e0417
>>      
> and this and openrd_base.h can be merged into a common file. Most stuff
> should be identical, right?
>    
I agree with you. But auto-generated 'config.h' file includes 
<board_name.h>. So there has to be one for each board. However, there 
could be one 'openrd.h'  in the configs and three board specific files 
include it. This will increase the number of files, but would decrease 
LOC. What do you think?

Thanks,

Tanmay
> // Simon
>
>
> Email Scanned for Virus&  Dangerous Content by : www.CleanMailGateway.com
>
> ____________________________________________________________________________________
> Disclaimer: This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated.Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email.
> ____________________________________________________________________________________
>    

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10  9:38     ` Tanmay Upadhyay
@ 2010-06-10 10:25       ` Simon Kagstrom
  2010-06-10 19:03         ` Prafulla Wadaskar
  0 siblings, 1 reply; 206+ messages in thread
From: Simon Kagstrom @ 2010-06-10 10:25 UTC (permalink / raw)
  To: u-boot

On Thu, 10 Jun 2010 15:08:00 +0530
Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> wrote:

> >> +#define MACH_TYPE_OPENRD_ULTIMATE      2884
> >>      
> > I don't think this file is supposed to be edited in patches, but rather
> > synched from arm-linux by Wolfgang from time to time.
>
> Sorry, I didn't know about that. However, as the number is already 
> registered, is that ok to have it here?

Probably Wolfgang or Tom Rix (the ARM maintainer) can synch it if you
ask them to.

> I agree with you. But auto-generated 'config.h' file includes 
> <board_name.h>. So there has to be one for each board. However, there 
> could be one 'openrd.h'  in the configs and three board specific files 
> include it. This will increase the number of files, but would decrease 
> LOC. What do you think?

Personally I'd prefer to keep the common parts in a common file, so I'd
vote for that solution.

// Simon

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10 10:25       ` Simon Kagstrom
@ 2010-06-10 19:03         ` Prafulla Wadaskar
  2010-06-14 11:02           ` Tanmay Upadhyay
  0 siblings, 1 reply; 206+ messages in thread
From: Prafulla Wadaskar @ 2010-06-10 19:03 UTC (permalink / raw)
  To: u-boot

 

> -----Original Message-----
> From: Simon Kagstrom [mailto:simon.kagstrom at netinsight.net] 
> Sent: Thursday, June 10, 2010 3:56 PM
> To: Tanmay Upadhyay
> Cc: Prafulla Wadaskar; u-boot at lists.denx.de
> Subject: Re: [PATCH] ARM: Kirkwood: Add support for 
> OpenRD-Client & OpenRD-Ultimate
> 
> On Thu, 10 Jun 2010 15:08:00 +0530
> Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> wrote:
> 
> > >> +#define MACH_TYPE_OPENRD_ULTIMATE      2884
> > >>      
> > > I don't think this file is supposed to be edited in 
> patches, but rather
> > > synched from arm-linux by Wolfgang from time to time.
> >
> > Sorry, I didn't know about that. However, as the number is already 
> > registered, is that ok to have it here?
> 
> Probably Wolfgang or Tom Rix (the ARM maintainer) can synch it if you
> ask them to.

Tom Does this frequently, Hi Tom, can you pls do the needful?

> 
> > I agree with you. But auto-generated 'config.h' file includes 
> > <board_name.h>. So there has to be one for each board. 

Yes, This is correct approach, lets have three files for three boards (like other added)
Abstract common part in openrd.h and include it in respective board config header files.

> However, there 
> > could be one 'openrd.h'  in the configs and three board 
> specific files 
> > include it. This will increase the number of files, but 
> would decrease 
> > LOC. What do you think?

As suggested above, let's keep code clean and simple.
Adding new board support in future to the same family will keep on increasing code complexity.
I prefer adding few files instead of modifying existing.
Secondly kwimage.cfg in your port may have common settings for all three board which may not be the case always.
And file parsing does not support conditional code for this file.

So I suggest, you should keep common code under openrd.c/h, and board specific in <board_name>.c/h
Even I don't mind keeping existing openrd_base board support as it is and adding new board support for two other boards.

Regards..
Prafulla . .

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10  9:12 ` [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate Tanmay Upadhyay
  2010-06-10  9:16   ` Simon Kagstrom
@ 2010-06-13 11:53   ` Albert ARIBAUD
  2010-06-13 12:41     ` Wolfgang Denk
  2010-06-13 12:51     ` Wolfgang Denk
  1 sibling, 2 replies; 206+ messages in thread
From: Albert ARIBAUD @ 2010-06-13 11:53 UTC (permalink / raw)
  To: u-boot

Le 10/06/2010 11:12, Tanmay Upadhyay a ?crit :

> This patch modifies existing OpenRD-Base support to deal with all
> the three OpenRD boards (OpenRD-Base, OpenRD-Client&  OpenRD-Ultimate).

Probably small detail: this patch replaces the @ by an <at> in the 
e-mail addresses (not only the patch author's). Is it a policy for 
submitting patches to u-boot that all e-mail addresses should be 
'obfuscated' so?

More important: I've tried running the resulting u-boot on my 
OpenRD-Client by TFTPing it to RAM (the default OpenRD-Client config has 
CONFIG_SKIP_LOWLEVEL_INIT defined and CONFIG_SKIP_RELACATION undefined). 
Doing a 'go' to the load address causes no visible output on the console 
and no sign of life at all -- I have to reset the board to get back to 
the FLASH u-boot. Anyone here had better luck with the OpenRD client config?

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-13 11:53   ` Albert ARIBAUD
@ 2010-06-13 12:41     ` Wolfgang Denk
  2010-06-13 12:51     ` Wolfgang Denk
  1 sibling, 0 replies; 206+ messages in thread
From: Wolfgang Denk @ 2010-06-13 12:41 UTC (permalink / raw)
  To: u-boot

Dear Albert ARIBAUD,

In message <4C14C6A9.6000407@free.fr> you wrote:
> Le 10/06/2010 11:12, Tanmay Upadhyay a =E9crit :
> 
> > This patch modifies existing OpenRD-Base support to deal with all
> > the three OpenRD boards (OpenRD-Base, OpenRD-Client&  OpenRD-Ultimate).
> 
> Probably small detail: this patch replaces the @ by an <at> in the >
> e-mail addresses (not only the patch author's). Is it a policy for >
> submitting patches to u-boot that all e-mail addresses should be >
> 'obfuscated' so?

This is not only NOT policy, but it is a strict NO-NO. Do NOT do that.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
When a child is taught ... its programmed with simple instructions --
and at some point, if its mind develops properly, it exceeds the  sum
of what it was taught, thinks independently.
	-- Dr. Richard Daystrom, "The Ultimate Computer",
	   stardate 4731.3.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-13 11:53   ` Albert ARIBAUD
  2010-06-13 12:41     ` Wolfgang Denk
@ 2010-06-13 12:51     ` Wolfgang Denk
  2010-06-13 13:39       ` Albert ARIBAUD
  1 sibling, 1 reply; 206+ messages in thread
From: Wolfgang Denk @ 2010-06-13 12:51 UTC (permalink / raw)
  To: u-boot

Dear Albert ARIBAUD,

In message <4C14C6A9.6000407@free.fr> you wrote:
>
> > This patch modifies existing OpenRD-Base support to deal with all
> > the three OpenRD boards (OpenRD-Base, OpenRD-Client&  OpenRD-Ultimate).
>
> Probably small detail: this patch replaces the @ by an <at> in the >
> e-mail addresses (not only the patch author's). Is it a policy for >
> submitting patches to u-boot that all e-mail addresses should be >
> 'obfuscated' so?

Hm... I cannot find any such change in the original patch. Did you
receive the original mail through the mailing list, or are you
reviewing the patch in some mailing list archive?

Note that many mailing list setups auto-obfuscate mail addresses.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
War isn't a good life, but it's life.
	-- Kirk, "A Private Little War", stardate 4211.8

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-13 12:51     ` Wolfgang Denk
@ 2010-06-13 13:39       ` Albert ARIBAUD
  0 siblings, 0 replies; 206+ messages in thread
From: Albert ARIBAUD @ 2010-06-13 13:39 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

Le 13/06/2010 14:51, Wolfgang Denk a ?crit :

>> Probably small detail: this patch replaces the @ by an<at>  in the>
>> e-mail addresses (not only the patch author's). Is it a policy for>
>> submitting patches to u-boot that all e-mail addresses should be>
>> 'obfuscated' so?
>
> Hm... I cannot find any such change in the original patch. Did you
> receive the original mail through the mailing list, or are you
> reviewing the patch in some mailing list archive?

Indeed, I used the web u-boot archives, and yes, that's what turned the 
@s into <at>s; going through the NNTP server instead solved this point.

Sorry for the noise.

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate
  2010-06-10 19:03         ` Prafulla Wadaskar
@ 2010-06-14 11:02           ` Tanmay Upadhyay
  0 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-06-14 11:02 UTC (permalink / raw)
  To: u-boot


On 06/11/2010 12:33 AM, Prafulla Wadaskar wrote:
>
>
>    
>> -----Original Message-----
>> From: Simon Kagstrom [mailto:simon.kagstrom at netinsight.net]
>> Sent: Thursday, June 10, 2010 3:56 PM
>> To: Tanmay Upadhyay
>> Cc: Prafulla Wadaskar; u-boot at lists.denx.de
>> Subject: Re: [PATCH] ARM: Kirkwood: Add support for
>> OpenRD-Client&  OpenRD-Ultimate
>>
>> On Thu, 10 Jun 2010 15:08:00 +0530
>> Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  wrote:
>>
>>      
>>>>> +#define MACH_TYPE_OPENRD_ULTIMATE      2884
>>>>>
>>>>>            
>>>> I don't think this file is supposed to be edited in
>>>>          
>> patches, but rather
>>      
>>>> synched from arm-linux by Wolfgang from time to time.
>>>>          
>>> Sorry, I didn't know about that. However, as the number is already
>>> registered, is that ok to have it here?
>>>        
>> Probably Wolfgang or Tom Rix (the ARM maintainer) can synch it if you
>> ask them to.
>>      
> Tom Does this frequently, Hi Tom, can you pls do the needful?
>    
Tom has synched it, but unfortunately the code for ultimate hasn't been 
in yet. It's stuck somewhere 
http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/017535.html.

Shall I wait for this patch to get into the kernel before I send mine 
for u-boot? Otherwise my patch won't get compiled. However, I can send 
my patch for review. I have operd.h, openrd_base.h, openrd_client.h & 
openrd_ultimate.h in 'include/configs' as suggested.

Please suggest.

Thanks,

Tanmay
>    
>>      
>>> I agree with you. But auto-generated 'config.h' file includes
>>> <board_name.h>. So there has to be one for each board.
>>>        
> Yes, This is correct approach, lets have three files for three boards (like other added)
> Abstract common part in openrd.h and include it in respective board config header files.
>
>    
>> However, there
>>      
>>> could be one 'openrd.h'  in the configs and three board
>>>        
>> specific files
>>      
>>> include it. This will increase the number of files, but
>>>        
>> would decrease
>>      
>>> LOC. What do you think?
>>>        
> As suggested above, let's keep code clean and simple.
> Adding new board support in future to the same family will keep on increasing code complexity.
> I prefer adding few files instead of modifying existing.
> Secondly kwimage.cfg in your port may have common settings for all three board which may not be the case always.
> And file parsing does not support conditional code for this file.
>
> So I suggest, you should keep common code under openrd.c/h, and board specific in<board_name>.c/h
> Even I don't mind keeping existing openrd_base board support as it is and adding new board support for two other boards.
>
> Regards..
> Prafulla . .
>
>
> Email Scanned for Virus&  Dangerous Content by : www.CleanMailGateway.com
>
> ____________________________________________________________________________________
> Disclaimer: This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated.Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email.
> ____________________________________________________________________________________
>
>    

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
       [not found] <no>
                   ` (8 preceding siblings ...)
  2010-06-10  9:12 ` [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate Tanmay Upadhyay
@ 2010-08-10  8:29 ` Tanmay Upadhyay
  2010-08-10  8:56   ` Alexander Clouter
  2010-08-10  8:40 ` [PATCH] ARM: Fix broken Kconfig in arch/arm Tanmay Upadhyay
                   ` (28 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-08-10  8:29 UTC (permalink / raw)
  To: linux-arm-kernel

This patch enables user to use serial port 1 of the OpenRD device for SDIO
or UART(RS232/RS485). The selection can be done through kernel parameter.

By default the port would be used for SDIO. To select RS232 or RS485 mode,
pass string "uart=232" or "uart=485" respectively in the kernel parameters.
"uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 arch/arm/mach-kirkwood/openrd-setup.c |   92 ++++++++++++++++++++++++++++++++-
 1 files changed, 91 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index fd06be6..cd061ab 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -19,6 +19,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
+#include <mach/gpio.h>
 #include <plat/mvsdio.h>
 #include "common.h"
 #include "mpp.h"
@@ -57,7 +58,15 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
+	MPP12_SD_CLK,
+	MPP13_SD_CMD,
+	MPP14_SD_D0,
+	MPP15_SD_D1,
+	MPP16_SD_D2,
+	MPP17_SD_D3,
+	MPP28_GPIO,
 	MPP29_GPIO,
+	MPP34_GPIO,
 	0
 };
 
@@ -67,6 +76,71 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
 	},
 };
 
+static int __initdata uart1;
+
+static int __init sd_uart_selection(char *str)
+{
+	/* Default is SD. Change if required, for UART */
+	if (!str)
+		return 0;
+
+	if (!strncmp(str, "232", 3)) {
+		uart1 = 232;
+	} else if (!strncmp(str, "485", 3)) {
+		/* OpenRD-Base doesn't have RS485. Treat is as an
+		 * unknown argument & just have default setting -
+		 * which is SD */
+		if (machine_is_openrd_base())
+			return 1;
+
+		uart1 = 485;
+	}
+	return 1;
+}
+/* Parse boot_command_line string uart=232/485 */
+__setup("uart=", sd_uart_selection);
+
+static int __init uart1_mpp_config(void)
+{
+	/* Configure MPP for UART1 */
+	unsigned int uart1_mpp_config[] = {
+		MPP13_UART1_TXD,
+		MPP14_UART1_RXD,
+		0
+	};
+
+	kirkwood_mpp_conf(uart1_mpp_config);
+
+	if (gpio_request(34, "SD_UART1_SEL")) {
+		printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
+				", gpio: 34\n");
+		return -EIO;
+	}
+
+	if (gpio_request(28, "RS232_RS485_SEL")) {
+		printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
+				", gpio# 28\n");
+		gpio_free(34);
+		return -EIO;
+	}
+
+	/* Select UART1
+	 * Pin # 34: 0 => UART1, 1 => SD */
+	gpio_direction_output(34, 0);
+
+	/* Select RS232 OR RS485
+	 * Pin # 28: 0 => RS232, 1 => RS485 */
+	if (uart1 == 232)
+		gpio_direction_output(28, 0);
+	else
+		gpio_direction_output(28, 1);
+
+	gpio_free(34);
+	gpio_free(28);
+
+	return 0;
+}
+
 static void __init openrd_init(void)
 {
 	/*
@@ -90,7 +164,6 @@ static void __init openrd_init(void)
 		kirkwood_ge01_init(&openrd_ge01_data);
 
 	kirkwood_sata_init(&openrd_sata_data);
-	kirkwood_sdio_init(&openrd_mvsdio_data);
 
 	kirkwood_i2c_init();
 
@@ -99,6 +172,23 @@ static void __init openrd_init(void)
 			ARRAY_SIZE(i2c_board_info));
 		kirkwood_audio_init();
 	}
+
+	if (!uart1) {
+		/* Select SD
+		 * Pin # 34: 0 => UART1, 1 => SD */
+		if (gpio_request(34, "SD_UART1_SEL")) {
+			printk(KERN_ERR "GPIO request failed for SD/UART1 "
+					"selection, gpio: 34\n");
+		} else {
+
+			gpio_direction_output(34, 1);
+			gpio_free(34);
+			kirkwood_sdio_init(&openrd_mvsdio_data);
+		}
+	} else {
+		if (!uart1_mpp_config())
+			kirkwood_uart1_init();
+	}
 }
 
 static int __init openrd_pci_init(void)
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH] ARM: Fix broken Kconfig in arch/arm
       [not found] <no>
                   ` (9 preceding siblings ...)
  2010-08-10  8:29 ` [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
@ 2010-08-10  8:40 ` Tanmay Upadhyay
  2011-03-02  8:38   ` Liu Yuan
                   ` (27 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-08-10  8:40 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 arch/arm/Kconfig |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 232f0c7..684c1a1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1184,8 +1184,8 @@ config LOCAL_TIMERS
 		REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
 		ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
 	default y
-	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || \\
-		ARCH_U8500 || ARCH_TEGRA
+	select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || \
+		ARCH_U8500 || ARCH_TEGRA)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10  8:29 ` [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
@ 2010-08-10  8:56   ` Alexander Clouter
  2010-08-10  8:58     ` Alexander Clouter
  0 siblings, 1 reply; 206+ messages in thread
From: Alexander Clouter @ 2010-08-10  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Comments inline.

* Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> [2010-08-10 13:59:33+0530]:
>
> This patch enables user to use serial port 1 of the OpenRD device for SDIO
> or UART(RS232/RS485). The selection can be done through kernel parameter.
> 
> By default the port would be used for SDIO. To select RS232 or RS485 mode,
> pass string "uart=232" or "uart=485" respectively in the kernel parameters.
> "uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.
> 
> Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
> ---
>  arch/arm/mach-kirkwood/openrd-setup.c |   92 ++++++++++++++++++++++++++++++++-
>  1 files changed, 91 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
> index fd06be6..cd061ab 100644
> --- a/arch/arm/mach-kirkwood/openrd-setup.c
> +++ b/arch/arm/mach-kirkwood/openrd-setup.c
> @@ -19,6 +19,7 @@
>  #include <asm/mach-types.h>
>  #include <asm/mach/arch.h>
>  #include <mach/kirkwood.h>
> +#include <mach/gpio.h>
>  #include <plat/mvsdio.h>
>  #include "common.h"
>  #include "mpp.h"
> @@ -57,7 +58,15 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
>  };
>  
>  static unsigned int openrd_mpp_config[] __initdata = {
> +	MPP12_SD_CLK,
> +	MPP13_SD_CMD,
> +	MPP14_SD_D0,
> +	MPP15_SD_D1,
> +	MPP16_SD_D2,
> +	MPP17_SD_D3,
> +	MPP28_GPIO,
>  	MPP29_GPIO,
> +	MPP34_GPIO,
>  	0
>  };
>  
> @@ -67,6 +76,71 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
>  	},
>  };
>  
> +static int __initdata uart1;
> +
> +static int __init sd_uart_selection(char *str)
> +{
> +	/* Default is SD. Change if required, for UART */
> +	if (!str)
> +		return 0;
> +
> +	if (!strncmp(str, "232", 3)) {
> +		uart1 = 232;
> +	} else if (!strncmp(str, "485", 3)) {
> +		/* OpenRD-Base doesn't have RS485. Treat is as an
> +		 * unknown argument & just have default setting -
> +		 * which is SD */
> +		if (machine_is_openrd_base())
> +			return 1;
> +
>
uart1 = -ENODEV;
return 1;

> +		uart1 = 485;
> +	}
> +	return 1;
>
uart1 = -EINVAL;
return 1;

> +}
> +/* Parse boot_command_line string uart=232/485 */
> +__setup("uart=", sd_uart_selection);
> +
>
'kirkwood_init_uart1' instead maybe, only going to annoy someone 
otherwise I'm guessing.

> +static int __init uart1_mpp_config(void)
> +{
> +	/* Configure MPP for UART1 */
> +	unsigned int uart1_mpp_config[] = {
> +		MPP13_UART1_TXD,
> +		MPP14_UART1_RXD,
> +		0
> +	};
> +
> +	kirkwood_mpp_conf(uart1_mpp_config);
> +
> +	if (gpio_request(34, "SD_UART1_SEL")) {
> +		printk(KERN_ERR "GPIO request failed for SD/UART1 selection"
> +				", gpio: 34\n");
> +		return -EIO;
> +	}
> +
> +	if (gpio_request(28, "RS232_RS485_SEL")) {
> +		printk(KERN_ERR "GPIO request failed for RS232/RS485 selection"
> +				", gpio# 28\n");
> +		gpio_free(34);
> +		return -EIO;
> +	}
> +
> +	/* Select UART1
> +	 * Pin # 34: 0 => UART1, 1 => SD */
> +	gpio_direction_output(34, 0);
> +
> +	/* Select RS232 OR RS485
> +	 * Pin # 28: 0 => RS232, 1 => RS485 */
> +	if (uart1 == 232)
> +		gpio_direction_output(28, 0);
> +	else
> +		gpio_direction_output(28, 1);
> +
> +	gpio_free(34);
> +	gpio_free(28);
> +
> +	return 0;
> +}
> +
>  static void __init openrd_init(void)
>  {
>  	/*
> @@ -90,7 +164,6 @@ static void __init openrd_init(void)
>  		kirkwood_ge01_init(&openrd_ge01_data);
>  
>  	kirkwood_sata_init(&openrd_sata_data);
> -	kirkwood_sdio_init(&openrd_mvsdio_data);
>  
>  	kirkwood_i2c_init();
>  
> @@ -99,6 +172,23 @@ static void __init openrd_init(void)
>  			ARRAY_SIZE(i2c_board_info));
>  		kirkwood_audio_init();
>  	}
> +
> +	if (!uart1) {
> +		/* Select SD
> +		 * Pin # 34: 0 => UART1, 1 => SD */
> +		if (gpio_request(34, "SD_UART1_SEL")) {
> +			printk(KERN_ERR "GPIO request failed for SD/UART1 "
> +					"selection, gpio: 34\n");
> +		} else {
> +
> +			gpio_direction_output(34, 1);
> +			gpio_free(34);
> +			kirkwood_sdio_init(&openrd_mvsdio_data);
> +		}
> +	} else {
>
} else if (uart1 < 0) {
	prink(KERN_WARNING, "<grumble>, uart1 init issue, "
		"defaulting to SD: %d\n", uart1);
} else {

> +		if (!uart1_mpp_config())
> +			kirkwood_uart1_init();
> +	}
>  }
>  
>  static int __init openrd_pci_init(void)
> -- 
> 1.6.6.1

Afterwards, remember to run it through ./scripts/checkpatch.pl.

Cheers

-- 
Alexander Clouter
.sigmonster says: Old MacDonald had an agricultural real estate tax abatement.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10  8:56   ` Alexander Clouter
@ 2010-08-10  8:58     ` Alexander Clouter
  2010-08-10 10:27       ` Tanmay Upadhyay
  0 siblings, 1 reply; 206+ messages in thread
From: Alexander Clouter @ 2010-08-10  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Just a quick amendment;

* Alexander Clouter <alex@digriz.org.uk> [2010-08-10 09:56:43+0100]:
>
> * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> [2010-08-10 13:59:33+0530]:
> >
> > This patch enables user to use serial port 1 of the OpenRD device for SDIO
> > or UART(RS232/RS485). The selection can be done through kernel parameter.
> > 
> > By default the port would be used for SDIO. To select RS232 or RS485 mode,
> > pass string "uart=232" or "uart=485" respectively in the kernel parameters.
> > "uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.
> > 
> > Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
> > ---
> >  arch/arm/mach-kirkwood/openrd-setup.c |   92 ++++++++++++++++++++++++++++++++-
> >  1 files changed, 91 insertions(+), 1 deletions(-)
> > 
> > diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
> > index fd06be6..cd061ab 100644
> > --- a/arch/arm/mach-kirkwood/openrd-setup.c
> > +++ b/arch/arm/mach-kirkwood/openrd-setup.c
> > @@ -19,6 +19,7 @@
> >  #include <asm/mach-types.h>
> >  #include <asm/mach/arch.h>
> >  #include <mach/kirkwood.h>
> > +#include <mach/gpio.h>
> >  #include <plat/mvsdio.h>
> >  #include "common.h"
> >  #include "mpp.h"
> > @@ -57,7 +58,15 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
> >  };
> >  
> >  static unsigned int openrd_mpp_config[] __initdata = {
> > +	MPP12_SD_CLK,
> > +	MPP13_SD_CMD,
> > +	MPP14_SD_D0,
> > +	MPP15_SD_D1,
> > +	MPP16_SD_D2,
> > +	MPP17_SD_D3,
> > +	MPP28_GPIO,
> >  	MPP29_GPIO,
> > +	MPP34_GPIO,
> >  	0
> >  };
> >  
> > @@ -67,6 +76,71 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
> >  	},
> >  };
> >  
> > +static int __initdata uart1;
>
static int __initdata uart1 = -EINVAL;

> > +
> > +static int __init sd_uart_selection(char *str)
> > +{
> > +	/* Default is SD. Change if required, for UART */
> > +	if (!str)
> > +		return 0;
> > +
> > +	if (!strncmp(str, "232", 3)) {
> > +		uart1 = 232;
> > +	} else if (!strncmp(str, "485", 3)) {
> > +		/* OpenRD-Base doesn't have RS485. Treat is as an
> > +		 * unknown argument & just have default setting -
> > +		 * which is SD */
> > +		if (machine_is_openrd_base())
> > +			return 1;
> > +
> >
> uart1 = -ENODEV;
> return 1;
> 
> > +		uart1 = 485;
> > +	}
> > +	return 1;
> >
> uart1 = -EINVAL;
> return 1;
> 
Drop this suggested amendment.

Cheers

-- 
Alexander Clouter
.sigmonster says: What I need is a MATURE RELATIONSHIP with a FLOPPY DISK ...

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10  8:58     ` Alexander Clouter
@ 2010-08-10 10:27       ` Tanmay Upadhyay
  2010-08-10 10:28         ` Alexander Clouter
  0 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-08-10 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/10/2010 02:28 PM, Alexander Clouter wrote:
> Hi,
>
> Just a quick amendment;
>
> * Alexander Clouter<alex@digriz.org.uk>  [2010-08-10 09:56:43+0100]:
>    
>> * Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  [2010-08-10 13:59:33+0530]:
>>      
>>> This patch enables user to use serial port 1 of the OpenRD device for SDIO
>>> or UART(RS232/RS485). The selection can be done through kernel parameter.
>>>
>>> By default the port would be used for SDIO. To select RS232 or RS485 mode,
>>> pass string "uart=232" or "uart=485" respectively in the kernel parameters.
>>> "uart=485" is ignored on OpenRD-Base as it doesn't have RS485 port.
>>>
>>> Signed-off-by: Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>
>>> ---
>>>   arch/arm/mach-kirkwood/openrd-setup.c |   92 ++++++++++++++++++++++++++++++++-
>>>   1 files changed, 91 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
>>> index fd06be6..cd061ab 100644
>>> --- a/arch/arm/mach-kirkwood/openrd-setup.c
>>> +++ b/arch/arm/mach-kirkwood/openrd-setup.c
>>> @@ -19,6 +19,7 @@
>>>   #include<asm/mach-types.h>
>>>   #include<asm/mach/arch.h>
>>>   #include<mach/kirkwood.h>
>>> +#include<mach/gpio.h>
>>>   #include<plat/mvsdio.h>
>>>   #include "common.h"
>>>   #include "mpp.h"
>>> @@ -57,7 +58,15 @@ static struct mvsdio_platform_data openrd_mvsdio_data = {
>>>   };
>>>
>>>   static unsigned int openrd_mpp_config[] __initdata = {
>>> +	MPP12_SD_CLK,
>>> +	MPP13_SD_CMD,
>>> +	MPP14_SD_D0,
>>> +	MPP15_SD_D1,
>>> +	MPP16_SD_D2,
>>> +	MPP17_SD_D3,
>>> +	MPP28_GPIO,
>>>   	MPP29_GPIO,
>>> +	MPP34_GPIO,
>>>   	0
>>>   };
>>>
>>> @@ -67,6 +76,71 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
>>>   	},
>>>   };
>>>
>>> +static int __initdata uart1;
>>>        
>>      
> static int __initdata uart1 = -EINVAL;
>
>    
>>> +
>>> +static int __init sd_uart_selection(char *str)
>>> +{
>>> +	/* Default is SD. Change if required, for UART */
>>> +	if (!str)
>>> +		return 0;
>>> +
>>> +	if (!strncmp(str, "232", 3)) {
>>> +		uart1 = 232;
>>> +	} else if (!strncmp(str, "485", 3)) {
>>> +		/* OpenRD-Base doesn't have RS485. Treat is as an
>>> +		 * unknown argument&  just have default setting -
>>> +		 * which is SD */
>>> +		if (machine_is_openrd_base())
>>> +			return 1;
>>> +
>>>
>>>        
>> uart1 = -ENODEV;
>> return 1;
>>
>>      
>>> +		uart1 = 485;
>>> +	}
>>> +	return 1;
>>>
>>>        
>> uart1 = -EINVAL;
>> return 1;
>>
>>      
> Drop this suggested amendment.
>
> Cheers
>
>    
Intention here is to provide SD support by default. It will be switched 
to UART mode only if someone asks to do so via kernel parameter. If 
someone doesn't give OR gives improper kernel parameter, he/she won't 
get UART1. It will simply fall-back to the default setting - which is SD 
support.

Does this make sense? Please suggest.

Thanks,

Tanmay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100810/d3ec9071/attachment-0001.html>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10 10:27       ` Tanmay Upadhyay
@ 2010-08-10 10:28         ` Alexander Clouter
  2010-08-10 10:49           ` Tanmay Upadhyay
  0 siblings, 1 reply; 206+ messages in thread
From: Alexander Clouter @ 2010-08-10 10:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

* Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> [2010-08-10 15:52:14+0530]:
>
> Intention here is to provide SD support by default. It will be switched  
> to UART mode only if someone asks to do so via kernel parameter. If  
> someone doesn't give OR gives improper kernel parameter, he/she won't get 
> UART1. It will simply fall-back to the default setting - which is SD  
> support.
>
My mis-type, I forgot to put a 
'kirkwood_sdio_init(&openrd_mvsdio_data);' after my added printk().

Cheers

-- 
Alexander Clouter
.sigmonster says: BOFH excuse #367:
                  Webmasters kidnapped by evil cult.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10 10:28         ` Alexander Clouter
@ 2010-08-10 10:49           ` Tanmay Upadhyay
  2010-08-10 11:53             ` Alexander Clouter
  0 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-08-10 10:49 UTC (permalink / raw)
  To: linux-arm-kernel


On 08/10/2010 03:58 PM, Alexander Clouter wrote:
> Hi,
>
> * Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  [2010-08-10 15:52:14+0530]:
>    
>> Intention here is to provide SD support by default. It will be switched
>> to UART mode only if someone asks to do so via kernel parameter. If
>> someone doesn't give OR gives improper kernel parameter, he/she won't get
>> UART1. It will simply fall-back to the default setting - which is SD
>> support.
>>
>>      
> My mis-type, I forgot to put a
> 'kirkwood_sdio_init(&openrd_mvsdio_data);' after my added printk().
>
> Cheers
>
>    
If I understood correctly, intention behind this is to inform user that 
he/she made a mistake while passing the kernel parameters. Is this correct?

Thanks,

Tanmay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100810/5e2bfe4c/attachment-0001.html>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10 10:49           ` Tanmay Upadhyay
@ 2010-08-10 11:53             ` Alexander Clouter
  2010-08-11  5:21               ` Tanmay Upadhyay
  0 siblings, 1 reply; 206+ messages in thread
From: Alexander Clouter @ 2010-08-10 11:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

* Tanmay Upadhyay <tanmay.upadhyay@einfochips.com> [2010-08-10 16:20:20+0530]:
>
> On 08/10/2010 03:58 PM, Alexander Clouter wrote:
>>
>> * Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  [2010-08-10 15:52:14+0530]:
>>    
>>> Intention here is to provide SD support by default. It will be switched
>>> to UART mode only if someone asks to do so via kernel parameter. If
>>> someone doesn't give OR gives improper kernel parameter, he/she won't get
>>> UART1. It will simply fall-back to the default setting - which is SD
>>> support.
>>
>> My mis-type, I forgot to put a
>> 'kirkwood_sdio_init(&openrd_mvsdio_data);' after my added printk().
>>
> If I understood correctly, intention behind this is to inform user that  
> he/she made a mistake while passing the kernel parameters. Is this 
> correct?
>
Exactly, and there is no harm turning on the SD slot rather than UART1 
at the same time.

Cheers

-- 
Alexander Clouter
.sigmonster says: tax office, n.:
                  	Den of inequity.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1
  2010-08-10 11:53             ` Alexander Clouter
@ 2010-08-11  5:21               ` Tanmay Upadhyay
  0 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2010-08-11  5:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/10/2010 05:23 PM, Alexander Clouter wrote:
> Hi,
>
> * Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>  [2010-08-10 16:20:20+0530]:
>    
>> On 08/10/2010 03:58 PM, Alexander Clouter wrote:
>>      
>>> * Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>   [2010-08-10 15:52:14+0530]:
>>>
>>>        
>>>> Intention here is to provide SD support by default. It will be switched
>>>> to UART mode only if someone asks to do so via kernel parameter. If
>>>> someone doesn't give OR gives improper kernel parameter, he/she won't get
>>>> UART1. It will simply fall-back to the default setting - which is SD
>>>> support.
>>>>          
>>> My mis-type, I forgot to put a
>>> 'kirkwood_sdio_init(&openrd_mvsdio_data);' after my added printk().
>>>
>>>        
>> If I understood correctly, intention behind this is to inform user that
>> he/she made a mistake while passing the kernel parameters. Is this
>> correct?
>>
>>      
> Exactly, and there is no harm turning on the SD slot rather than UART1
> at the same time.
>
> Cheers
>
>    
Sent version 3 to the list.

-- Tanmay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100811/844218f3/attachment-0001.html>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry
       [not found] <no>
@ 2011-03-02  8:38   ` Liu Yuan
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 arch/x86/Kconfig.debug |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 615e188..f29e32d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -304,4 +304,13 @@ config DEBUG_STRICT_USER_COPY_CHECKS
 
 	  If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config PAGE_CACHE_ACCT
+	bool "Page cache accounting"
+	---help---
+	  Enabling this options to account for page cache hit/missed number of
+	  times. This would allow user space applications get better knowledge
+	  of underlying page cache system by reading virtual file. The statitics
+	  per partition are collected.
+
+	  If unsure, say N.
 endmenu
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry
@ 2011-03-02  8:38   ` Liu Yuan
  0 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 arch/x86/Kconfig.debug |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 615e188..f29e32d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -304,4 +304,13 @@ config DEBUG_STRICT_USER_COPY_CHECKS
 
 	  If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config PAGE_CACHE_ACCT
+	bool "Page cache accounting"
+	---help---
+	  Enabling this options to account for page cache hit/missed number of
+	  times. This would allow user space applications get better knowledge
+	  of underlying page cache system by reading virtual file. The statitics
+	  per partition are collected.
+
+	  If unsure, say N.
 endmenu
-- 
1.7.0.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 2/5] block: Add functions and data types for Page Cache Accounting
       [not found] <no>
@ 2011-03-02  8:38   ` Liu Yuan
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

These functions and data types are based on the percpu
disk stats infrastructure.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 include/linux/genhd.h |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index c0d5f69..4f0257c 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -86,6 +86,11 @@ struct disk_stats {
 	unsigned long ticks[2];
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	unsigned long page_cache_readpages;
+	unsigned long page_cache_hit[2];
+	unsigned long page_cache_missed[2];
+#endif
 };
 
 #define PARTITION_META_INFO_VOLNAMELTH	64
@@ -400,6 +405,57 @@ static inline void free_part_info(struct hd_struct *part)
 	kfree(part->info);
 }
 
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static inline void page_cache_acct_readpages(struct super_block *sb, int nr_pages)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_add(cpu, part, page_cache_readpages, nr_pages);
+		part_stat_unlock();
+	}
+}
+static inline void page_cache_acct_hit(struct super_block *sb, int rw)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_inc(cpu, part, page_cache_hit[rw]);
+		part_stat_unlock();
+	}
+}
+
+static inline void page_cache_acct_missed(struct super_block *sb, int rw)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_inc(cpu, part, page_cache_missed[rw]);
+		part_stat_unlock();
+	}
+}
+
+#else /* !CONFIG_PAGE_CACHE_ACCT */
+static inline void page_cache_acct_readpages(struct super_block *sb, int nr_pages)
+{
+}
+
+static inline void page_cache_acct_hit(struct super_block *sb, int rw)
+{
+}
+
+static inline void page_cache_acct_missed(struct super_block *sb, int rw)
+{
+}
+
+#endif /* CONFIG_PAGE_CACHE_ACCT */
+
 /* block/blk-core.c */
 extern void part_round_stats(int cpu, struct hd_struct *part);
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 2/5] block: Add functions and data types for Page Cache Accounting
@ 2011-03-02  8:38   ` Liu Yuan
  0 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

These functions and data types are based on the percpu
disk stats infrastructure.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 include/linux/genhd.h |   56 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index c0d5f69..4f0257c 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -86,6 +86,11 @@ struct disk_stats {
 	unsigned long ticks[2];
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	unsigned long page_cache_readpages;
+	unsigned long page_cache_hit[2];
+	unsigned long page_cache_missed[2];
+#endif
 };
 
 #define PARTITION_META_INFO_VOLNAMELTH	64
@@ -400,6 +405,57 @@ static inline void free_part_info(struct hd_struct *part)
 	kfree(part->info);
 }
 
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static inline void page_cache_acct_readpages(struct super_block *sb, int nr_pages)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_add(cpu, part, page_cache_readpages, nr_pages);
+		part_stat_unlock();
+	}
+}
+static inline void page_cache_acct_hit(struct super_block *sb, int rw)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_inc(cpu, part, page_cache_hit[rw]);
+		part_stat_unlock();
+	}
+}
+
+static inline void page_cache_acct_missed(struct super_block *sb, int rw)
+{
+	struct block_device *bdev = sb->s_bdev;
+	struct hd_struct *part;
+	int cpu;
+	if (likely(bdev) && likely(part = bdev->bd_part)) {
+		cpu = part_stat_lock();
+		part_stat_inc(cpu, part, page_cache_missed[rw]);
+		part_stat_unlock();
+	}
+}
+
+#else /* !CONFIG_PAGE_CACHE_ACCT */
+static inline void page_cache_acct_readpages(struct super_block *sb, int nr_pages)
+{
+}
+
+static inline void page_cache_acct_hit(struct super_block *sb, int rw)
+{
+}
+
+static inline void page_cache_acct_missed(struct super_block *sb, int rw)
+{
+}
+
+#endif /* CONFIG_PAGE_CACHE_ACCT */
+
 /* block/blk-core.c */
 extern void part_round_stats(int cpu, struct hd_struct *part);
 
-- 
1.7.0.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 3/5] block: Make Page Cache counters work with sysfs
       [not found] <no>
@ 2011-03-02  8:38   ` Liu Yuan
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Three counters are exported to the userspace from
/sys/block/sdx/{,sdxx}/page_cache_stats.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 block/genhd.c         |    6 ++++++
 fs/partitions/check.c |   23 +++++++++++++++++++++++
 include/linux/genhd.h |    4 ++++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index cbf1112..af9e7f8 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -988,6 +988,9 @@ static struct device_attribute dev_attr_fail_timeout =
 	__ATTR(io-timeout-fail,  S_IRUGO|S_IWUSR, part_timeout_show,
 		part_timeout_store);
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static DEVICE_ATTR(page_cache_stats, S_IRUGO, part_page_cache_stats_show, NULL);
+#endif
 
 static struct attribute *disk_attrs[] = {
 	&dev_attr_range.attr,
@@ -1006,6 +1009,9 @@ static struct attribute *disk_attrs[] = {
 #ifdef CONFIG_FAIL_IO_TIMEOUT
 	&dev_attr_fail_timeout.attr,
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	&dev_attr_page_cache_stats.attr,
+#endif
 	NULL
 };
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9c21119..e882e95 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -316,6 +316,23 @@ ssize_t part_fail_store(struct device *dev,
 }
 #endif
 
+#ifdef CONFIG_PAGE_CACHE_ACCT
+ssize_t part_page_cache_stats_show(struct device *dev,
+					  struct device_attribute * attr,
+					  char *buf)
+{
+	struct hd_struct  *p = dev_to_part(dev);
+
+	return sprintf(buf,
+			"%8lu %8lu %8lu %8lu %8lu\n ",
+			part_stat_read(p, page_cache_readpages),
+			part_stat_read(p, page_cache_missed[READ]),
+			part_stat_read(p, page_cache_hit[READ]),
+			part_stat_read(p, page_cache_missed[WRITE]),
+			part_stat_read(p, page_cache_hit[WRITE]));
+}
+#endif
+
 static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
 static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
@@ -329,6 +346,9 @@ static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL);
 static struct device_attribute dev_attr_fail =
 	__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static DEVICE_ATTR(page_cache_stats, S_IRUGO, part_page_cache_stats_show, NULL);
+#endif
 
 static struct attribute *part_attrs[] = {
 	&dev_attr_partition.attr,
@@ -342,6 +362,9 @@ static struct attribute *part_attrs[] = {
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	&dev_attr_fail.attr,
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	&dev_attr_page_cache_stats.attr,
+#endif
 	NULL
 };
 
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 4f0257c..0ecd165 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -682,6 +682,10 @@ extern ssize_t part_fail_store(struct device *dev,
 			       struct device_attribute *attr,
 			       const char *buf, size_t count);
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
+#ifdef CONFIG_PAGE_CACHE_ACCT
+extern ssize_t part_page_cache_stats_show(struct device *dev,
+					  struct device_attribute *attr, char *buf);
+#endif /*  CONFIG_PAGE_CACHE_ACCT */
 
 static inline void hd_ref_init(struct hd_struct *part)
 {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 3/5] block: Make Page Cache counters work with sysfs
@ 2011-03-02  8:38   ` Liu Yuan
  0 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Three counters are exported to the userspace from
/sys/block/sdx/{,sdxx}/page_cache_stats.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 block/genhd.c         |    6 ++++++
 fs/partitions/check.c |   23 +++++++++++++++++++++++
 include/linux/genhd.h |    4 ++++
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index cbf1112..af9e7f8 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -988,6 +988,9 @@ static struct device_attribute dev_attr_fail_timeout =
 	__ATTR(io-timeout-fail,  S_IRUGO|S_IWUSR, part_timeout_show,
 		part_timeout_store);
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static DEVICE_ATTR(page_cache_stats, S_IRUGO, part_page_cache_stats_show, NULL);
+#endif
 
 static struct attribute *disk_attrs[] = {
 	&dev_attr_range.attr,
@@ -1006,6 +1009,9 @@ static struct attribute *disk_attrs[] = {
 #ifdef CONFIG_FAIL_IO_TIMEOUT
 	&dev_attr_fail_timeout.attr,
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	&dev_attr_page_cache_stats.attr,
+#endif
 	NULL
 };
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9c21119..e882e95 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -316,6 +316,23 @@ ssize_t part_fail_store(struct device *dev,
 }
 #endif
 
+#ifdef CONFIG_PAGE_CACHE_ACCT
+ssize_t part_page_cache_stats_show(struct device *dev,
+					  struct device_attribute * attr,
+					  char *buf)
+{
+	struct hd_struct  *p = dev_to_part(dev);
+
+	return sprintf(buf,
+			"%8lu %8lu %8lu %8lu %8lu\n ",
+			part_stat_read(p, page_cache_readpages),
+			part_stat_read(p, page_cache_missed[READ]),
+			part_stat_read(p, page_cache_hit[READ]),
+			part_stat_read(p, page_cache_missed[WRITE]),
+			part_stat_read(p, page_cache_hit[WRITE]));
+}
+#endif
+
 static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
 static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
@@ -329,6 +346,9 @@ static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL);
 static struct device_attribute dev_attr_fail =
 	__ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+static DEVICE_ATTR(page_cache_stats, S_IRUGO, part_page_cache_stats_show, NULL);
+#endif
 
 static struct attribute *part_attrs[] = {
 	&dev_attr_partition.attr,
@@ -342,6 +362,9 @@ static struct attribute *part_attrs[] = {
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	&dev_attr_fail.attr,
 #endif
+#ifdef CONFIG_PAGE_CACHE_ACCT
+	&dev_attr_page_cache_stats.attr,
+#endif
 	NULL
 };
 
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 4f0257c..0ecd165 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -682,6 +682,10 @@ extern ssize_t part_fail_store(struct device *dev,
 			       struct device_attribute *attr,
 			       const char *buf, size_t count);
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
+#ifdef CONFIG_PAGE_CACHE_ACCT
+extern ssize_t part_page_cache_stats_show(struct device *dev,
+					  struct device_attribute *attr, char *buf);
+#endif /*  CONFIG_PAGE_CACHE_ACCT */
 
 static inline void hd_ref_init(struct hd_struct *part)
 {
-- 
1.7.0.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
       [not found] <no>
@ 2011-03-02  8:38   ` Liu Yuan
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Hit/Miss accountings are request-centric: that is, single request
would either cause one hit or one miss to be accounted for the very
first time that kernel query the page cache. In some rare error
conditions, kernel would re-query the page cache, but we donnot
account for it and ignore it for simplicity.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 mm/filemap.c |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 83a45d3..5388b2a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1009,10 +1009,15 @@ static void do_generic_file_read(struct file *filp, loff_t *ppos,
 		pgoff_t end_index;
 		loff_t isize;
 		unsigned long nr, ret;
+		int retry_find = 0;
 
 		cond_resched();
 find_page:
 		page = find_get_page(mapping, index);
+		if (likely(!retry_find) && page && PageUptodate(page))
+			page_cache_acct_hit(inode->i_sb, READ);
+		else
+			page_cache_acct_missed(inode->i_sb, READ);
 		if (!page) {
 			page_cache_sync_readahead(mapping,
 					ra, filp,
@@ -1137,6 +1142,7 @@ readpage:
 		if (unlikely(error)) {
 			if (error == AOP_TRUNCATED_PAGE) {
 				page_cache_release(page);
+				retry_find = 1;
 				goto find_page;
 			}
 			goto readpage_error;
@@ -1153,6 +1159,7 @@ readpage:
 					 */
 					unlock_page(page);
 					page_cache_release(page);
+					retry_find = 1;
 					goto find_page;
 				}
 				unlock_page(page);
@@ -1185,8 +1192,10 @@ no_cached_page:
 						index, GFP_KERNEL);
 		if (error) {
 			page_cache_release(page);
-			if (error == -EEXIST)
+			if (error == -EEXIST) {
+				retry_find = 1;
 				goto find_page;
+			}
 			desc->error = error;
 			goto out;
 		}
@@ -1543,6 +1552,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct page *page;
 	pgoff_t size;
 	int ret = 0;
+	int rw = !!(vmf->flags & FAULT_FLAG_WRITE);
 
 	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (offset >= size)
@@ -1552,6 +1562,10 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	 * Do we have something in the page cache already?
 	 */
 	page = find_get_page(mapping, offset);
+	if (page && page->mapping && PageUptodate(page))
+		page_cache_acct_hit(inode->i_sb, rw);
+	else
+		page_cache_acct_missed(inode->i_sb, rw);
 	if (likely(page)) {
 		/*
 		 * We found the page, so try async readahead before
@@ -2227,20 +2241,24 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping,
 		gfp_notmask = __GFP_FS;
 repeat:
 	page = find_lock_page(mapping, index);
-	if (page)
+	if (page) {
+		page_cache_acct_hit(mapping->host->i_sb, WRITE);
 		return page;
+	}
 
 	page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask);
 	if (!page)
-		return NULL;
+		goto out;
 	status = add_to_page_cache_lru(page, mapping, index,
 						GFP_KERNEL & ~gfp_notmask);
 	if (unlikely(status)) {
 		page_cache_release(page);
 		if (status == -EEXIST)
 			goto repeat;
-		return NULL;
+		page = NULL;
 	}
+out:
+	page_cache_acct_missed(mapping->host->i_sb, WRITE);
 	return page;
 }
 EXPORT_SYMBOL(grab_cache_page_write_begin);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-02  8:38   ` Liu Yuan
  0 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

Hit/Miss accountings are request-centric: that is, single request
would either cause one hit or one miss to be accounted for the very
first time that kernel query the page cache. In some rare error
conditions, kernel would re-query the page cache, but we donnot
account for it and ignore it for simplicity.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 mm/filemap.c |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 83a45d3..5388b2a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1009,10 +1009,15 @@ static void do_generic_file_read(struct file *filp, loff_t *ppos,
 		pgoff_t end_index;
 		loff_t isize;
 		unsigned long nr, ret;
+		int retry_find = 0;
 
 		cond_resched();
 find_page:
 		page = find_get_page(mapping, index);
+		if (likely(!retry_find) && page && PageUptodate(page))
+			page_cache_acct_hit(inode->i_sb, READ);
+		else
+			page_cache_acct_missed(inode->i_sb, READ);
 		if (!page) {
 			page_cache_sync_readahead(mapping,
 					ra, filp,
@@ -1137,6 +1142,7 @@ readpage:
 		if (unlikely(error)) {
 			if (error == AOP_TRUNCATED_PAGE) {
 				page_cache_release(page);
+				retry_find = 1;
 				goto find_page;
 			}
 			goto readpage_error;
@@ -1153,6 +1159,7 @@ readpage:
 					 */
 					unlock_page(page);
 					page_cache_release(page);
+					retry_find = 1;
 					goto find_page;
 				}
 				unlock_page(page);
@@ -1185,8 +1192,10 @@ no_cached_page:
 						index, GFP_KERNEL);
 		if (error) {
 			page_cache_release(page);
-			if (error == -EEXIST)
+			if (error == -EEXIST) {
+				retry_find = 1;
 				goto find_page;
+			}
 			desc->error = error;
 			goto out;
 		}
@@ -1543,6 +1552,7 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct page *page;
 	pgoff_t size;
 	int ret = 0;
+	int rw = !!(vmf->flags & FAULT_FLAG_WRITE);
 
 	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (offset >= size)
@@ -1552,6 +1562,10 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	 * Do we have something in the page cache already?
 	 */
 	page = find_get_page(mapping, offset);
+	if (page && page->mapping && PageUptodate(page))
+		page_cache_acct_hit(inode->i_sb, rw);
+	else
+		page_cache_acct_missed(inode->i_sb, rw);
 	if (likely(page)) {
 		/*
 		 * We found the page, so try async readahead before
@@ -2227,20 +2241,24 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping,
 		gfp_notmask = __GFP_FS;
 repeat:
 	page = find_lock_page(mapping, index);
-	if (page)
+	if (page) {
+		page_cache_acct_hit(mapping->host->i_sb, WRITE);
 		return page;
+	}
 
 	page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask);
 	if (!page)
-		return NULL;
+		goto out;
 	status = add_to_page_cache_lru(page, mapping, index,
 						GFP_KERNEL & ~gfp_notmask);
 	if (unlikely(status)) {
 		page_cache_release(page);
 		if (status == -EEXIST)
 			goto repeat;
-		return NULL;
+		page = NULL;
 	}
+out:
+	page_cache_acct_missed(mapping->host->i_sb, WRITE);
 	return page;
 }
 EXPORT_SYMBOL(grab_cache_page_write_begin);
-- 
1.7.0.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 5/5] mm: Add readpages accounting
       [not found] <no>
@ 2011-03-02  8:38   ` Liu Yuan
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

The _readpages_ counter simply counts how many pages the kernel
really request from the disk, either by readahead module or
aop->readpage() when readahead window equals 0.

This counter is request-centric and doesnot check read errors
since the read requests are issued to the block layer already.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 mm/filemap.c   |    1 +
 mm/readahead.c |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 5388b2a..d638391 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1137,6 +1137,7 @@ readpage:
 		 */
 		ClearPageError(page);
 		/* Start the actual read. The read will unlock the page. */
+		page_cache_acct_readpages(mapping->host->i_sb, 1);
 		error = mapping->a_ops->readpage(filp, page);
 
 		if (unlikely(error)) {
diff --git a/mm/readahead.c b/mm/readahead.c
index 77506a2..483acb8 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -112,6 +112,8 @@ static int read_pages(struct address_space *mapping, struct file *filp,
 	unsigned page_idx;
 	int ret;
 
+	page_cache_acct_readpages(mapping->host->i_sb, nr_pages);
+
 	if (mapping->a_ops->readpages) {
 		ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
 		/* Clean up the remaining pages */
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [RFC PATCH 5/5] mm: Add readpages accounting
@ 2011-03-02  8:38   ` Liu Yuan
  0 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-02  8:38 UTC (permalink / raw)
  To: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

From: Liu Yuan <tailai.ly@taobao.com>

The _readpages_ counter simply counts how many pages the kernel
really request from the disk, either by readahead module or
aop->readpage() when readahead window equals 0.

This counter is request-centric and doesnot check read errors
since the read requests are issued to the block layer already.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 mm/filemap.c   |    1 +
 mm/readahead.c |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 5388b2a..d638391 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1137,6 +1137,7 @@ readpage:
 		 */
 		ClearPageError(page);
 		/* Start the actual read. The read will unlock the page. */
+		page_cache_acct_readpages(mapping->host->i_sb, 1);
 		error = mapping->a_ops->readpage(filp, page);
 
 		if (unlikely(error)) {
diff --git a/mm/readahead.c b/mm/readahead.c
index 77506a2..483acb8 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -112,6 +112,8 @@ static int read_pages(struct address_space *mapping, struct file *filp,
 	unsigned page_idx;
 	int ret;
 
+	page_cache_acct_readpages(mapping->host->i_sb, nr_pages);
+
 	if (mapping->a_ops->readpages) {
 		ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
 		/* Clean up the remaining pages */
-- 
1.7.0.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02  8:38   ` Liu Yuan
@ 2011-03-02  8:45     ` Ingo Molnar
  -1 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-02  8:45 UTC (permalink / raw)
  To: Liu Yuan
  Cc: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo


* Liu Yuan <namei.unix@gmail.com> wrote:

> +		if (likely(!retry_find) && page && PageUptodate(page))
> +			page_cache_acct_hit(inode->i_sb, READ);
> +		else
> +			page_cache_acct_missed(inode->i_sb, READ);

Sigh.

This would make such a nice tracepoint or sw perf event. It could be collected in a 
'count' form, equivalent to the stats you are aiming for here, or it could even be 
traced, if someone is interested in such details.

It could be mixed with other events, enriching multiple apps at once.

But, instead of trying to improve those aspects of our existing instrumentation 
frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
the big picture and fragmenting the instrumentation space some more.

That trend is somewhat sad.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-02  8:45     ` Ingo Molnar
  0 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-02  8:45 UTC (permalink / raw)
  To: Liu Yuan
  Cc: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo


* Liu Yuan <namei.unix@gmail.com> wrote:

> +		if (likely(!retry_find) && page && PageUptodate(page))
> +			page_cache_acct_hit(inode->i_sb, READ);
> +		else
> +			page_cache_acct_missed(inode->i_sb, READ);

Sigh.

This would make such a nice tracepoint or sw perf event. It could be collected in a 
'count' form, equivalent to the stats you are aiming for here, or it could even be 
traced, if someone is interested in such details.

It could be mixed with other events, enriching multiple apps at once.

But, instead of trying to improve those aspects of our existing instrumentation 
frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
the big picture and fragmenting the instrumentation space some more.

That trend is somewhat sad.

Thanks,

	Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry
  2011-03-02  8:38   ` Liu Yuan
@ 2011-03-02 16:24     ` Randy Dunlap
  -1 siblings, 0 replies; 206+ messages in thread
From: Randy Dunlap @ 2011-03-02 16:24 UTC (permalink / raw)
  To: Liu Yuan; +Cc: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

On Wed,  2 Mar 2011 16:38:06 +0800 Liu Yuan wrote:

> From: Liu Yuan <tailai.ly@taobao.com>
> 
> Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
> ---
>  arch/x86/Kconfig.debug |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> index 615e188..f29e32d 100644
> --- a/arch/x86/Kconfig.debug
> +++ b/arch/x86/Kconfig.debug
> @@ -304,4 +304,13 @@ config DEBUG_STRICT_USER_COPY_CHECKS
>  
>  	  If unsure, or if you run an older (pre 4.4) gcc, say N.
>  
> +config PAGE_CACHE_ACCT
> +	bool "Page cache accounting"
> +	---help---
> +	  Enabling this options to account for page cache hit/missed number of
> +	  times. This would allow user space applications get better knowledge
> +	  of underlying page cache system by reading virtual file. The statitics
> +	  per partition are collected.
> +
> +	  If unsure, say N.
>  endmenu
> -- 

rewrite:

	  Enable this option to provide for page cache hit/miss counters.
	  This allows userspace applications to obtain better knowledge of the
	  underlying page cache subsystem by reading a virtual file.
	  Statistics are collect per partition.

questions:
	what virtual file?
	what kind of partition?

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry
@ 2011-03-02 16:24     ` Randy Dunlap
  0 siblings, 0 replies; 206+ messages in thread
From: Randy Dunlap @ 2011-03-02 16:24 UTC (permalink / raw)
  To: Liu Yuan; +Cc: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

On Wed,  2 Mar 2011 16:38:06 +0800 Liu Yuan wrote:

> From: Liu Yuan <tailai.ly@taobao.com>
> 
> Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
> ---
>  arch/x86/Kconfig.debug |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> index 615e188..f29e32d 100644
> --- a/arch/x86/Kconfig.debug
> +++ b/arch/x86/Kconfig.debug
> @@ -304,4 +304,13 @@ config DEBUG_STRICT_USER_COPY_CHECKS
>  
>  	  If unsure, or if you run an older (pre 4.4) gcc, say N.
>  
> +config PAGE_CACHE_ACCT
> +	bool "Page cache accounting"
> +	---help---
> +	  Enabling this options to account for page cache hit/missed number of
> +	  times. This would allow user space applications get better knowledge
> +	  of underlying page cache system by reading virtual file. The statitics
> +	  per partition are collected.
> +
> +	  If unsure, say N.
>  endmenu
> -- 

rewrite:

	  Enable this option to provide for page cache hit/miss counters.
	  This allows userspace applications to obtain better knowledge of the
	  underlying page cache subsystem by reading a virtual file.
	  Statistics are collect per partition.

questions:
	what virtual file?
	what kind of partition?

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02  8:45     ` Ingo Molnar
@ 2011-03-02 17:02       ` Dave Hansen
  -1 siblings, 0 replies; 206+ messages in thread
From: Dave Hansen @ 2011-03-02 17:02 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> But, instead of trying to improve those aspects of our existing instrumentation 
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> the big picture and fragmenting the instrumentation space some more.
> 
> That trend is somewhat sad. 

Go any handy examples of how you'd like to see these done?

We're trying to add a batch of these for transparent huge pages, and
there was a similar set for KSM, so there's certainly no shortage of
potential sites.

-- Dave


^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-02 17:02       ` Dave Hansen
  0 siblings, 0 replies; 206+ messages in thread
From: Dave Hansen @ 2011-03-02 17:02 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> But, instead of trying to improve those aspects of our existing instrumentation 
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> the big picture and fragmenting the instrumentation space some more.
> 
> That trend is somewhat sad. 

Go any handy examples of how you'd like to see these done?

We're trying to add a batch of these for transparent huge pages, and
there was a similar set for KSM, so there's certainly no shortage of
potential sites.

-- Dave

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02 17:02       ` Dave Hansen
@ 2011-03-02 18:49         ` Ingo Molnar
  -1 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-02 18:49 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo


* Dave Hansen <dave@linux.vnet.ibm.com> wrote:

> On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> > But, instead of trying to improve those aspects of our existing instrumentation 
> > frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> > the big picture and fragmenting the instrumentation space some more.
> > 
> > That trend is somewhat sad. 
> 
> Go any handy examples of how you'd like to see these done?

There's a very, very old branch in tip:tracing/mm (by Steve) that shows off some of 
the concepts that could be introduced, to 'dump' current MM state via an extension 
to the tracepoints APIs:

3383e37ea796: tracing, page-allocator: Add a postprocessing script for page-allocator-related ftrace events
c33b3596bc38: tracing, page-allocator: Add trace event for page traffic related to the buddy lists
0d524fb734bc: tracing, mm: Add trace events for anti-fragmentation falling back to other migratetypes
b9a28177eedf: tracing, page-allocator: Add trace events for page allocation and page freeing
807243eb20b2: Merge branch 'perfcounters/urgent' into tracing/mm
08b6cb88eeb5: perf_counter tools: Provide default bfd_demangle() function in case it's not around
eb4671011887: tracing/mm: rename 'trigger' file to 'dump_range'
1487a7a1ff99: tracing/mm: fix mapcount trace record field
dcac8cdac1d4: tracing/mm: add page frame snapshot trace

That's just a demo in essence - showing what things could be done in this area.

You can pick those commits up via running:

  http://people.redhat.com/mingo/tip.git/README

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-02 18:49         ` Ingo Molnar
  0 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-02 18:49 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo


* Dave Hansen <dave@linux.vnet.ibm.com> wrote:

> On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> > But, instead of trying to improve those aspects of our existing instrumentation 
> > frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> > the big picture and fragmenting the instrumentation space some more.
> > 
> > That trend is somewhat sad. 
> 
> Go any handy examples of how you'd like to see these done?

There's a very, very old branch in tip:tracing/mm (by Steve) that shows off some of 
the concepts that could be introduced, to 'dump' current MM state via an extension 
to the tracepoints APIs:

3383e37ea796: tracing, page-allocator: Add a postprocessing script for page-allocator-related ftrace events
c33b3596bc38: tracing, page-allocator: Add trace event for page traffic related to the buddy lists
0d524fb734bc: tracing, mm: Add trace events for anti-fragmentation falling back to other migratetypes
b9a28177eedf: tracing, page-allocator: Add trace events for page allocation and page freeing
807243eb20b2: Merge branch 'perfcounters/urgent' into tracing/mm
08b6cb88eeb5: perf_counter tools: Provide default bfd_demangle() function in case it's not around
eb4671011887: tracing/mm: rename 'trigger' file to 'dump_range'
1487a7a1ff99: tracing/mm: fix mapcount trace record field
dcac8cdac1d4: tracing/mm: add page frame snapshot trace

That's just a demo in essence - showing what things could be done in this area.

You can pick those commits up via running:

  http://people.redhat.com/mingo/tip.git/README

Thanks,

	Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02 18:49         ` Ingo Molnar
@ 2011-03-03  0:33           ` Wu Fengguang
  -1 siblings, 0 replies; 206+ messages in thread
From: Wu Fengguang @ 2011-03-03  0:33 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Dave Hansen, Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On Thu, Mar 03, 2011 at 02:49:53AM +0800, Ingo Molnar wrote:
> 
> * Dave Hansen <dave@linux.vnet.ibm.com> wrote:
> 
> > On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> > > But, instead of trying to improve those aspects of our existing instrumentation 
> > > frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> > > the big picture and fragmenting the instrumentation space some more.
> > > 
> > > That trend is somewhat sad. 
> > 
> > Go any handy examples of how you'd like to see these done?
> 
> There's a very, very old branch in tip:tracing/mm (by Steve) that shows off some of 
> the concepts that could be introduced, to 'dump' current MM state via an extension 
> to the tracepoints APIs:
> 
> 3383e37ea796: tracing, page-allocator: Add a postprocessing script for page-allocator-related ftrace events
> c33b3596bc38: tracing, page-allocator: Add trace event for page traffic related to the buddy lists
> 0d524fb734bc: tracing, mm: Add trace events for anti-fragmentation falling back to other migratetypes
> b9a28177eedf: tracing, page-allocator: Add trace events for page allocation and page freeing
> 807243eb20b2: Merge branch 'perfcounters/urgent' into tracing/mm
> 08b6cb88eeb5: perf_counter tools: Provide default bfd_demangle() function in case it's not around
> eb4671011887: tracing/mm: rename 'trigger' file to 'dump_range'
> 1487a7a1ff99: tracing/mm: fix mapcount trace record field
> dcac8cdac1d4: tracing/mm: add page frame snapshot trace
> 
> That's just a demo in essence - showing what things could be done in this area.
> 
> You can pick those commits up via running:
> 
>   http://people.redhat.com/mingo/tip.git/README

Ingo, sorry for remain silence on this topic. I'm actually updating the code.
Below is the most up-to-date version on top of 2.6.37.  I can post a patchset
for review after finished with the writeback patches.

Thanks,
Fengguang
---

Usage:

root@bay /home/wfg# echo / > /debug/tracing/objects/mm/pages/dump-fs
root@bay /home/wfg# cat /debug/tracing/trace

# The output has intermixed lines for inode and page
#         ino         size       cached      age(ms) dirty type first-opened-by file-name
      1507329         4096         8192       309042 ____  DIR          swapper /
#      index    len  page-flags count mapcount
           0      2 ____RU_____    1    0
      1786836        12288        40960       309026 ____  DIR          swapper /sbin
           0     10 ___ARU_____    1    0
      1786946        37312        40960       309024 ____  REG          swapper /sbin/init
           0      6 M__ARU_____    2    1
           6      1 M__A_U_____    2    1
           7      1 M__ARU_____    2    1
           8      2 _____U_____    1    0
      1507464            4         4096       309022 ____  LNK          swapper /lib64
           0      1 ___ARU_____    1    0
      1590173        12288            0       309021 ____  DIR          swapper /lib
      4563326           12         4096       309020 ____  LNK          swapper /lib/ld-linux-x86-64.so.2
           0      1 ___ARU_____    1    0
      4563295       128744       131072       309019 ____  REG          swapper /lib/ld-2.11.2.so
           0      1 M__ARU_____   21   20
           1      3 M__ARU_____   17   16
           4      4 M__ARU_____   20   19
           8      2 M__ARU_____   27   26
          10      3 M__ARU_____   20   19
          13      1 M__ARU_____   27   26
          14      1 M__ARU_____   26   25
          15      1 M__ARU_____   20   19
          16      1 M__ARU_____   18   17
          17      1 M__ARU_____    9    8
          18      1 M__A_U_____    4    3
          19      1 M__ARU_____   27   26
          20      1 M__ARU_____   17   16
          21      1 M__ARU_____   20   19
          22      1 M__ARU_____   27   26
          23      1 M__ARU_____   20   19
          24      1 M__ARU_____   26   25
          25      1 _____U_____    1    0
          26      1 M__A_U_____    4    3
          27      1 M__ARU_____   20   19
          28      4 _____U_____    1    0
      1525477        12288            0       309011 ____  DIR             init /etc
      1526463        64634        65536       309009 ____  REG             init /etc/ld.so.cache
           0      1 ___ARU_____    1    0
           1      1 _____U_____    1    0

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/include/trace/events/mm.h	2010-12-26 20:59:48.000000000 +0800
@@ -0,0 +1,164 @@
+#if !defined(_TRACE_MM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MM_H
+
+#include <linux/tracepoint.h>
+#include <linux/page-flags.h>
+#include <linux/memcontrol.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/kernel-page-flags.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mm
+
+extern struct trace_print_flags pageflag_names[];
+
+/**
+ * dump_page_frame - called by the trace page dump trigger
+ * @pfn: page frame number
+ * @page: pointer to the page frame
+ *
+ * This is a helper trace point into the dumping of the page frames.
+ * It will record various infromation about a page frame.
+ */
+TRACE_EVENT(dump_page_frame,
+
+	TP_PROTO(unsigned long pfn, struct page *page),
+
+	TP_ARGS(pfn, page),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	pfn		)
+		__field(	struct page *,	page		)
+		__field(	u64,		stable_flags	)
+		__field(	unsigned long,	flags		)
+		__field(	unsigned int,	count		)
+		__field(	unsigned int,	mapcount	)
+		__field(	unsigned long,	private		)
+		__field(	unsigned long,	mapping		)
+		__field(	unsigned long,	index		)
+	),
+
+	TP_fast_assign(
+		__entry->pfn		= pfn;
+		__entry->page		= page;
+		__entry->stable_flags	= stable_page_flags(page);
+		__entry->flags		= page->flags;
+		__entry->count		= atomic_read(&page->_count);
+		__entry->mapcount	= page_mapcount(page);
+		__entry->private	= page->private;
+		__entry->mapping	= (unsigned long)page->mapping;
+		__entry->index		= page->index;
+	),
+
+	TP_printk("%12lx %16p %8x %8x %16lx %16lx %16lx %s",
+		  __entry->pfn,
+		  __entry->page,
+		  __entry->count,
+		  __entry->mapcount,
+		  __entry->private,
+		  __entry->mapping,
+		  __entry->index,
+		  ftrace_print_flags_seq(p, "|",
+					 __entry->flags & PAGE_FLAGS_MASK,
+					 pageflag_names)
+	)
+);
+
+TRACE_EVENT(dump_page_cache,
+
+	TP_PROTO(struct page *page, unsigned long len),
+
+	TP_ARGS(page, len),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	index		)
+		__field(	unsigned long,	len		)
+		__field(	u64,		flags		)
+		__field(	unsigned int,	count		)
+		__field(	unsigned int,	mapcount	)
+	),
+
+	TP_fast_assign(
+		__entry->index		= page->index;
+		__entry->len		= len;
+		__entry->flags		= stable_page_flags(page);
+		__entry->count		= atomic_read(&page->_count);
+		__entry->mapcount	= page_mapcount(page);
+	),
+
+	TP_printk("%12lu %6lu %c%c%c%c%c%c%c%c%c%c%c %4u %4u",
+		  __entry->index,
+		  __entry->len,
+		  __entry->flags & (1ULL << KPF_MMAP)		? 'M' : '_',
+		  __entry->flags & (1ULL << KPF_MLOCKED)	? 'm' : '_',
+		  __entry->flags & (1ULL << KPF_UNEVICTABLE)	? 'u' : '_',
+		  __entry->flags & (1ULL << KPF_ACTIVE)		? 'A' : '_',
+		  __entry->flags & (1ULL << KPF_REFERENCED)	? 'R' : '_',
+		  __entry->flags & (1ULL << KPF_UPTODATE)	? 'U' : '_',
+		  __entry->flags & (1ULL << KPF_DIRTY)		? 'D' : '_',
+		  __entry->flags & (1ULL << KPF_WRITEBACK)	? 'W' : '_',
+		  __entry->flags & (1ULL << KPF_RECLAIM)	? 'I' : '_',
+		  __entry->flags & (1ULL << KPF_MAPPEDTODISK)	? 'd' : '_',
+		  __entry->flags & (1ULL << KPF_PRIVATE)	? 'P' : '_',
+		  __entry->count,
+		  __entry->mapcount)
+);
+
+
+#define show_inode_type(val)	__print_symbolic(val, 	   \
+				{ S_IFREG,	"REG"	}, \
+				{ S_IFDIR,	"DIR"	}, \
+				{ S_IFLNK,	"LNK"	}, \
+				{ S_IFBLK,	"BLK"	}, \
+				{ S_IFCHR,	"CHR"	}, \
+				{ S_IFIFO,	"FIFO"	}, \
+				{ S_IFSOCK,	"SOCK"	})
+
+TRACE_EVENT(dump_inode_cache,
+
+	TP_PROTO(struct inode *inode, char *name, int len),
+
+	TP_ARGS(inode, name, len),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	ino		)
+		__field(	loff_t,		size		) /* bytes */
+		__field(	loff_t,		cached		) /* bytes */
+		__field(	unsigned long,	age		) /*    ms */
+		__field(	unsigned long,	state		)
+		__field(	umode_t,	mode		)
+		__array(	char,		comm, TASK_COMM_LEN)
+		__dynamic_array(char,		file,	len	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->size	= i_size_read(inode);
+		__entry->cached	= inode->i_mapping->nrpages;
+		__entry->cached	<<= PAGE_CACHE_SHIFT;
+		__entry->age	= (jiffies - inode->dirtied_when) * 1000 / HZ;
+		__entry->state	= inode->i_state;
+		__entry->mode	= inode->i_mode;
+		memcpy(__entry->comm, inode->i_comm, TASK_COMM_LEN);
+		memcpy(__get_str(file), name, len);
+	),
+
+	TP_printk("%12lu %12llu %12llu %12lu %c%c%c%c %4s %16s %s",
+		  __entry->ino,
+		  __entry->size,
+		  __entry->cached,
+		  __entry->age,
+		  __entry->state & I_DIRTY_PAGES	? 'D' : '_',
+		  __entry->state & I_DIRTY_DATASYNC	? 'd' : '_',
+		  __entry->state & I_DIRTY_SYNC		? 'm' : '_',
+		  __entry->state & I_SYNC		? 'S' : '_',
+		  show_inode_type(__entry->mode & S_IFMT),
+		  __entry->comm,
+		  __get_str(file))
+);
+
+#endif /*  _TRACE_MM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--- mmotm.orig/kernel/trace/Makefile	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/kernel/trace/Makefile	2010-12-26 20:59:41.000000000 +0800
@@ -26,6 +26,7 @@ obj-$(CONFIG_RING_BUFFER) += ring_buffer
 obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o
 
 obj-$(CONFIG_TRACING) += trace.o
+obj-$(CONFIG_TRACING) += trace_objects.o
 obj-$(CONFIG_TRACING) += trace_output.o
 obj-$(CONFIG_TRACING) += trace_stat.o
 obj-$(CONFIG_TRACING) += trace_printk.o
@@ -53,6 +54,7 @@ endif
 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
 obj-$(CONFIG_EVENT_TRACING) += power-traces.o
+obj-$(CONFIG_EVENT_TRACING) += trace_mm.o
 ifeq ($(CONFIG_TRACING),y)
 obj-$(CONFIG_KGDB_KDB) += trace_kdb.o
 endif
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/kernel/trace/trace_mm.c	2010-12-26 20:59:41.000000000 +0800
@@ -0,0 +1,367 @@
+/*
+ * Trace mm pages
+ *
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * Code based on Matt Mackall's /proc/[kpagecount|kpageflags] code.
+ */
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/pagevec.h>
+#include <linux/writeback.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+#include "trace_output.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/mm.h>
+
+void trace_mm_page_frames(unsigned long start, unsigned long end,
+			  void (*trace)(unsigned long pfn, struct page *page))
+{
+	unsigned long pfn = start;
+	struct page *page;
+
+	if (start > max_pfn - 1)
+		return;
+
+	if (end > max_pfn)
+		end = max_pfn;
+
+	while (pfn < end) {
+		page = NULL;
+		if (pfn_valid(pfn))
+			page = pfn_to_page(pfn);
+		pfn++;
+		if (page)
+			trace(pfn, page);
+	}
+}
+
+static void trace_mm_page_frame(unsigned long pfn, struct page *page)
+{
+	trace_dump_page_frame(pfn, page);
+}
+
+static ssize_t
+trace_mm_pfn_range_read(struct file *filp, char __user *ubuf, size_t cnt,
+			loff_t *ppos)
+{
+	return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
+}
+
+
+/*
+ * recognized formats:
+ * 		"M N"	start=M, end=N
+ * 		"M"	start=M, end=M+1
+ * 		"M +N"	start=M, end=M+N-1
+ */
+static ssize_t
+trace_mm_pfn_range_write(struct file *filp, const char __user *ubuf, size_t cnt,
+			 loff_t *ppos)
+{
+	unsigned long start;
+	unsigned long end = 0;
+	char buf[64];
+	char *ptr;
+
+	if (cnt >= sizeof(buf))
+		return -EINVAL;
+
+	if (copy_from_user(&buf, ubuf, cnt))
+		return -EFAULT;
+
+	if (tracing_update_buffers() < 0)
+		return -ENOMEM;
+
+	if (trace_set_clr_event("mm", "dump_page_frame", 1))
+		return -EINVAL;
+
+	buf[cnt] = 0;
+
+	start = simple_strtoul(buf, &ptr, 0);
+
+	for (; *ptr; ptr++) {
+		if (isdigit(*ptr)) {
+			if (*(ptr - 1) == '+')
+				end = start;
+			end += simple_strtoul(ptr, NULL, 0);
+			break;
+		}
+	}
+	if (!*ptr)
+		end = start + 1;
+
+	trace_mm_page_frames(start, end, trace_mm_page_frame);
+
+	return cnt;
+}
+
+static const struct file_operations trace_mm_fops = {
+	.open		= tracing_open_generic,
+	.read		= trace_mm_pfn_range_read,
+	.write		= trace_mm_pfn_range_write,
+};
+
+static struct dentry *trace_objects_mm_dir(void)
+{
+	static struct dentry *d_mm;
+	struct dentry *d_objects;
+
+	if (d_mm)
+		return d_mm;
+
+	d_objects = trace_objects_dir();
+	if (!d_objects)
+		return NULL;
+
+	d_mm = debugfs_create_dir("mm", d_objects);
+	if (!d_mm)
+		pr_warning("Could not create 'objects/mm' directory\n");
+
+	return d_mm;
+}
+
+static unsigned long page_flags(struct page *page)
+{
+	return page->flags & ((1 << NR_PAGEFLAGS) - 1);
+}
+
+static int pages_similar(struct page *page0, struct page *page)
+{
+	if (page_flags(page0) != page_flags(page))
+		return 0;
+
+	if (page_count(page0) != page_count(page))
+		return 0;
+
+	if (page_mapcount(page0) != page_mapcount(page))
+		return 0;
+
+	return 1;
+}
+
+static void dump_pagecache(struct address_space *mapping)
+{
+	unsigned long nr_pages;
+	struct page *pages[PAGEVEC_SIZE];
+	struct page *uninitialized_var(page0);
+	struct page *page;
+	unsigned long start = 0;
+	unsigned long len = 0;
+	int i;
+
+	for (;;) {
+		rcu_read_lock();
+		nr_pages = radix_tree_gang_lookup(&mapping->page_tree,
+				(void **)pages, start + len, PAGEVEC_SIZE);
+		rcu_read_unlock();
+
+		if (nr_pages == 0) {
+			if (len)
+				trace_dump_page_cache(page0, len);
+			return;
+		}
+
+		for (i = 0; i < nr_pages; i++) {
+			page = pages[i];
+
+			if (len &&
+			    page->index == start + len &&
+			    pages_similar(page0, page))
+				len++;
+			else {
+				if (len)
+					trace_dump_page_cache(page0, len);
+				page0 = page;
+				start = page->index;
+				len = 1;
+			}
+		}
+		cond_resched();
+	}
+}
+
+static void dump_inode_cache(struct inode *inode,
+			     char *name_buf,
+			     struct vfsmount *mnt)
+{
+	struct path path = {
+		.mnt = mnt,
+		.dentry = d_find_alias(inode)
+	};
+	char *name;
+	int len;
+
+	if (!mnt) {
+		trace_dump_inode_cache(inode, name_buf, strlen(name_buf));
+		return;
+	}
+
+	if (!path.dentry) {
+		trace_dump_inode_cache(inode, "", 1);
+		return;
+	}
+
+	name = d_path(&path, name_buf, PAGE_SIZE);
+	if (IS_ERR(name)) {
+		name = "";
+		len = 1;
+	} else
+		len = PAGE_SIZE + name_buf - name;
+
+	trace_dump_inode_cache(inode, name, len);
+
+	if (path.dentry)
+		dput(path.dentry);
+}
+
+static void dump_fs_pagecache(struct super_block *sb, struct vfsmount *mnt)
+{
+	struct inode *inode;
+	struct inode *prev_inode = NULL;
+	char *name_buf;
+
+	name_buf = (char *)__get_free_page(GFP_TEMPORARY);
+	if (!name_buf)
+		return;
+
+	down_read(&sb->s_umount);
+	if (!sb->s_root)
+		goto out;
+
+	spin_lock(&inode_lock);
+	list_for_each_entry_reverse(inode, &sb->s_inodes, i_sb_list) {
+		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
+			continue;
+		__iget(inode);
+		spin_unlock(&inode_lock);
+		dump_inode_cache(inode, name_buf, mnt);
+		if (inode->i_mapping->nrpages)
+			dump_pagecache(inode->i_mapping);
+		iput(prev_inode);
+		prev_inode = inode;
+		cond_resched();
+		spin_lock(&inode_lock);
+	}
+	spin_unlock(&inode_lock);
+	iput(prev_inode);
+out:
+	up_read(&sb->s_umount);
+	free_page((unsigned long)name_buf);
+}
+
+static ssize_t
+trace_pagecache_write(struct file *filp, const char __user *ubuf, size_t count,
+		      loff_t *ppos)
+{
+	struct file *file = NULL;
+	char *name;
+	int err = 0;
+
+	if (count <= 1)
+		return -EINVAL;
+	if (count >= PAGE_SIZE)
+		return -ENAMETOOLONG;
+
+	name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	if (copy_from_user(name, ubuf, count)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	/* strip the newline added by `echo` */
+	if (name[count-1] == '\n')
+		name[count-1] = '\0';
+	else
+		name[count] = '\0';
+
+	file = filp_open(name, O_RDONLY|O_LARGEFILE, 0);
+	if (IS_ERR(file)) {
+		err = PTR_ERR(file);
+		file = NULL;
+		goto out;
+	}
+
+	if (tracing_update_buffers() < 0) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (trace_set_clr_event("mm", "dump_page_cache", 1)) {
+		err = -EINVAL;
+		goto out;
+	}
+	if (trace_set_clr_event("mm", "dump_inode_cache", 1)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (filp->f_path.dentry->d_inode->i_private) {
+		dump_fs_pagecache(file->f_path.dentry->d_sb, file->f_path.mnt);
+	} else {
+		dump_inode_cache(file->f_mapping->host, name, NULL);
+		dump_pagecache(file->f_mapping);
+	}
+
+out:
+	if (file)
+		fput(file);
+	kfree(name);
+
+	return err ? err : count;
+}
+
+static const struct file_operations trace_pagecache_fops = {
+	.open		= tracing_open_generic,
+	.read		= trace_mm_pfn_range_read,
+	.write		= trace_pagecache_write,
+};
+
+static struct dentry *trace_objects_mm_pages_dir(void)
+{
+	static struct dentry *d_pages;
+	struct dentry *d_mm;
+
+	if (d_pages)
+		return d_pages;
+
+	d_mm = trace_objects_mm_dir();
+	if (!d_mm)
+		return NULL;
+
+	d_pages = debugfs_create_dir("pages", d_mm);
+	if (!d_pages)
+		pr_warning("Could not create debugfs "
+			   "'objects/mm/pages' directory\n");
+
+	return d_pages;
+}
+
+static __init int trace_objects_mm_init(void)
+{
+	struct dentry *d_pages;
+
+	d_pages = trace_objects_mm_pages_dir();
+	if (!d_pages)
+		return 0;
+
+	trace_create_file("dump-pfn", 0600, d_pages, NULL,
+			  &trace_mm_fops);
+
+	trace_create_file("dump-file", 0600, d_pages, NULL,
+			  &trace_pagecache_fops);
+
+	trace_create_file("dump-fs", 0600, d_pages, (void *)1,
+			  &trace_pagecache_fops);
+
+	return 0;
+}
+fs_initcall(trace_objects_mm_init);
--- mmotm.orig/kernel/trace/trace.h	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/kernel/trace/trace.h	2010-12-26 20:59:41.000000000 +0800
@@ -295,6 +295,7 @@ struct dentry *trace_create_file(const c
 				 const struct file_operations *fops);
 
 struct dentry *tracing_init_dentry(void);
+struct dentry *trace_objects_dir(void);
 
 struct ring_buffer_event;
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/kernel/trace/trace_objects.c	2010-12-26 20:59:41.000000000 +0800
@@ -0,0 +1,26 @@
+#include <linux/debugfs.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+struct dentry *trace_objects_dir(void)
+{
+	static struct dentry *d_objects;
+	struct dentry *d_tracer;
+
+	if (d_objects)
+		return d_objects;
+
+	d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return NULL;
+
+	d_objects = debugfs_create_dir("objects", d_tracer);
+	if (!d_objects)
+		pr_warning("Could not create debugfs "
+			   "'objects' directory\n");
+
+	return d_objects;
+}
+
+
--- mmotm.orig/mm/page_alloc.c	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/mm/page_alloc.c	2010-12-26 20:59:41.000000000 +0800
@@ -5493,7 +5493,7 @@ bool is_free_buddy_page(struct page *pag
 }
 #endif
 
-static struct trace_print_flags pageflag_names[] = {
+struct trace_print_flags pageflag_names[] = {
 	{1UL << PG_locked,		"locked"	},
 	{1UL << PG_error,		"error"		},
 	{1UL << PG_referenced,		"referenced"	},
@@ -5541,7 +5541,7 @@ static void dump_page_flags(unsigned lon
 	printk(KERN_ALERT "page flags: %#lx(", flags);
 
 	/* remove zone id */
-	flags &= (1UL << NR_PAGEFLAGS) - 1;
+	flags &= PAGE_FLAGS_MASK;
 
 	for (i = 0; pageflag_names[i].name && flags; i++) {
 
--- mmotm.orig/include/linux/page-flags.h	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/include/linux/page-flags.h	2010-12-26 20:59:41.000000000 +0800
@@ -414,6 +414,7 @@ static inline void __ClearPageTail(struc
  * there has been a kernel bug or struct page corruption.
  */
 #define PAGE_FLAGS_CHECK_AT_PREP	((1 << NR_PAGEFLAGS) - 1)
+#define PAGE_FLAGS_MASK			((1 << NR_PAGEFLAGS) - 1)
 
 #define PAGE_FLAGS_PRIVATE				\
 	(1 << PG_private | 1 << PG_private_2)
--- mmotm.orig/fs/inode.c	2010-12-26 20:58:45.000000000 +0800
+++ mmotm/fs/inode.c	2010-12-26 21:00:09.000000000 +0800
@@ -182,7 +182,13 @@ int inode_init_always(struct super_block
 	inode->i_bdev = NULL;
 	inode->i_cdev = NULL;
 	inode->i_rdev = 0;
-	inode->dirtied_when = 0;
+
+	/*
+	 * This records inode load time. It will be invalidated once inode is
+	 * dirtied, or jiffies wraps around. Despite the pitfalls it still
+	 * provides useful information for some use cases like fastboot.
+	 */
+	inode->dirtied_when = jiffies;
 
 	if (security_inode_alloc(inode))
 		goto out;
@@ -226,6 +232,9 @@ int inode_init_always(struct super_block
 
 	percpu_counter_inc(&nr_inodes);
 
+	BUILD_BUG_ON(sizeof(inode->i_comm) != TASK_COMM_LEN);
+	memcpy(inode->i_comm, current->comm, TASK_COMM_LEN);
+
 	return 0;
 out:
 	return -ENOMEM;
--- mmotm.orig/include/linux/fs.h	2010-12-26 20:59:50.000000000 +0800
+++ mmotm/include/linux/fs.h	2010-12-26 21:00:09.000000000 +0800
@@ -800,6 +800,8 @@ struct inode {
 	struct posix_acl	*i_default_acl;
 #endif
 	void			*i_private; /* fs or device private pointer */
+
+	char			i_comm[16]; /* first opened by */
 };
 
 static inline int inode_unhashed(struct inode *inode)

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-03  0:33           ` Wu Fengguang
  0 siblings, 0 replies; 206+ messages in thread
From: Wu Fengguang @ 2011-03-03  0:33 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Dave Hansen, Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On Thu, Mar 03, 2011 at 02:49:53AM +0800, Ingo Molnar wrote:
> 
> * Dave Hansen <dave@linux.vnet.ibm.com> wrote:
> 
> > On Wed, 2011-03-02 at 09:45 +0100, Ingo Molnar wrote:
> > > But, instead of trying to improve those aspects of our existing instrumentation 
> > > frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> > > the big picture and fragmenting the instrumentation space some more.
> > > 
> > > That trend is somewhat sad. 
> > 
> > Go any handy examples of how you'd like to see these done?
> 
> There's a very, very old branch in tip:tracing/mm (by Steve) that shows off some of 
> the concepts that could be introduced, to 'dump' current MM state via an extension 
> to the tracepoints APIs:
> 
> 3383e37ea796: tracing, page-allocator: Add a postprocessing script for page-allocator-related ftrace events
> c33b3596bc38: tracing, page-allocator: Add trace event for page traffic related to the buddy lists
> 0d524fb734bc: tracing, mm: Add trace events for anti-fragmentation falling back to other migratetypes
> b9a28177eedf: tracing, page-allocator: Add trace events for page allocation and page freeing
> 807243eb20b2: Merge branch 'perfcounters/urgent' into tracing/mm
> 08b6cb88eeb5: perf_counter tools: Provide default bfd_demangle() function in case it's not around
> eb4671011887: tracing/mm: rename 'trigger' file to 'dump_range'
> 1487a7a1ff99: tracing/mm: fix mapcount trace record field
> dcac8cdac1d4: tracing/mm: add page frame snapshot trace
> 
> That's just a demo in essence - showing what things could be done in this area.
> 
> You can pick those commits up via running:
> 
>   http://people.redhat.com/mingo/tip.git/README

Ingo, sorry for remain silence on this topic. I'm actually updating the code.
Below is the most up-to-date version on top of 2.6.37.  I can post a patchset
for review after finished with the writeback patches.

Thanks,
Fengguang
---

Usage:

root@bay /home/wfg# echo / > /debug/tracing/objects/mm/pages/dump-fs
root@bay /home/wfg# cat /debug/tracing/trace

# The output has intermixed lines for inode and page
#         ino         size       cached      age(ms) dirty type first-opened-by file-name
      1507329         4096         8192       309042 ____  DIR          swapper /
#      index    len  page-flags count mapcount
           0      2 ____RU_____    1    0
      1786836        12288        40960       309026 ____  DIR          swapper /sbin
           0     10 ___ARU_____    1    0
      1786946        37312        40960       309024 ____  REG          swapper /sbin/init
           0      6 M__ARU_____    2    1
           6      1 M__A_U_____    2    1
           7      1 M__ARU_____    2    1
           8      2 _____U_____    1    0
      1507464            4         4096       309022 ____  LNK          swapper /lib64
           0      1 ___ARU_____    1    0
      1590173        12288            0       309021 ____  DIR          swapper /lib
      4563326           12         4096       309020 ____  LNK          swapper /lib/ld-linux-x86-64.so.2
           0      1 ___ARU_____    1    0
      4563295       128744       131072       309019 ____  REG          swapper /lib/ld-2.11.2.so
           0      1 M__ARU_____   21   20
           1      3 M__ARU_____   17   16
           4      4 M__ARU_____   20   19
           8      2 M__ARU_____   27   26
          10      3 M__ARU_____   20   19
          13      1 M__ARU_____   27   26
          14      1 M__ARU_____   26   25
          15      1 M__ARU_____   20   19
          16      1 M__ARU_____   18   17
          17      1 M__ARU_____    9    8
          18      1 M__A_U_____    4    3
          19      1 M__ARU_____   27   26
          20      1 M__ARU_____   17   16
          21      1 M__ARU_____   20   19
          22      1 M__ARU_____   27   26
          23      1 M__ARU_____   20   19
          24      1 M__ARU_____   26   25
          25      1 _____U_____    1    0
          26      1 M__A_U_____    4    3
          27      1 M__ARU_____   20   19
          28      4 _____U_____    1    0
      1525477        12288            0       309011 ____  DIR             init /etc
      1526463        64634        65536       309009 ____  REG             init /etc/ld.so.cache
           0      1 ___ARU_____    1    0
           1      1 _____U_____    1    0

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/include/trace/events/mm.h	2010-12-26 20:59:48.000000000 +0800
@@ -0,0 +1,164 @@
+#if !defined(_TRACE_MM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MM_H
+
+#include <linux/tracepoint.h>
+#include <linux/page-flags.h>
+#include <linux/memcontrol.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/kernel-page-flags.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mm
+
+extern struct trace_print_flags pageflag_names[];
+
+/**
+ * dump_page_frame - called by the trace page dump trigger
+ * @pfn: page frame number
+ * @page: pointer to the page frame
+ *
+ * This is a helper trace point into the dumping of the page frames.
+ * It will record various infromation about a page frame.
+ */
+TRACE_EVENT(dump_page_frame,
+
+	TP_PROTO(unsigned long pfn, struct page *page),
+
+	TP_ARGS(pfn, page),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	pfn		)
+		__field(	struct page *,	page		)
+		__field(	u64,		stable_flags	)
+		__field(	unsigned long,	flags		)
+		__field(	unsigned int,	count		)
+		__field(	unsigned int,	mapcount	)
+		__field(	unsigned long,	private		)
+		__field(	unsigned long,	mapping		)
+		__field(	unsigned long,	index		)
+	),
+
+	TP_fast_assign(
+		__entry->pfn		= pfn;
+		__entry->page		= page;
+		__entry->stable_flags	= stable_page_flags(page);
+		__entry->flags		= page->flags;
+		__entry->count		= atomic_read(&page->_count);
+		__entry->mapcount	= page_mapcount(page);
+		__entry->private	= page->private;
+		__entry->mapping	= (unsigned long)page->mapping;
+		__entry->index		= page->index;
+	),
+
+	TP_printk("%12lx %16p %8x %8x %16lx %16lx %16lx %s",
+		  __entry->pfn,
+		  __entry->page,
+		  __entry->count,
+		  __entry->mapcount,
+		  __entry->private,
+		  __entry->mapping,
+		  __entry->index,
+		  ftrace_print_flags_seq(p, "|",
+					 __entry->flags & PAGE_FLAGS_MASK,
+					 pageflag_names)
+	)
+);
+
+TRACE_EVENT(dump_page_cache,
+
+	TP_PROTO(struct page *page, unsigned long len),
+
+	TP_ARGS(page, len),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	index		)
+		__field(	unsigned long,	len		)
+		__field(	u64,		flags		)
+		__field(	unsigned int,	count		)
+		__field(	unsigned int,	mapcount	)
+	),
+
+	TP_fast_assign(
+		__entry->index		= page->index;
+		__entry->len		= len;
+		__entry->flags		= stable_page_flags(page);
+		__entry->count		= atomic_read(&page->_count);
+		__entry->mapcount	= page_mapcount(page);
+	),
+
+	TP_printk("%12lu %6lu %c%c%c%c%c%c%c%c%c%c%c %4u %4u",
+		  __entry->index,
+		  __entry->len,
+		  __entry->flags & (1ULL << KPF_MMAP)		? 'M' : '_',
+		  __entry->flags & (1ULL << KPF_MLOCKED)	? 'm' : '_',
+		  __entry->flags & (1ULL << KPF_UNEVICTABLE)	? 'u' : '_',
+		  __entry->flags & (1ULL << KPF_ACTIVE)		? 'A' : '_',
+		  __entry->flags & (1ULL << KPF_REFERENCED)	? 'R' : '_',
+		  __entry->flags & (1ULL << KPF_UPTODATE)	? 'U' : '_',
+		  __entry->flags & (1ULL << KPF_DIRTY)		? 'D' : '_',
+		  __entry->flags & (1ULL << KPF_WRITEBACK)	? 'W' : '_',
+		  __entry->flags & (1ULL << KPF_RECLAIM)	? 'I' : '_',
+		  __entry->flags & (1ULL << KPF_MAPPEDTODISK)	? 'd' : '_',
+		  __entry->flags & (1ULL << KPF_PRIVATE)	? 'P' : '_',
+		  __entry->count,
+		  __entry->mapcount)
+);
+
+
+#define show_inode_type(val)	__print_symbolic(val, 	   \
+				{ S_IFREG,	"REG"	}, \
+				{ S_IFDIR,	"DIR"	}, \
+				{ S_IFLNK,	"LNK"	}, \
+				{ S_IFBLK,	"BLK"	}, \
+				{ S_IFCHR,	"CHR"	}, \
+				{ S_IFIFO,	"FIFO"	}, \
+				{ S_IFSOCK,	"SOCK"	})
+
+TRACE_EVENT(dump_inode_cache,
+
+	TP_PROTO(struct inode *inode, char *name, int len),
+
+	TP_ARGS(inode, name, len),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	ino		)
+		__field(	loff_t,		size		) /* bytes */
+		__field(	loff_t,		cached		) /* bytes */
+		__field(	unsigned long,	age		) /*    ms */
+		__field(	unsigned long,	state		)
+		__field(	umode_t,	mode		)
+		__array(	char,		comm, TASK_COMM_LEN)
+		__dynamic_array(char,		file,	len	)
+	),
+
+	TP_fast_assign(
+		__entry->ino	= inode->i_ino;
+		__entry->size	= i_size_read(inode);
+		__entry->cached	= inode->i_mapping->nrpages;
+		__entry->cached	<<= PAGE_CACHE_SHIFT;
+		__entry->age	= (jiffies - inode->dirtied_when) * 1000 / HZ;
+		__entry->state	= inode->i_state;
+		__entry->mode	= inode->i_mode;
+		memcpy(__entry->comm, inode->i_comm, TASK_COMM_LEN);
+		memcpy(__get_str(file), name, len);
+	),
+
+	TP_printk("%12lu %12llu %12llu %12lu %c%c%c%c %4s %16s %s",
+		  __entry->ino,
+		  __entry->size,
+		  __entry->cached,
+		  __entry->age,
+		  __entry->state & I_DIRTY_PAGES	? 'D' : '_',
+		  __entry->state & I_DIRTY_DATASYNC	? 'd' : '_',
+		  __entry->state & I_DIRTY_SYNC		? 'm' : '_',
+		  __entry->state & I_SYNC		? 'S' : '_',
+		  show_inode_type(__entry->mode & S_IFMT),
+		  __entry->comm,
+		  __get_str(file))
+);
+
+#endif /*  _TRACE_MM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--- mmotm.orig/kernel/trace/Makefile	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/kernel/trace/Makefile	2010-12-26 20:59:41.000000000 +0800
@@ -26,6 +26,7 @@ obj-$(CONFIG_RING_BUFFER) += ring_buffer
 obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o
 
 obj-$(CONFIG_TRACING) += trace.o
+obj-$(CONFIG_TRACING) += trace_objects.o
 obj-$(CONFIG_TRACING) += trace_output.o
 obj-$(CONFIG_TRACING) += trace_stat.o
 obj-$(CONFIG_TRACING) += trace_printk.o
@@ -53,6 +54,7 @@ endif
 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o
 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
 obj-$(CONFIG_EVENT_TRACING) += power-traces.o
+obj-$(CONFIG_EVENT_TRACING) += trace_mm.o
 ifeq ($(CONFIG_TRACING),y)
 obj-$(CONFIG_KGDB_KDB) += trace_kdb.o
 endif
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/kernel/trace/trace_mm.c	2010-12-26 20:59:41.000000000 +0800
@@ -0,0 +1,367 @@
+/*
+ * Trace mm pages
+ *
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * Code based on Matt Mackall's /proc/[kpagecount|kpageflags] code.
+ */
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/pagevec.h>
+#include <linux/writeback.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+#include "trace_output.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/mm.h>
+
+void trace_mm_page_frames(unsigned long start, unsigned long end,
+			  void (*trace)(unsigned long pfn, struct page *page))
+{
+	unsigned long pfn = start;
+	struct page *page;
+
+	if (start > max_pfn - 1)
+		return;
+
+	if (end > max_pfn)
+		end = max_pfn;
+
+	while (pfn < end) {
+		page = NULL;
+		if (pfn_valid(pfn))
+			page = pfn_to_page(pfn);
+		pfn++;
+		if (page)
+			trace(pfn, page);
+	}
+}
+
+static void trace_mm_page_frame(unsigned long pfn, struct page *page)
+{
+	trace_dump_page_frame(pfn, page);
+}
+
+static ssize_t
+trace_mm_pfn_range_read(struct file *filp, char __user *ubuf, size_t cnt,
+			loff_t *ppos)
+{
+	return simple_read_from_buffer(ubuf, cnt, ppos, "0\n", 2);
+}
+
+
+/*
+ * recognized formats:
+ * 		"M N"	start=M, end=N
+ * 		"M"	start=M, end=M+1
+ * 		"M +N"	start=M, end=M+N-1
+ */
+static ssize_t
+trace_mm_pfn_range_write(struct file *filp, const char __user *ubuf, size_t cnt,
+			 loff_t *ppos)
+{
+	unsigned long start;
+	unsigned long end = 0;
+	char buf[64];
+	char *ptr;
+
+	if (cnt >= sizeof(buf))
+		return -EINVAL;
+
+	if (copy_from_user(&buf, ubuf, cnt))
+		return -EFAULT;
+
+	if (tracing_update_buffers() < 0)
+		return -ENOMEM;
+
+	if (trace_set_clr_event("mm", "dump_page_frame", 1))
+		return -EINVAL;
+
+	buf[cnt] = 0;
+
+	start = simple_strtoul(buf, &ptr, 0);
+
+	for (; *ptr; ptr++) {
+		if (isdigit(*ptr)) {
+			if (*(ptr - 1) == '+')
+				end = start;
+			end += simple_strtoul(ptr, NULL, 0);
+			break;
+		}
+	}
+	if (!*ptr)
+		end = start + 1;
+
+	trace_mm_page_frames(start, end, trace_mm_page_frame);
+
+	return cnt;
+}
+
+static const struct file_operations trace_mm_fops = {
+	.open		= tracing_open_generic,
+	.read		= trace_mm_pfn_range_read,
+	.write		= trace_mm_pfn_range_write,
+};
+
+static struct dentry *trace_objects_mm_dir(void)
+{
+	static struct dentry *d_mm;
+	struct dentry *d_objects;
+
+	if (d_mm)
+		return d_mm;
+
+	d_objects = trace_objects_dir();
+	if (!d_objects)
+		return NULL;
+
+	d_mm = debugfs_create_dir("mm", d_objects);
+	if (!d_mm)
+		pr_warning("Could not create 'objects/mm' directory\n");
+
+	return d_mm;
+}
+
+static unsigned long page_flags(struct page *page)
+{
+	return page->flags & ((1 << NR_PAGEFLAGS) - 1);
+}
+
+static int pages_similar(struct page *page0, struct page *page)
+{
+	if (page_flags(page0) != page_flags(page))
+		return 0;
+
+	if (page_count(page0) != page_count(page))
+		return 0;
+
+	if (page_mapcount(page0) != page_mapcount(page))
+		return 0;
+
+	return 1;
+}
+
+static void dump_pagecache(struct address_space *mapping)
+{
+	unsigned long nr_pages;
+	struct page *pages[PAGEVEC_SIZE];
+	struct page *uninitialized_var(page0);
+	struct page *page;
+	unsigned long start = 0;
+	unsigned long len = 0;
+	int i;
+
+	for (;;) {
+		rcu_read_lock();
+		nr_pages = radix_tree_gang_lookup(&mapping->page_tree,
+				(void **)pages, start + len, PAGEVEC_SIZE);
+		rcu_read_unlock();
+
+		if (nr_pages == 0) {
+			if (len)
+				trace_dump_page_cache(page0, len);
+			return;
+		}
+
+		for (i = 0; i < nr_pages; i++) {
+			page = pages[i];
+
+			if (len &&
+			    page->index == start + len &&
+			    pages_similar(page0, page))
+				len++;
+			else {
+				if (len)
+					trace_dump_page_cache(page0, len);
+				page0 = page;
+				start = page->index;
+				len = 1;
+			}
+		}
+		cond_resched();
+	}
+}
+
+static void dump_inode_cache(struct inode *inode,
+			     char *name_buf,
+			     struct vfsmount *mnt)
+{
+	struct path path = {
+		.mnt = mnt,
+		.dentry = d_find_alias(inode)
+	};
+	char *name;
+	int len;
+
+	if (!mnt) {
+		trace_dump_inode_cache(inode, name_buf, strlen(name_buf));
+		return;
+	}
+
+	if (!path.dentry) {
+		trace_dump_inode_cache(inode, "", 1);
+		return;
+	}
+
+	name = d_path(&path, name_buf, PAGE_SIZE);
+	if (IS_ERR(name)) {
+		name = "";
+		len = 1;
+	} else
+		len = PAGE_SIZE + name_buf - name;
+
+	trace_dump_inode_cache(inode, name, len);
+
+	if (path.dentry)
+		dput(path.dentry);
+}
+
+static void dump_fs_pagecache(struct super_block *sb, struct vfsmount *mnt)
+{
+	struct inode *inode;
+	struct inode *prev_inode = NULL;
+	char *name_buf;
+
+	name_buf = (char *)__get_free_page(GFP_TEMPORARY);
+	if (!name_buf)
+		return;
+
+	down_read(&sb->s_umount);
+	if (!sb->s_root)
+		goto out;
+
+	spin_lock(&inode_lock);
+	list_for_each_entry_reverse(inode, &sb->s_inodes, i_sb_list) {
+		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
+			continue;
+		__iget(inode);
+		spin_unlock(&inode_lock);
+		dump_inode_cache(inode, name_buf, mnt);
+		if (inode->i_mapping->nrpages)
+			dump_pagecache(inode->i_mapping);
+		iput(prev_inode);
+		prev_inode = inode;
+		cond_resched();
+		spin_lock(&inode_lock);
+	}
+	spin_unlock(&inode_lock);
+	iput(prev_inode);
+out:
+	up_read(&sb->s_umount);
+	free_page((unsigned long)name_buf);
+}
+
+static ssize_t
+trace_pagecache_write(struct file *filp, const char __user *ubuf, size_t count,
+		      loff_t *ppos)
+{
+	struct file *file = NULL;
+	char *name;
+	int err = 0;
+
+	if (count <= 1)
+		return -EINVAL;
+	if (count >= PAGE_SIZE)
+		return -ENAMETOOLONG;
+
+	name = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	if (copy_from_user(name, ubuf, count)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	/* strip the newline added by `echo` */
+	if (name[count-1] == '\n')
+		name[count-1] = '\0';
+	else
+		name[count] = '\0';
+
+	file = filp_open(name, O_RDONLY|O_LARGEFILE, 0);
+	if (IS_ERR(file)) {
+		err = PTR_ERR(file);
+		file = NULL;
+		goto out;
+	}
+
+	if (tracing_update_buffers() < 0) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (trace_set_clr_event("mm", "dump_page_cache", 1)) {
+		err = -EINVAL;
+		goto out;
+	}
+	if (trace_set_clr_event("mm", "dump_inode_cache", 1)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (filp->f_path.dentry->d_inode->i_private) {
+		dump_fs_pagecache(file->f_path.dentry->d_sb, file->f_path.mnt);
+	} else {
+		dump_inode_cache(file->f_mapping->host, name, NULL);
+		dump_pagecache(file->f_mapping);
+	}
+
+out:
+	if (file)
+		fput(file);
+	kfree(name);
+
+	return err ? err : count;
+}
+
+static const struct file_operations trace_pagecache_fops = {
+	.open		= tracing_open_generic,
+	.read		= trace_mm_pfn_range_read,
+	.write		= trace_pagecache_write,
+};
+
+static struct dentry *trace_objects_mm_pages_dir(void)
+{
+	static struct dentry *d_pages;
+	struct dentry *d_mm;
+
+	if (d_pages)
+		return d_pages;
+
+	d_mm = trace_objects_mm_dir();
+	if (!d_mm)
+		return NULL;
+
+	d_pages = debugfs_create_dir("pages", d_mm);
+	if (!d_pages)
+		pr_warning("Could not create debugfs "
+			   "'objects/mm/pages' directory\n");
+
+	return d_pages;
+}
+
+static __init int trace_objects_mm_init(void)
+{
+	struct dentry *d_pages;
+
+	d_pages = trace_objects_mm_pages_dir();
+	if (!d_pages)
+		return 0;
+
+	trace_create_file("dump-pfn", 0600, d_pages, NULL,
+			  &trace_mm_fops);
+
+	trace_create_file("dump-file", 0600, d_pages, NULL,
+			  &trace_pagecache_fops);
+
+	trace_create_file("dump-fs", 0600, d_pages, (void *)1,
+			  &trace_pagecache_fops);
+
+	return 0;
+}
+fs_initcall(trace_objects_mm_init);
--- mmotm.orig/kernel/trace/trace.h	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/kernel/trace/trace.h	2010-12-26 20:59:41.000000000 +0800
@@ -295,6 +295,7 @@ struct dentry *trace_create_file(const c
 				 const struct file_operations *fops);
 
 struct dentry *tracing_init_dentry(void);
+struct dentry *trace_objects_dir(void);
 
 struct ring_buffer_event;
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mmotm/kernel/trace/trace_objects.c	2010-12-26 20:59:41.000000000 +0800
@@ -0,0 +1,26 @@
+#include <linux/debugfs.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+struct dentry *trace_objects_dir(void)
+{
+	static struct dentry *d_objects;
+	struct dentry *d_tracer;
+
+	if (d_objects)
+		return d_objects;
+
+	d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return NULL;
+
+	d_objects = debugfs_create_dir("objects", d_tracer);
+	if (!d_objects)
+		pr_warning("Could not create debugfs "
+			   "'objects' directory\n");
+
+	return d_objects;
+}
+
+
--- mmotm.orig/mm/page_alloc.c	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/mm/page_alloc.c	2010-12-26 20:59:41.000000000 +0800
@@ -5493,7 +5493,7 @@ bool is_free_buddy_page(struct page *pag
 }
 #endif
 
-static struct trace_print_flags pageflag_names[] = {
+struct trace_print_flags pageflag_names[] = {
 	{1UL << PG_locked,		"locked"	},
 	{1UL << PG_error,		"error"		},
 	{1UL << PG_referenced,		"referenced"	},
@@ -5541,7 +5541,7 @@ static void dump_page_flags(unsigned lon
 	printk(KERN_ALERT "page flags: %#lx(", flags);
 
 	/* remove zone id */
-	flags &= (1UL << NR_PAGEFLAGS) - 1;
+	flags &= PAGE_FLAGS_MASK;
 
 	for (i = 0; pageflag_names[i].name && flags; i++) {
 
--- mmotm.orig/include/linux/page-flags.h	2010-12-26 20:58:46.000000000 +0800
+++ mmotm/include/linux/page-flags.h	2010-12-26 20:59:41.000000000 +0800
@@ -414,6 +414,7 @@ static inline void __ClearPageTail(struc
  * there has been a kernel bug or struct page corruption.
  */
 #define PAGE_FLAGS_CHECK_AT_PREP	((1 << NR_PAGEFLAGS) - 1)
+#define PAGE_FLAGS_MASK			((1 << NR_PAGEFLAGS) - 1)
 
 #define PAGE_FLAGS_PRIVATE				\
 	(1 << PG_private | 1 << PG_private_2)
--- mmotm.orig/fs/inode.c	2010-12-26 20:58:45.000000000 +0800
+++ mmotm/fs/inode.c	2010-12-26 21:00:09.000000000 +0800
@@ -182,7 +182,13 @@ int inode_init_always(struct super_block
 	inode->i_bdev = NULL;
 	inode->i_cdev = NULL;
 	inode->i_rdev = 0;
-	inode->dirtied_when = 0;
+
+	/*
+	 * This records inode load time. It will be invalidated once inode is
+	 * dirtied, or jiffies wraps around. Despite the pitfalls it still
+	 * provides useful information for some use cases like fastboot.
+	 */
+	inode->dirtied_when = jiffies;
 
 	if (security_inode_alloc(inode))
 		goto out;
@@ -226,6 +232,9 @@ int inode_init_always(struct super_block
 
 	percpu_counter_inc(&nr_inodes);
 
+	BUILD_BUG_ON(sizeof(inode->i_comm) != TASK_COMM_LEN);
+	memcpy(inode->i_comm, current->comm, TASK_COMM_LEN);
+
 	return 0;
 out:
 	return -ENOMEM;
--- mmotm.orig/include/linux/fs.h	2010-12-26 20:59:50.000000000 +0800
+++ mmotm/include/linux/fs.h	2010-12-26 21:00:09.000000000 +0800
@@ -800,6 +800,8 @@ struct inode {
 	struct posix_acl	*i_default_acl;
 #endif
 	void			*i_private; /* fs or device private pointer */
+
+	char			i_comm[16]; /* first opened by */
 };
 
 static inline int inode_unhashed(struct inode *inode)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02  8:45     ` Ingo Molnar
@ 2011-03-03  2:01       ` KOSAKI Motohiro
  -1 siblings, 0 replies; 206+ messages in thread
From: KOSAKI Motohiro @ 2011-03-03  2:01 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: kosaki.motohiro, Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm,
	fengguang.wu, Peter Zijlstra, Fr馘駻ic Weisbecker,
	Steven Rostedt, Thomas Gleixner, Arnaldo Carvalho de Melo

> 
> * Liu Yuan <namei.unix@gmail.com> wrote:
> 
> > +		if (likely(!retry_find) && page && PageUptodate(page))
> > +			page_cache_acct_hit(inode->i_sb, READ);
> > +		else
> > +			page_cache_acct_missed(inode->i_sb, READ);
> 
> Sigh.
> 
> This would make such a nice tracepoint or sw perf event. It could be collected in a 
> 'count' form, equivalent to the stats you are aiming for here, or it could even be 
> traced, if someone is interested in such details.
> 
> It could be mixed with other events, enriching multiple apps at once.

Totally agreed.


> But, instead of trying to improve those aspects of our existing instrumentation 
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> the big picture and fragmenting the instrumentation space some more.
> 
> That trend is somewhat sad.

So, I think thing is, the stat is how much people and how frequently used.
If it is really really really common, /proc/meminfo or similar special place
is good idea. Another example, If the stat can help our MM debugging to
handle LKML bug report, it is worth to have special care. But other almost
else case are better to use generic framework.



^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-03  2:01       ` KOSAKI Motohiro
  0 siblings, 0 replies; 206+ messages in thread
From: KOSAKI Motohiro @ 2011-03-03  2:01 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: kosaki.motohiro, Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm,
	fengguang.wu, Peter Zijlstra, Fr馘駻ic Weisbecker,
	Steven Rostedt, Thomas Gleixner, Arnaldo Carvalho de Melo

> 
> * Liu Yuan <namei.unix@gmail.com> wrote:
> 
> > +		if (likely(!retry_find) && page && PageUptodate(page))
> > +			page_cache_acct_hit(inode->i_sb, READ);
> > +		else
> > +			page_cache_acct_missed(inode->i_sb, READ);
> 
> Sigh.
> 
> This would make such a nice tracepoint or sw perf event. It could be collected in a 
> 'count' form, equivalent to the stats you are aiming for here, or it could even be 
> traced, if someone is interested in such details.
> 
> It could be mixed with other events, enriching multiple apps at once.

Totally agreed.


> But, instead of trying to improve those aspects of our existing instrumentation 
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing 
> the big picture and fragmenting the instrumentation space some more.
> 
> That trend is somewhat sad.

So, I think thing is, the stat is how much people and how frequently used.
If it is really really really common, /proc/meminfo or similar special place
is good idea. Another example, If the stat can help our MM debugging to
handle LKML bug report, it is worth to have special care. But other almost
else case are better to use generic framework.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry
  2011-03-02 16:24     ` Randy Dunlap
  (?)
@ 2011-03-03  3:11     ` Liu Yuan
  -1 siblings, 0 replies; 206+ messages in thread
From: Liu Yuan @ 2011-03-03  3:11 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu

[-- Attachment #1: Type: text/plain, Size: 1801 bytes --]

On Thu, Mar 3, 2011 at 12:24 AM, Randy Dunlap <rdunlap@xenotime.net> wrote:

> On Wed,  2 Mar 2011 16:38:06 +0800 Liu Yuan wrote:
>
> > From: Liu Yuan <tailai.ly@taobao.com>
> >
> > Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
> > ---
> >  arch/x86/Kconfig.debug |    9 +++++++++
> >  1 files changed, 9 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> > index 615e188..f29e32d 100644
> > --- a/arch/x86/Kconfig.debug
> > +++ b/arch/x86/Kconfig.debug
> > @@ -304,4 +304,13 @@ config DEBUG_STRICT_USER_COPY_CHECKS
> >
> >         If unsure, or if you run an older (pre 4.4) gcc, say N.
> >
> > +config PAGE_CACHE_ACCT
> > +     bool "Page cache accounting"
> > +     ---help---
> > +       Enabling this options to account for page cache hit/missed number
> of
> > +       times. This would allow user space applications get better
> knowledge
> > +       of underlying page cache system by reading virtual file. The
> statitics
> > +       per partition are collected.
> > +
> > +       If unsure, say N.
> >  endmenu
> > --
>
> rewrite:
>
>          Enable this option to provide for page cache hit/miss counters.
>          This allows userspace applications to obtain better knowledge of
> the
>          underlying page cache subsystem by reading a virtual file.
>          Statistics are collect per partition.
>
> questions:
>        what virtual file?
>        what kind of partition?
>
>
Hi Randy,

Thanks for your correction.

'virtual file' in this patch context means files in sysfs mounted at /sys.
'partition' indicates that every disk partition (like
/dev/sda/{sda1,sda2...} has its own accountings for page cache information.

I am not confident about phrasing. so please correct it if you think it is
way better.

Thanks,
Liu Yuan

[-- Attachment #2: Type: text/html, Size: 2582 bytes --]

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-02  8:45     ` Ingo Molnar
@ 2011-03-03  3:14       ` Tao Ma
  -1 siblings, 0 replies; 206+ messages in thread
From: Tao Ma @ 2011-03-03  3:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On 03/02/2011 04:45 PM, Ingo Molnar wrote:
> * Liu Yuan<namei.unix@gmail.com>  wrote:
>
>    
>> +		if (likely(!retry_find)&&  page&&  PageUptodate(page))
>> +			page_cache_acct_hit(inode->i_sb, READ);
>> +		else
>> +			page_cache_acct_missed(inode->i_sb, READ);
>>      
> Sigh.
>
> This would make such a nice tracepoint or sw perf event. It could be collected in a
> 'count' form, equivalent to the stats you are aiming for here, or it could even be
> traced, if someone is interested in such details.
>
> It could be mixed with other events, enriching multiple apps at once.
>
> But, instead of trying to improve those aspects of our existing instrumentation
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
> the big picture and fragmenting the instrumentation space some more.
>    
Thanks for the quick response. Actually our team(including Liu) here are 
planing to add some
debug info to the mm parts for analyzing the application behavior and 
hope to find some way
to improve our application's performance.
We have searched the trace points in mm, but it seems to us that the 
trace points isn't quite welcomed
there. Only vmscan and writeback have some limited trace points added. 
That's the reason we first
tried to add some debug info like this patch. You does shed some light 
on our direction. Thanks.

btw, what part do you think is needed to add some trace point?  We 
volunteer to add more if you like.

Regards,
Tao

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-03  3:14       ` Tao Ma
  0 siblings, 0 replies; 206+ messages in thread
From: Tao Ma @ 2011-03-03  3:14 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo

On 03/02/2011 04:45 PM, Ingo Molnar wrote:
> * Liu Yuan<namei.unix@gmail.com>  wrote:
>
>    
>> +		if (likely(!retry_find)&&  page&&  PageUptodate(page))
>> +			page_cache_acct_hit(inode->i_sb, READ);
>> +		else
>> +			page_cache_acct_missed(inode->i_sb, READ);
>>      
> Sigh.
>
> This would make such a nice tracepoint or sw perf event. It could be collected in a
> 'count' form, equivalent to the stats you are aiming for here, or it could even be
> traced, if someone is interested in such details.
>
> It could be mixed with other events, enriching multiple apps at once.
>
> But, instead of trying to improve those aspects of our existing instrumentation
> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
> the big picture and fragmenting the instrumentation space some more.
>    
Thanks for the quick response. Actually our team(including Liu) here are 
planing to add some
debug info to the mm parts for analyzing the application behavior and 
hope to find some way
to improve our application's performance.
We have searched the trace points in mm, but it seems to us that the 
trace points isn't quite welcomed
there. Only vmscan and writeback have some limited trace points added. 
That's the reason we first
tried to add some debug info like this patch. You does shed some light 
on our direction. Thanks.

btw, what part do you think is needed to add some trace point?  We 
volunteer to add more if you like.

Regards,
Tao

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-03  3:14       ` Tao Ma
@ 2011-03-03  9:34         ` Ingo Molnar
  -1 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-03  9:34 UTC (permalink / raw)
  To: Tao Ma
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo, Tom Zanussi


* Tao Ma <tm@tao.ma> wrote:

> On 03/02/2011 04:45 PM, Ingo Molnar wrote:
> >* Liu Yuan<namei.unix@gmail.com>  wrote:
> >
> >>+		if (likely(!retry_find)&&  page&&  PageUptodate(page))
> >>+			page_cache_acct_hit(inode->i_sb, READ);
> >>+		else
> >>+			page_cache_acct_missed(inode->i_sb, READ);
> >Sigh.
> >
> >This would make such a nice tracepoint or sw perf event. It could be collected in a
> >'count' form, equivalent to the stats you are aiming for here, or it could even be
> >traced, if someone is interested in such details.
> >
> >It could be mixed with other events, enriching multiple apps at once.
> >
> >But, instead of trying to improve those aspects of our existing instrumentation
> >frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
> >the big picture and fragmenting the instrumentation space some more.

> Thanks for the quick response. Actually our team(including Liu) here are planing 
> to add some debug info to the mm parts for analyzing the application behavior and 
> hope to find some way to improve our application's performance. We have searched 
> the trace points in mm, but it seems to us that the trace points isn't quite 
> welcomed there. Only vmscan and writeback have some limited trace points added. 
> That's the reason we first tried to add some debug info like this patch. You does 
> shed some light on our direction. Thanks.

Yes, it's very much a 'critical mass' phenomenon: the moment there's enough 
tracepoints, above some magic limit, things happen quickly and everyone finds the 
stuff obviously useful.

Before that limit it's all pretty painful.

> btw, what part do you think is needed to add some trace point?  We
> volunteer to add more if you like.

Whatever part you find useful in your daily development work!

Tracepoints are pretty flexible. The bit that is missing and which is very important 
for the MM is the collapse into 'summaries' and the avoidance of tracing overhead 
when only a summary is wanted. Please see Wu Fengguang's reply in this thread about 
the 'dump state' facility he and Steve added to recover large statistics.

I suspect the hit/miss histogram you are building in this patch could be recovered 
via that facility initially?

The next step would generalize that approach - it is non-trivial but powerful :-)

The idea is to allow non-trivial histograms and summaries to be built out of simple 
events, via the filter engine.

It would require an extension of tracing to really allow a filter expression to be 
defined over existing events, which would allow the maintenance of a persistent 
'sum' variable - probably within the perf ring-buffer. We already have filter 
support, that would have to be extended with a notion of 'persistent variables'.

So right now, if you define a tracepoint in that spot, we already support such 
filter expressions:

     'bdev == sda1 && page_state == PageUptodate'

You can inject such filter expressions into /debug/tracing/events/*/*/filter today, 
and you can use filters in perf record --filter '...' as well.

To implement 'fast statistics', the filter engine would have to be extended to 
support (simple) statements like:

	if (bdev == sda1 && page_state == PageUptodate)'
		var0++;

And:

	if (bdev == sda1 && page_state != PageUptodate)'
		var1++;

Only a very minimal type of C syntax would be supported - not a full C parser.

That way the 'var0' portion of the perf ring-buffer (which would not be part of the 
regular, overwritten ring-buffer) would act as a 'hits' variable that you could 
recover. The 'var1' portion would be the 'misses' counter.

Individual trace events would only twiddle var0 and var1 - they would not inject a 
full-blown event into the ring-buffer, so statistics would be very fast.

This method is very extensible and could be used for far more things than just MM 
statistics. In theory all of /proc statistics collection could be replaced and made 
optional that way, just by adding the right events to the right spots in the kernel.  
That is obviously a very long-term project.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-03  9:34         ` Ingo Molnar
  0 siblings, 0 replies; 206+ messages in thread
From: Ingo Molnar @ 2011-03-03  9:34 UTC (permalink / raw)
  To: Tao Ma
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo, Tom Zanussi


* Tao Ma <tm@tao.ma> wrote:

> On 03/02/2011 04:45 PM, Ingo Molnar wrote:
> >* Liu Yuan<namei.unix@gmail.com>  wrote:
> >
> >>+		if (likely(!retry_find)&&  page&&  PageUptodate(page))
> >>+			page_cache_acct_hit(inode->i_sb, READ);
> >>+		else
> >>+			page_cache_acct_missed(inode->i_sb, READ);
> >Sigh.
> >
> >This would make such a nice tracepoint or sw perf event. It could be collected in a
> >'count' form, equivalent to the stats you are aiming for here, or it could even be
> >traced, if someone is interested in such details.
> >
> >It could be mixed with other events, enriching multiple apps at once.
> >
> >But, instead of trying to improve those aspects of our existing instrumentation
> >frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
> >the big picture and fragmenting the instrumentation space some more.

> Thanks for the quick response. Actually our team(including Liu) here are planing 
> to add some debug info to the mm parts for analyzing the application behavior and 
> hope to find some way to improve our application's performance. We have searched 
> the trace points in mm, but it seems to us that the trace points isn't quite 
> welcomed there. Only vmscan and writeback have some limited trace points added. 
> That's the reason we first tried to add some debug info like this patch. You does 
> shed some light on our direction. Thanks.

Yes, it's very much a 'critical mass' phenomenon: the moment there's enough 
tracepoints, above some magic limit, things happen quickly and everyone finds the 
stuff obviously useful.

Before that limit it's all pretty painful.

> btw, what part do you think is needed to add some trace point?  We
> volunteer to add more if you like.

Whatever part you find useful in your daily development work!

Tracepoints are pretty flexible. The bit that is missing and which is very important 
for the MM is the collapse into 'summaries' and the avoidance of tracing overhead 
when only a summary is wanted. Please see Wu Fengguang's reply in this thread about 
the 'dump state' facility he and Steve added to recover large statistics.

I suspect the hit/miss histogram you are building in this patch could be recovered 
via that facility initially?

The next step would generalize that approach - it is non-trivial but powerful :-)

The idea is to allow non-trivial histograms and summaries to be built out of simple 
events, via the filter engine.

It would require an extension of tracing to really allow a filter expression to be 
defined over existing events, which would allow the maintenance of a persistent 
'sum' variable - probably within the perf ring-buffer. We already have filter 
support, that would have to be extended with a notion of 'persistent variables'.

So right now, if you define a tracepoint in that spot, we already support such 
filter expressions:

     'bdev == sda1 && page_state == PageUptodate'

You can inject such filter expressions into /debug/tracing/events/*/*/filter today, 
and you can use filters in perf record --filter '...' as well.

To implement 'fast statistics', the filter engine would have to be extended to 
support (simple) statements like:

	if (bdev == sda1 && page_state == PageUptodate)'
		var0++;

And:

	if (bdev == sda1 && page_state != PageUptodate)'
		var1++;

Only a very minimal type of C syntax would be supported - not a full C parser.

That way the 'var0' portion of the perf ring-buffer (which would not be part of the 
regular, overwritten ring-buffer) would act as a 'hits' variable that you could 
recover. The 'var1' portion would be the 'misses' counter.

Individual trace events would only twiddle var0 and var1 - they would not inject a 
full-blown event into the ring-buffer, so statistics would be very fast.

This method is very extensible and could be used for far more things than just MM 
statistics. In theory all of /proc statistics collection could be replaced and made 
optional that way, just by adding the right events to the right spots in the kernel.  
That is obviously a very long-term project.

Thanks,

	Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
  2011-03-03  9:34         ` Ingo Molnar
@ 2011-03-03 15:08           ` Tao Ma
  -1 siblings, 0 replies; 206+ messages in thread
From: Tao Ma @ 2011-03-03 15:08 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo, Tom Zanussi

On 03/03/2011 05:34 PM, Ingo Molnar wrote:
> * Tao Ma<tm@tao.ma>  wrote:
>
>> On 03/02/2011 04:45 PM, Ingo Molnar wrote:
>>> * Liu Yuan<namei.unix@gmail.com>   wrote:
>>>
>>>> +		if (likely(!retry_find)&&   page&&   PageUptodate(page))
>>>> +			page_cache_acct_hit(inode->i_sb, READ);
>>>> +		else
>>>> +			page_cache_acct_missed(inode->i_sb, READ);
>>> Sigh.
>>>
>>> This would make such a nice tracepoint or sw perf event. It could be collected in a
>>> 'count' form, equivalent to the stats you are aiming for here, or it could even be
>>> traced, if someone is interested in such details.
>>>
>>> It could be mixed with other events, enriching multiple apps at once.
>>>
>>> But, instead of trying to improve those aspects of our existing instrumentation
>>> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
>>> the big picture and fragmenting the instrumentation space some more.
>> Thanks for the quick response. Actually our team(including Liu) here are planing
>> to add some debug info to the mm parts for analyzing the application behavior and
>> hope to find some way to improve our application's performance. We have searched
>> the trace points in mm, but it seems to us that the trace points isn't quite
>> welcomed there. Only vmscan and writeback have some limited trace points added.
>> That's the reason we first tried to add some debug info like this patch. You does
>> shed some light on our direction. Thanks.
> Yes, it's very much a 'critical mass' phenomenon: the moment there's enough
> tracepoints, above some magic limit, things happen quickly and everyone finds the
> stuff obviously useful.
>
> Before that limit it's all pretty painful.
yeah.
>> btw, what part do you think is needed to add some trace point?  We
>> volunteer to add more if you like.
> Whatever part you find useful in your daily development work!
>
> Tracepoints are pretty flexible. The bit that is missing and which is very important
> for the MM is the collapse into 'summaries' and the avoidance of tracing overhead
> when only a summary is wanted. Please see Wu Fengguang's reply in this thread about
> the 'dump state' facility he and Steve added to recover large statistics.
We are looking into it now. Thanks for the hint.
> I suspect the hit/miss histogram you are building in this patch could be recovered
> via that facility initially?
>
> The next step would generalize that approach - it is non-trivial but powerful :-)
>
> The idea is to allow non-trivial histograms and summaries to be built out of simple
> events, via the filter engine.
>
> It would require an extension of tracing to really allow a filter expression to be
> defined over existing events, which would allow the maintenance of a persistent
> 'sum' variable - probably within the perf ring-buffer. We already have filter
> support, that would have to be extended with a notion of 'persistent variables'.
>
> So right now, if you define a tracepoint in that spot, we already support such
> filter expressions:
>
>       'bdev == sda1&&  page_state == PageUptodate'
>
> You can inject such filter expressions into /debug/tracing/events/*/*/filter today,
> and you can use filters in perf record --filter '...' as well.
>
> To implement 'fast statistics', the filter engine would have to be extended to
> support (simple) statements like:
>
> 	if (bdev == sda1&&  page_state == PageUptodate)'
> 		var0++;
>
> And:
>
> 	if (bdev == sda1&&  page_state != PageUptodate)'
> 		var1++;
>
> Only a very minimal type of C syntax would be supported - not a full C parser.
>
> That way the 'var0' portion of the perf ring-buffer (which would not be part of the
> regular, overwritten ring-buffer) would act as a 'hits' variable that you could
> recover. The 'var1' portion would be the 'misses' counter.
>
> Individual trace events would only twiddle var0 and var1 - they would not inject a
> full-blown event into the ring-buffer, so statistics would be very fast.
>
> This method is very extensible and could be used for far more things than just MM
> statistics. In theory all of /proc statistics collection could be replaced and made
> optional that way, just by adding the right events to the right spots in the kernel.
> That is obviously a very long-term project.
It looks really fantastic for us. OK, we will try to figure out when and 
how we can work on this issue. Great thanks.

Regards,
Tao

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache
@ 2011-03-03 15:08           ` Tao Ma
  0 siblings, 0 replies; 206+ messages in thread
From: Tao Ma @ 2011-03-03 15:08 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Liu Yuan, linux-kernel, linux-mm, jaxboe, akpm, fengguang.wu,
	Peter Zijlstra, Frédéric Weisbecker, Steven Rostedt,
	Thomas Gleixner, Arnaldo Carvalho de Melo, Tom Zanussi

On 03/03/2011 05:34 PM, Ingo Molnar wrote:
> * Tao Ma<tm@tao.ma>  wrote:
>
>> On 03/02/2011 04:45 PM, Ingo Molnar wrote:
>>> * Liu Yuan<namei.unix@gmail.com>   wrote:
>>>
>>>> +		if (likely(!retry_find)&&   page&&   PageUptodate(page))
>>>> +			page_cache_acct_hit(inode->i_sb, READ);
>>>> +		else
>>>> +			page_cache_acct_missed(inode->i_sb, READ);
>>> Sigh.
>>>
>>> This would make such a nice tracepoint or sw perf event. It could be collected in a
>>> 'count' form, equivalent to the stats you are aiming for here, or it could even be
>>> traced, if someone is interested in such details.
>>>
>>> It could be mixed with other events, enriching multiple apps at once.
>>>
>>> But, instead of trying to improve those aspects of our existing instrumentation
>>> frameworks, mm/* is gradually growing its own special instrumentation hacks, missing
>>> the big picture and fragmenting the instrumentation space some more.
>> Thanks for the quick response. Actually our team(including Liu) here are planing
>> to add some debug info to the mm parts for analyzing the application behavior and
>> hope to find some way to improve our application's performance. We have searched
>> the trace points in mm, but it seems to us that the trace points isn't quite
>> welcomed there. Only vmscan and writeback have some limited trace points added.
>> That's the reason we first tried to add some debug info like this patch. You does
>> shed some light on our direction. Thanks.
> Yes, it's very much a 'critical mass' phenomenon: the moment there's enough
> tracepoints, above some magic limit, things happen quickly and everyone finds the
> stuff obviously useful.
>
> Before that limit it's all pretty painful.
yeah.
>> btw, what part do you think is needed to add some trace point?  We
>> volunteer to add more if you like.
> Whatever part you find useful in your daily development work!
>
> Tracepoints are pretty flexible. The bit that is missing and which is very important
> for the MM is the collapse into 'summaries' and the avoidance of tracing overhead
> when only a summary is wanted. Please see Wu Fengguang's reply in this thread about
> the 'dump state' facility he and Steve added to recover large statistics.
We are looking into it now. Thanks for the hint.
> I suspect the hit/miss histogram you are building in this patch could be recovered
> via that facility initially?
>
> The next step would generalize that approach - it is non-trivial but powerful :-)
>
> The idea is to allow non-trivial histograms and summaries to be built out of simple
> events, via the filter engine.
>
> It would require an extension of tracing to really allow a filter expression to be
> defined over existing events, which would allow the maintenance of a persistent
> 'sum' variable - probably within the perf ring-buffer. We already have filter
> support, that would have to be extended with a notion of 'persistent variables'.
>
> So right now, if you define a tracepoint in that spot, we already support such
> filter expressions:
>
>       'bdev == sda1&&  page_state == PageUptodate'
>
> You can inject such filter expressions into /debug/tracing/events/*/*/filter today,
> and you can use filters in perf record --filter '...' as well.
>
> To implement 'fast statistics', the filter engine would have to be extended to
> support (simple) statements like:
>
> 	if (bdev == sda1&&  page_state == PageUptodate)'
> 		var0++;
>
> And:
>
> 	if (bdev == sda1&&  page_state != PageUptodate)'
> 		var1++;
>
> Only a very minimal type of C syntax would be supported - not a full C parser.
>
> That way the 'var0' portion of the perf ring-buffer (which would not be part of the
> regular, overwritten ring-buffer) would act as a 'hits' variable that you could
> recover. The 'var1' portion would be the 'misses' counter.
>
> Individual trace events would only twiddle var0 and var1 - they would not inject a
> full-blown event into the ring-buffer, so statistics would be very fast.
>
> This method is very extensible and could be used for far more things than just MM
> statistics. In theory all of /proc statistics collection could be replaced and made
> optional that way, just by adding the right events to the right spots in the kernel.
> That is obviously a very long-term project.
It looks really fantastic for us. OK, we will try to figure out when and 
how we can work on this issue. Great thanks.

Regards,
Tao

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Use PM runtime framework in OMAP GPIO driver.

Patch series is based on mainline rc3 following commit
commit a1b49cb7e2a7961ec3aa8b64860bf480d4ec9077
Merge branch 'i2c-for-linus' of
	git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

Changes in v2:
* Use a per-bank flag 'looses_context' (using pwrdm_can_ever_lose_context())
       instead of using the powerdomain name
* Make use of omap_device_get_context_loss_count() to decide on if restore
       context needs to be done.
* Do not remove #ifdef CONFIG_ARCH_OMAP2PLUS
* Do not use pm_runtime_suspended() before calling pm_runtime_get_sync/put_sync
* use IS_ERR_VALUE() instead of '< 0' in "if" conditions
(Thanks to Kevin and Paul for the above suggestions)

Previous version of this patch series is available at:
http://ns.spinics.net/lists/linux-omap/msg48167.html
http://ns.spinics.net/lists/linux-omap/msg47989.html
http://ns.spinics.net/lists/linux-omap/msg47827.html
http://ns.spinics.net/lists/linux-omap/msg47830.html

Compile tested for:
 - omap1_defconfig
 - omap2plus_defconfig

Boot test (success on the following boards):
 - OMAP1710-H3
 - OMAP2420-H4
 - OMAP3430-SDP
 - OMAP3430-Zoom2
 - OMAP3630-Zoom3
 - OMAP4430-SDP

GPIO module functionality testing (success on the following boards):
 - OMAP2420-H4
 - OMAP3430-SDP
 - OMAP3430-Zoom2
 - OMAP3630-Zoom3
 - OMAP4430-SDP

PM Testing (success as given below):
OMAP3430-SDP: retention, off_mode, system_wide suspend, gpio wakeup
OMAP3630-Zoom3: retention, system_wide suspend
using the following:
	     echo 5 > /sys/devices/platform/omap/omap_uart.0/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.1/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.2/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.3/sleep_timeout
	     echo '5' > /debug/pm_debug/wakeup_timer_seconds
	     echo 1 > /debug/pm_debug/sleep_while_idle
	     echo 1 > /debug/pm_debug/enable_off_mode
	     echo mem > /sys/power/state


Charulatha V (7):
  OMAP: GPIO: Make gpio_context part of gpio_bank structure
  OMAP: GPIO: Use flag to identify wkup dmn GPIO
  OMAP4: GPIO: Save/restore context
  OMAP: GPIO: handle save/restore ctx in GPIO driver
  OMAP2+: GPIO: make workaround_enabled bank specific
  OMAP: GPIO: Cleanup prepare_for_idle/resume
  OMAP: GPIO: use PM runtime framework

 arch/arm/mach-omap2/gpio.c             |    6 +
 arch/arm/mach-omap2/pm34xx.c           |   22 +-
 arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
 arch/arm/plat-omap/include/plat/gpio.h |    3 +-
 4 files changed, 439 insertions(+), 358 deletions(-)


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Use PM runtime framework in OMAP GPIO driver.

Patch series is based on mainline rc3 following commit
commit a1b49cb7e2a7961ec3aa8b64860bf480d4ec9077
Merge branch 'i2c-for-linus' of
	git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

Changes in v2:
* Use a per-bank flag 'looses_context' (using pwrdm_can_ever_lose_context())
       instead of using the powerdomain name
* Make use of omap_device_get_context_loss_count() to decide on if restore
       context needs to be done.
* Do not remove #ifdef CONFIG_ARCH_OMAP2PLUS
* Do not use pm_runtime_suspended() before calling pm_runtime_get_sync/put_sync
* use IS_ERR_VALUE() instead of '< 0' in "if" conditions
(Thanks to Kevin and Paul for the above suggestions)

Previous version of this patch series is available at:
http://ns.spinics.net/lists/linux-omap/msg48167.html
http://ns.spinics.net/lists/linux-omap/msg47989.html
http://ns.spinics.net/lists/linux-omap/msg47827.html
http://ns.spinics.net/lists/linux-omap/msg47830.html

Compile tested for:
 - omap1_defconfig
 - omap2plus_defconfig

Boot test (success on the following boards):
 - OMAP1710-H3
 - OMAP2420-H4
 - OMAP3430-SDP
 - OMAP3430-Zoom2
 - OMAP3630-Zoom3
 - OMAP4430-SDP

GPIO module functionality testing (success on the following boards):
 - OMAP2420-H4
 - OMAP3430-SDP
 - OMAP3430-Zoom2
 - OMAP3630-Zoom3
 - OMAP4430-SDP

PM Testing (success as given below):
OMAP3430-SDP: retention, off_mode, system_wide suspend, gpio wakeup
OMAP3630-Zoom3: retention, system_wide suspend
using the following:
	     echo 5 > /sys/devices/platform/omap/omap_uart.0/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.1/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.2/sleep_timeout
	     echo 5 > /sys/devices/platform/omap/omap_uart.3/sleep_timeout
	     echo '5' > /debug/pm_debug/wakeup_timer_seconds
	     echo 1 > /debug/pm_debug/sleep_while_idle
	     echo 1 > /debug/pm_debug/enable_off_mode
	     echo mem > /sys/power/state


Charulatha V (7):
  OMAP: GPIO: Make gpio_context part of gpio_bank structure
  OMAP: GPIO: Use flag to identify wkup dmn GPIO
  OMAP4: GPIO: Save/restore context
  OMAP: GPIO: handle save/restore ctx in GPIO driver
  OMAP2+: GPIO: make workaround_enabled bank specific
  OMAP: GPIO: Cleanup prepare_for_idle/resume
  OMAP: GPIO: use PM runtime framework

 arch/arm/mach-omap2/gpio.c             |    6 +
 arch/arm/mach-omap2/pm34xx.c           |   22 +-
 arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
 arch/arm/plat-omap/include/plat/gpio.h |    3 +-
 4 files changed, 439 insertions(+), 358 deletions(-)

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/7] OMAP: GPIO: Make gpio_context part of gpio_bank structure
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

gpio_context array, which is used to save gpio bank's context,
is used only for OMAP3 architecture.

Move gpio_context as part of gpio_bank structure so that
it can be specific to each gpio bank and can be used for
any OMAP architecture

TODO: extend the gpio save/restore context function for OMAP4
architecture. This is done in one of the next patches in this
series

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |   72 +++++++++++++++++++++-----------------------
 1 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index d2adcdd..c8736b0 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -133,6 +133,19 @@
 #define OMAP4_GPIO_CLEARDATAOUT		0x0190
 #define OMAP4_GPIO_SETDATAOUT		0x0194
 
+struct gpio_regs {
+	u32 irqenable1;
+	u32 irqenable2;
+	u32 wake_en;
+	u32 ctrl;
+	u32 oe;
+	u32 leveldetect0;
+	u32 leveldetect1;
+	u32 risingdetect;
+	u32 fallingdetect;
+	u32 dataout;
+};
+
 struct gpio_bank {
 	unsigned long pbase;
 	void __iomem *base;
@@ -145,7 +158,7 @@ struct gpio_bank {
 #endif
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
-
+	struct gpio_regs context;
 	u32 saved_datain;
 	u32 saved_fallingdetect;
 	u32 saved_risingdetect;
@@ -161,23 +174,6 @@ struct gpio_bank {
 	int stride;
 };
 
-#ifdef CONFIG_ARCH_OMAP3
-struct omap3_gpio_regs {
-	u32 irqenable1;
-	u32 irqenable2;
-	u32 wake_en;
-	u32 ctrl;
-	u32 oe;
-	u32 leveldetect0;
-	u32 leveldetect1;
-	u32 risingdetect;
-	u32 fallingdetect;
-	u32 dataout;
-};
-
-static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
-#endif
-
 /*
  * TODO: Cleanup gpio_bank usage as it is having information
  * related to all instances of the device
@@ -2034,25 +2030,25 @@ void omap_gpio_save_context(void)
 	/* saving banks from 2-6 only since GPIO1 is in WKUP */
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		gpio_context[i].irqenable1 =
+		bank->context.irqenable1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		gpio_context[i].irqenable2 =
+		bank->context.irqenable2 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		gpio_context[i].wake_en =
+		bank->context.wake_en =
 			__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
-		gpio_context[i].ctrl =
+		bank->context.ctrl =
 			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-		gpio_context[i].oe =
+		bank->context.oe =
 			__raw_readl(bank->base + OMAP24XX_GPIO_OE);
-		gpio_context[i].leveldetect0 =
+		bank->context.leveldetect0 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		gpio_context[i].leveldetect1 =
+		bank->context.leveldetect1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		gpio_context[i].risingdetect =
+		bank->context.risingdetect =
 			__raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		gpio_context[i].fallingdetect =
+		bank->context.fallingdetect =
 			__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		gpio_context[i].dataout =
+		bank->context.dataout =
 			__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
 	}
 }
@@ -2064,25 +2060,25 @@ void omap_gpio_restore_context(void)
 
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		__raw_writel(gpio_context[i].irqenable1,
+		__raw_writel(bank->context.irqenable1,
 				bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		__raw_writel(gpio_context[i].irqenable2,
+		__raw_writel(bank->context.irqenable2,
 				bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		__raw_writel(gpio_context[i].wake_en,
+		__raw_writel(bank->context.wake_en,
 				bank->base + OMAP24XX_GPIO_WAKE_EN);
-		__raw_writel(gpio_context[i].ctrl,
+		__raw_writel(bank->context.ctrl,
 				bank->base + OMAP24XX_GPIO_CTRL);
-		__raw_writel(gpio_context[i].oe,
+		__raw_writel(bank->context.oe,
 				bank->base + OMAP24XX_GPIO_OE);
-		__raw_writel(gpio_context[i].leveldetect0,
+		__raw_writel(bank->context.leveldetect0,
 				bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		__raw_writel(gpio_context[i].leveldetect1,
+		__raw_writel(bank->context.leveldetect1,
 				bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		__raw_writel(gpio_context[i].risingdetect,
+		__raw_writel(bank->context.risingdetect,
 				bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		__raw_writel(gpio_context[i].fallingdetect,
+		__raw_writel(bank->context.fallingdetect,
 				bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		__raw_writel(gpio_context[i].dataout,
+		__raw_writel(bank->context.dataout,
 				bank->base + OMAP24XX_GPIO_DATAOUT);
 	}
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 1/7] OMAP: GPIO: Make gpio_context part of gpio_bank structure
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

gpio_context array, which is used to save gpio bank's context,
is used only for OMAP3 architecture.

Move gpio_context as part of gpio_bank structure so that
it can be specific to each gpio bank and can be used for
any OMAP architecture

TODO: extend the gpio save/restore context function for OMAP4
architecture. This is done in one of the next patches in this
series

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |   72 +++++++++++++++++++++-----------------------
 1 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index d2adcdd..c8736b0 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -133,6 +133,19 @@
 #define OMAP4_GPIO_CLEARDATAOUT		0x0190
 #define OMAP4_GPIO_SETDATAOUT		0x0194
 
+struct gpio_regs {
+	u32 irqenable1;
+	u32 irqenable2;
+	u32 wake_en;
+	u32 ctrl;
+	u32 oe;
+	u32 leveldetect0;
+	u32 leveldetect1;
+	u32 risingdetect;
+	u32 fallingdetect;
+	u32 dataout;
+};
+
 struct gpio_bank {
 	unsigned long pbase;
 	void __iomem *base;
@@ -145,7 +158,7 @@ struct gpio_bank {
 #endif
 	u32 non_wakeup_gpios;
 	u32 enabled_non_wakeup_gpios;
-
+	struct gpio_regs context;
 	u32 saved_datain;
 	u32 saved_fallingdetect;
 	u32 saved_risingdetect;
@@ -161,23 +174,6 @@ struct gpio_bank {
 	int stride;
 };
 
-#ifdef CONFIG_ARCH_OMAP3
-struct omap3_gpio_regs {
-	u32 irqenable1;
-	u32 irqenable2;
-	u32 wake_en;
-	u32 ctrl;
-	u32 oe;
-	u32 leveldetect0;
-	u32 leveldetect1;
-	u32 risingdetect;
-	u32 fallingdetect;
-	u32 dataout;
-};
-
-static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
-#endif
-
 /*
  * TODO: Cleanup gpio_bank usage as it is having information
  * related to all instances of the device
@@ -2034,25 +2030,25 @@ void omap_gpio_save_context(void)
 	/* saving banks from 2-6 only since GPIO1 is in WKUP */
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		gpio_context[i].irqenable1 =
+		bank->context.irqenable1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		gpio_context[i].irqenable2 =
+		bank->context.irqenable2 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		gpio_context[i].wake_en =
+		bank->context.wake_en =
 			__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
-		gpio_context[i].ctrl =
+		bank->context.ctrl =
 			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-		gpio_context[i].oe =
+		bank->context.oe =
 			__raw_readl(bank->base + OMAP24XX_GPIO_OE);
-		gpio_context[i].leveldetect0 =
+		bank->context.leveldetect0 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		gpio_context[i].leveldetect1 =
+		bank->context.leveldetect1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		gpio_context[i].risingdetect =
+		bank->context.risingdetect =
 			__raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		gpio_context[i].fallingdetect =
+		bank->context.fallingdetect =
 			__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		gpio_context[i].dataout =
+		bank->context.dataout =
 			__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
 	}
 }
@@ -2064,25 +2060,25 @@ void omap_gpio_restore_context(void)
 
 	for (i = 1; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		__raw_writel(gpio_context[i].irqenable1,
+		__raw_writel(bank->context.irqenable1,
 				bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		__raw_writel(gpio_context[i].irqenable2,
+		__raw_writel(bank->context.irqenable2,
 				bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		__raw_writel(gpio_context[i].wake_en,
+		__raw_writel(bank->context.wake_en,
 				bank->base + OMAP24XX_GPIO_WAKE_EN);
-		__raw_writel(gpio_context[i].ctrl,
+		__raw_writel(bank->context.ctrl,
 				bank->base + OMAP24XX_GPIO_CTRL);
-		__raw_writel(gpio_context[i].oe,
+		__raw_writel(bank->context.oe,
 				bank->base + OMAP24XX_GPIO_OE);
-		__raw_writel(gpio_context[i].leveldetect0,
+		__raw_writel(bank->context.leveldetect0,
 				bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		__raw_writel(gpio_context[i].leveldetect1,
+		__raw_writel(bank->context.leveldetect1,
 				bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		__raw_writel(gpio_context[i].risingdetect,
+		__raw_writel(bank->context.risingdetect,
 				bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		__raw_writel(gpio_context[i].fallingdetect,
+		__raw_writel(bank->context.fallingdetect,
 				bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		__raw_writel(gpio_context[i].dataout,
+		__raw_writel(bank->context.dataout,
 				bank->base + OMAP24XX_GPIO_DATAOUT);
 	}
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/7] OMAP: GPIO: Use flag to identify wkup dmn GPIO
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

In omap3, save/restore context is implemented for GPIO
banks 2-6 as GPIO bank1 is in wakeup domain. Instead
of identifying bank's power domain by bank id, make use
of a flag "losses_context" which is filled by
pwrdm_can_ever_lose_context() during dev_init.

For getting the powerdomain pointer, omap_hwmod_get_pwrdm()
is used. omap_device_get_pwrdm() could not be used as the
pwrdm information needs to be filled in pdata, whereas
omap_device_get_pwrdm() could be used only after
omap_device_build() call.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/mach-omap2/gpio.c             |    6 ++++++
 arch/arm/plat-omap/gpio.c              |   31 ++++++++++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpio.h |    1 +
 3 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9529842..1f1c604 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -24,6 +24,8 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
+#include "powerdomain.h"
+
 static struct omap_device_pm_latency omap_gpio_latency[] = {
 	[0] = {
 		.deactivate_func = omap_device_idle_hwmods,
@@ -39,6 +41,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 	struct omap_gpio_dev_attr *dev_attr;
 	char *name = "omap_gpio";
 	int id;
+	struct powerdomain *pwrdm;
 
 	/*
 	 * extract the device id from name field available in the
@@ -75,6 +78,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		return -EINVAL;
 	}
 
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	pdata->looses_context = pwrdm_can_ever_lose_context(pwrdm);
+
 	od = omap_device_build(name, id - 1, oh, pdata,
 				sizeof(*pdata),	omap_gpio_latency,
 				ARRAY_SIZE(omap_gpio_latency),
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index c8736b0..74085b5 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -172,6 +172,7 @@ struct gpio_bank {
 	struct device *dev;
 	bool dbck_flag;
 	int stride;
+	bool looses_context;
 };
 
 /*
@@ -1711,6 +1712,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	bank->dbck_flag = pdata->dbck_flag;
 	bank->stride = pdata->bank_stride;
 	bank_width = pdata->bank_width;
+	bank->looses_context = pdata->looses_context;
 
 	spin_lock_init(&bank->lock);
 
@@ -1856,16 +1858,15 @@ static int workaround_enabled;
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i, c = 0;
-	int min = 0;
 
-	if (cpu_is_omap34xx())
-		min = 1;
-
-	for (i = min; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 		u32 l1 = 0, l2 = 0;
 		int j;
 
+		if (!bank->looses_context)
+			continue;
+
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_disable(bank->dbck);
 
@@ -1925,15 +1926,15 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
-	int min = 0;
 
-	if (cpu_is_omap34xx())
-		min = 1;
-	for (i = min; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 		u32 l = 0, gen, gen0, gen1;
 		int j;
 
+		if (!bank->looses_context)
+			continue;
+
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_enable(bank->dbck);
 
@@ -2028,8 +2029,12 @@ void omap_gpio_save_context(void)
 	int i;
 
 	/* saving banks from 2-6 only since GPIO1 is in WKUP */
-	for (i = 1; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+
+		if (!bank->looses_context)
+			continue;
+
 		bank->context.irqenable1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		bank->context.irqenable2 =
@@ -2058,8 +2063,12 @@ void omap_gpio_restore_context(void)
 {
 	int i;
 
-	for (i = 1; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+
+		if (!bank->looses_context)
+			continue;
+
 		__raw_writel(bank->context.irqenable1,
 				bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		__raw_writel(bank->context.irqenable2,
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index cac2e8a..15aeb71 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -77,6 +77,7 @@ struct omap_gpio_platform_data {
 	int bank_width;		/* GPIO bank width */
 	int bank_stride;	/* Only needed for omap1 MPUIO */
 	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
+	bool looses_context;	/* whether the bank would ever loose context */
 };
 
 /* TODO: Analyze removing gpio_bank_count usage from driver code */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/7] OMAP: GPIO: Use flag to identify wkup dmn GPIO
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

In omap3, save/restore context is implemented for GPIO
banks 2-6 as GPIO bank1 is in wakeup domain. Instead
of identifying bank's power domain by bank id, make use
of a flag "losses_context" which is filled by
pwrdm_can_ever_lose_context() during dev_init.

For getting the powerdomain pointer, omap_hwmod_get_pwrdm()
is used. omap_device_get_pwrdm() could not be used as the
pwrdm information needs to be filled in pdata, whereas
omap_device_get_pwrdm() could be used only after
omap_device_build() call.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/mach-omap2/gpio.c             |    6 ++++++
 arch/arm/plat-omap/gpio.c              |   31 ++++++++++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpio.h |    1 +
 3 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9529842..1f1c604 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -24,6 +24,8 @@
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
+#include "powerdomain.h"
+
 static struct omap_device_pm_latency omap_gpio_latency[] = {
 	[0] = {
 		.deactivate_func = omap_device_idle_hwmods,
@@ -39,6 +41,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 	struct omap_gpio_dev_attr *dev_attr;
 	char *name = "omap_gpio";
 	int id;
+	struct powerdomain *pwrdm;
 
 	/*
 	 * extract the device id from name field available in the
@@ -75,6 +78,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		return -EINVAL;
 	}
 
+	pwrdm = omap_hwmod_get_pwrdm(oh);
+	pdata->looses_context = pwrdm_can_ever_lose_context(pwrdm);
+
 	od = omap_device_build(name, id - 1, oh, pdata,
 				sizeof(*pdata),	omap_gpio_latency,
 				ARRAY_SIZE(omap_gpio_latency),
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index c8736b0..74085b5 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -172,6 +172,7 @@ struct gpio_bank {
 	struct device *dev;
 	bool dbck_flag;
 	int stride;
+	bool looses_context;
 };
 
 /*
@@ -1711,6 +1712,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	bank->dbck_flag = pdata->dbck_flag;
 	bank->stride = pdata->bank_stride;
 	bank_width = pdata->bank_width;
+	bank->looses_context = pdata->looses_context;
 
 	spin_lock_init(&bank->lock);
 
@@ -1856,16 +1858,15 @@ static int workaround_enabled;
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i, c = 0;
-	int min = 0;
 
-	if (cpu_is_omap34xx())
-		min = 1;
-
-	for (i = min; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 		u32 l1 = 0, l2 = 0;
 		int j;
 
+		if (!bank->looses_context)
+			continue;
+
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_disable(bank->dbck);
 
@@ -1925,15 +1926,15 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
-	int min = 0;
 
-	if (cpu_is_omap34xx())
-		min = 1;
-	for (i = min; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 		u32 l = 0, gen, gen0, gen1;
 		int j;
 
+		if (!bank->looses_context)
+			continue;
+
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_enable(bank->dbck);
 
@@ -2028,8 +2029,12 @@ void omap_gpio_save_context(void)
 	int i;
 
 	/* saving banks from 2-6 only since GPIO1 is in WKUP */
-	for (i = 1; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+
+		if (!bank->looses_context)
+			continue;
+
 		bank->context.irqenable1 =
 			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		bank->context.irqenable2 =
@@ -2058,8 +2063,12 @@ void omap_gpio_restore_context(void)
 {
 	int i;
 
-	for (i = 1; i < gpio_bank_count; i++) {
+	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+
+		if (!bank->looses_context)
+			continue;
+
 		__raw_writel(bank->context.irqenable1,
 				bank->base + OMAP24XX_GPIO_IRQENABLE1);
 		__raw_writel(bank->context.irqenable2,
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index cac2e8a..15aeb71 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -77,6 +77,7 @@ struct omap_gpio_platform_data {
 	int bank_width;		/* GPIO bank width */
 	int bank_stride;	/* Only needed for omap1 MPUIO */
 	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
+	bool looses_context;	/* whether the bank would ever loose context */
 };
 
 /* TODO: Analyze removing gpio_bank_count usage from driver code */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 3/7] OMAP4: GPIO: Save/restore context
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Modify the omap_gpio_save/restore_context to support OMAP4
architecture so that the OMAP GPIO driver need not be modified
when OMAP4 off mode support is available.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  131 +++++++++++++++++++++++++++++---------------
 1 files changed, 86 insertions(+), 45 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 74085b5..e68da08 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -2022,43 +2022,62 @@ void omap2_gpio_resume_after_idle(void)
 
 #endif
 
-#ifdef CONFIG_ARCH_OMAP3
-/* save the registers of bank 2-6 */
 void omap_gpio_save_context(void)
 {
 	int i;
 
-	/* saving banks from 2-6 only since GPIO1 is in WKUP */
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
 		if (!bank->looses_context)
 			continue;
 
-		bank->context.irqenable1 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		bank->context.irqenable2 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		bank->context.wake_en =
-			__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
-		bank->context.ctrl =
-			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-		bank->context.oe =
-			__raw_readl(bank->base + OMAP24XX_GPIO_OE);
-		bank->context.leveldetect0 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		bank->context.leveldetect1 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		bank->context.risingdetect =
-			__raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		bank->context.fallingdetect =
-			__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		bank->context.dataout =
-			__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
+		if (bank->method == METHOD_GPIO_24XX) {
+			bank->context.irqenable1 = __raw_readl(
+					bank->base + OMAP24XX_GPIO_IRQENABLE1);
+			bank->context.irqenable2 = __raw_readl(
+					bank->base + OMAP24XX_GPIO_IRQENABLE2);
+			bank->context.wake_en = __raw_readl(
+					bank->base + OMAP24XX_GPIO_WAKE_EN);
+			bank->context.ctrl = __raw_readl(
+					bank->base + OMAP24XX_GPIO_CTRL);
+			bank->context.oe = __raw_readl(
+					bank->base + OMAP24XX_GPIO_OE);
+			bank->context.leveldetect0 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			bank->context.leveldetect1 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			bank->context.risingdetect = __raw_readl(bank->base +
+					OMAP24XX_GPIO_RISINGDETECT);
+			bank->context.fallingdetect = __raw_readl(bank->base +
+					OMAP24XX_GPIO_FALLINGDETECT);
+			bank->context.dataout = __raw_readl(
+					bank->base + OMAP24XX_GPIO_DATAOUT);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			bank->context.irqenable1 = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQSTATUSSET0);
+			bank->context.irqenable2 = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQSTATUSSET1);
+			bank->context.wake_en = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQWAKEN0);
+			bank->context.ctrl = __raw_readl(
+					bank->base + OMAP4_GPIO_CTRL);
+			bank->context.oe = __raw_readl(
+					bank->base + OMAP24XX_GPIO_OE);
+			bank->context.leveldetect0 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			bank->context.leveldetect1 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			bank->context.risingdetect = __raw_readl(bank->base +
+					OMAP4_GPIO_RISINGDETECT);
+			bank->context.fallingdetect = __raw_readl(bank->base +
+					OMAP4_GPIO_FALLINGDETECT);
+			bank->context.dataout = __raw_readl(
+					bank->base + OMAP4_GPIO_DATAOUT);
+		}
 	}
 }
 
-/* restore the required registers of bank 2-6 */
 void omap_gpio_restore_context(void)
 {
 	int i;
@@ -2069,29 +2088,51 @@ void omap_gpio_restore_context(void)
 		if (!bank->looses_context)
 			continue;
 
-		__raw_writel(bank->context.irqenable1,
-				bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		__raw_writel(bank->context.irqenable2,
-				bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		__raw_writel(bank->context.wake_en,
-				bank->base + OMAP24XX_GPIO_WAKE_EN);
-		__raw_writel(bank->context.ctrl,
-				bank->base + OMAP24XX_GPIO_CTRL);
-		__raw_writel(bank->context.oe,
-				bank->base + OMAP24XX_GPIO_OE);
-		__raw_writel(bank->context.leveldetect0,
-				bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		__raw_writel(bank->context.leveldetect1,
-				bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		__raw_writel(bank->context.risingdetect,
-				bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		__raw_writel(bank->context.fallingdetect,
-				bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		__raw_writel(bank->context.dataout,
-				bank->base + OMAP24XX_GPIO_DATAOUT);
+		if (bank->method == METHOD_GPIO_24XX) {
+			__raw_writel(bank->context.irqenable1, bank->base +
+						OMAP24XX_GPIO_IRQENABLE1);
+			__raw_writel(bank->context.irqenable2, bank->base +
+						OMAP24XX_GPIO_IRQENABLE2);
+			__raw_writel(bank->context.wake_en, bank->base +
+						OMAP24XX_GPIO_WAKE_EN);
+			__raw_writel(bank->context.ctrl, bank->base +
+						OMAP24XX_GPIO_CTRL);
+			__raw_writel(bank->context.oe, bank->base +
+						OMAP24XX_GPIO_OE);
+			__raw_writel(bank->context.leveldetect0, bank->base +
+						OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(bank->context.leveldetect1, bank->base +
+						OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(bank->context.risingdetect, bank->base +
+						OMAP24XX_GPIO_RISINGDETECT);
+			__raw_writel(bank->context.fallingdetect, bank->base +
+						OMAP24XX_GPIO_FALLINGDETECT);
+			__raw_writel(bank->context.dataout, bank->base +
+						OMAP24XX_GPIO_DATAOUT);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			__raw_writel(bank->context.irqenable1, bank->base +
+						OMAP4_GPIO_IRQSTATUSSET0);
+			__raw_writel(bank->context.irqenable2, bank->base +
+						OMAP4_GPIO_IRQSTATUSSET1);
+			__raw_writel(bank->context.wake_en, bank->base +
+						OMAP4_GPIO_IRQWAKEN0);
+			__raw_writel(bank->context.ctrl, bank->base +
+						OMAP4_GPIO_CTRL);
+			__raw_writel(bank->context.oe, bank->base +
+						OMAP24XX_GPIO_OE);
+			__raw_writel(bank->context.leveldetect0, bank->base +
+						OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(bank->context.leveldetect1, bank->base +
+						OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(bank->context.risingdetect, bank->base +
+						OMAP4_GPIO_RISINGDETECT);
+			__raw_writel(bank->context.fallingdetect, bank->base +
+						OMAP4_GPIO_FALLINGDETECT);
+			__raw_writel(bank->context.dataout, bank->base +
+						OMAP4_GPIO_DATAOUT);
+		}
 	}
 }
-#endif
 
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 3/7] OMAP4: GPIO: Save/restore context
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Modify the omap_gpio_save/restore_context to support OMAP4
architecture so that the OMAP GPIO driver need not be modified
when OMAP4 off mode support is available.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  131 +++++++++++++++++++++++++++++---------------
 1 files changed, 86 insertions(+), 45 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 74085b5..e68da08 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -2022,43 +2022,62 @@ void omap2_gpio_resume_after_idle(void)
 
 #endif
 
-#ifdef CONFIG_ARCH_OMAP3
-/* save the registers of bank 2-6 */
 void omap_gpio_save_context(void)
 {
 	int i;
 
-	/* saving banks from 2-6 only since GPIO1 is in WKUP */
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
 		if (!bank->looses_context)
 			continue;
 
-		bank->context.irqenable1 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		bank->context.irqenable2 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		bank->context.wake_en =
-			__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
-		bank->context.ctrl =
-			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-		bank->context.oe =
-			__raw_readl(bank->base + OMAP24XX_GPIO_OE);
-		bank->context.leveldetect0 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		bank->context.leveldetect1 =
-			__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		bank->context.risingdetect =
-			__raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		bank->context.fallingdetect =
-			__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		bank->context.dataout =
-			__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
+		if (bank->method == METHOD_GPIO_24XX) {
+			bank->context.irqenable1 = __raw_readl(
+					bank->base + OMAP24XX_GPIO_IRQENABLE1);
+			bank->context.irqenable2 = __raw_readl(
+					bank->base + OMAP24XX_GPIO_IRQENABLE2);
+			bank->context.wake_en = __raw_readl(
+					bank->base + OMAP24XX_GPIO_WAKE_EN);
+			bank->context.ctrl = __raw_readl(
+					bank->base + OMAP24XX_GPIO_CTRL);
+			bank->context.oe = __raw_readl(
+					bank->base + OMAP24XX_GPIO_OE);
+			bank->context.leveldetect0 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			bank->context.leveldetect1 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			bank->context.risingdetect = __raw_readl(bank->base +
+					OMAP24XX_GPIO_RISINGDETECT);
+			bank->context.fallingdetect = __raw_readl(bank->base +
+					OMAP24XX_GPIO_FALLINGDETECT);
+			bank->context.dataout = __raw_readl(
+					bank->base + OMAP24XX_GPIO_DATAOUT);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			bank->context.irqenable1 = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQSTATUSSET0);
+			bank->context.irqenable2 = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQSTATUSSET1);
+			bank->context.wake_en = __raw_readl(
+					bank->base + OMAP4_GPIO_IRQWAKEN0);
+			bank->context.ctrl = __raw_readl(
+					bank->base + OMAP4_GPIO_CTRL);
+			bank->context.oe = __raw_readl(
+					bank->base + OMAP24XX_GPIO_OE);
+			bank->context.leveldetect0 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			bank->context.leveldetect1 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			bank->context.risingdetect = __raw_readl(bank->base +
+					OMAP4_GPIO_RISINGDETECT);
+			bank->context.fallingdetect = __raw_readl(bank->base +
+					OMAP4_GPIO_FALLINGDETECT);
+			bank->context.dataout = __raw_readl(
+					bank->base + OMAP4_GPIO_DATAOUT);
+		}
 	}
 }
 
-/* restore the required registers of bank 2-6 */
 void omap_gpio_restore_context(void)
 {
 	int i;
@@ -2069,29 +2088,51 @@ void omap_gpio_restore_context(void)
 		if (!bank->looses_context)
 			continue;
 
-		__raw_writel(bank->context.irqenable1,
-				bank->base + OMAP24XX_GPIO_IRQENABLE1);
-		__raw_writel(bank->context.irqenable2,
-				bank->base + OMAP24XX_GPIO_IRQENABLE2);
-		__raw_writel(bank->context.wake_en,
-				bank->base + OMAP24XX_GPIO_WAKE_EN);
-		__raw_writel(bank->context.ctrl,
-				bank->base + OMAP24XX_GPIO_CTRL);
-		__raw_writel(bank->context.oe,
-				bank->base + OMAP24XX_GPIO_OE);
-		__raw_writel(bank->context.leveldetect0,
-				bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-		__raw_writel(bank->context.leveldetect1,
-				bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-		__raw_writel(bank->context.risingdetect,
-				bank->base + OMAP24XX_GPIO_RISINGDETECT);
-		__raw_writel(bank->context.fallingdetect,
-				bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-		__raw_writel(bank->context.dataout,
-				bank->base + OMAP24XX_GPIO_DATAOUT);
+		if (bank->method == METHOD_GPIO_24XX) {
+			__raw_writel(bank->context.irqenable1, bank->base +
+						OMAP24XX_GPIO_IRQENABLE1);
+			__raw_writel(bank->context.irqenable2, bank->base +
+						OMAP24XX_GPIO_IRQENABLE2);
+			__raw_writel(bank->context.wake_en, bank->base +
+						OMAP24XX_GPIO_WAKE_EN);
+			__raw_writel(bank->context.ctrl, bank->base +
+						OMAP24XX_GPIO_CTRL);
+			__raw_writel(bank->context.oe, bank->base +
+						OMAP24XX_GPIO_OE);
+			__raw_writel(bank->context.leveldetect0, bank->base +
+						OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(bank->context.leveldetect1, bank->base +
+						OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(bank->context.risingdetect, bank->base +
+						OMAP24XX_GPIO_RISINGDETECT);
+			__raw_writel(bank->context.fallingdetect, bank->base +
+						OMAP24XX_GPIO_FALLINGDETECT);
+			__raw_writel(bank->context.dataout, bank->base +
+						OMAP24XX_GPIO_DATAOUT);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			__raw_writel(bank->context.irqenable1, bank->base +
+						OMAP4_GPIO_IRQSTATUSSET0);
+			__raw_writel(bank->context.irqenable2, bank->base +
+						OMAP4_GPIO_IRQSTATUSSET1);
+			__raw_writel(bank->context.wake_en, bank->base +
+						OMAP4_GPIO_IRQWAKEN0);
+			__raw_writel(bank->context.ctrl, bank->base +
+						OMAP4_GPIO_CTRL);
+			__raw_writel(bank->context.oe, bank->base +
+						OMAP24XX_GPIO_OE);
+			__raw_writel(bank->context.leveldetect0, bank->base +
+						OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(bank->context.leveldetect1, bank->base +
+						OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(bank->context.risingdetect, bank->base +
+						OMAP4_GPIO_RISINGDETECT);
+			__raw_writel(bank->context.fallingdetect, bank->base +
+						OMAP4_GPIO_FALLINGDETECT);
+			__raw_writel(bank->context.dataout, bank->base +
+						OMAP4_GPIO_DATAOUT);
+		}
 	}
 }
-#endif
 
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 4/7] OMAP: GPIO: handle save/restore ctx in GPIO driver
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Modify omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle()
functions to handle save context & restore context respectively in the
OMAP GPIO driver itself instead of calling these functions from pm specific
files. For this, in gpio_prepare_for_idle(), use
omap_device_get_context_loss_count() and in gpio_resume_after_idle()
call it again. If the count is different, do restore context.

context lost count is modified in omap_sram_idle() path when
pwrdm_post_transition() is called. But pwrdm_post_transition() is called
only after omap_gpio_resume_after_idle() is called. Hence correct this
so that context lost count is modified before calling
omap_gpio_resume_after_idle().

omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle()
do nothing if none of the GPIOs in a bank is being used.

Also remove usage of cpu_is_* checks from the above mentioned
functions and fix the multi-line comment style

Signed-off-by: Charulatha V <charu@ti.com>
---
Note that the usage of bank->method checks would be re-addressed
during OMAP GPIO cleanup series which would follow this patch series

 arch/arm/mach-omap2/pm34xx.c           |   22 +---
 arch/arm/plat-omap/gpio.c              |  226 ++++++++++++++++---------------
 arch/arm/plat-omap/include/plat/gpio.h |    2 -
 3 files changed, 122 insertions(+), 128 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 0c5e3a4..682d147 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -91,16 +91,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
-static inline void omap3_per_save_context(void)
-{
-	omap_gpio_save_context();
-}
-
-static inline void omap3_per_restore_context(void)
-{
-	omap_gpio_restore_context();
-}
-
 static void omap3_enable_io_chain(void)
 {
 	int timeout = 0;
@@ -395,8 +385,10 @@ void omap_sram_idle(void)
 	if (!is_suspending())
 		if (per_next_state < PWRDM_POWER_ON ||
 		    core_next_state < PWRDM_POWER_ON)
-			if (!console_trylock())
+			if (!console_trylock()) {
+				pwrdm_post_transition();
 				goto console_still_active;
+			}
 
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
@@ -404,8 +396,6 @@ void omap_sram_idle(void)
 		omap_uart_prepare_idle(2);
 		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_going_off);
-		if (per_next_state == PWRDM_POWER_OFF)
-				omap3_per_save_context();
 	}
 
 	/* CORE */
@@ -467,12 +457,12 @@ void omap_sram_idle(void)
 	}
 	omap3_intc_resume_idle();
 
+	pwrdm_post_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
 		omap2_gpio_resume_after_idle();
-		if (per_prev_state == PWRDM_POWER_OFF)
-			omap3_per_restore_context();
 		omap_uart_resume_idle(2);
 		omap_uart_resume_idle(3);
 	}
@@ -490,8 +480,6 @@ console_still_active:
 		omap3_disable_io_chain();
 	}
 
-	pwrdm_post_transition();
-
 	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index e68da08..5d4ed6c 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -24,6 +24,8 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 
+#include <plat/omap_device.h>
+
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
@@ -173,6 +175,7 @@ struct gpio_bank {
 	bool dbck_flag;
 	int stride;
 	bool looses_context;
+	u32 ctx_lost_cnt_before;
 };
 
 /*
@@ -1852,6 +1855,8 @@ static struct sys_device omap_gpio_device = {
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+static void omap_gpio_save_context(struct gpio_bank *bank);
+static void omap_gpio_restore_context(struct gpio_bank *bank);
 
 static int workaround_enabled;
 
@@ -1861,9 +1866,14 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+		struct platform_device *pdev;
 		u32 l1 = 0, l2 = 0;
 		int j;
 
+		/* If the gpio bank is not used, do nothing */
+		if (!bank->mod_usage)
+			continue;
+
 		if (!bank->looses_context)
 			continue;
 
@@ -1873,22 +1883,22 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 		if (!off_mode)
 			continue;
 
-		/* If going to OFF, remove triggering for all
+		/*
+		 * If going to OFF, remove triggering for all
 		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
-		 * generated.  See OMAP2420 Errata item 1.101. */
+		 * generated.  See OMAP2420 Errata item 1.101.
+		 */
 		if (!(bank->enabled_non_wakeup_gpios))
-			continue;
+			goto save_gpio_ctx;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			bank->saved_datain = __raw_readl(bank->base +
 					OMAP24XX_GPIO_DATAIN);
 			l1 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
 			l2 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			bank->saved_datain = __raw_readl(bank->base +
 						OMAP4_GPIO_DATAIN);
 			l1 = __raw_readl(bank->base +
@@ -1902,19 +1912,23 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 		l1 &= ~bank->enabled_non_wakeup_gpios;
 		l2 &= ~bank->enabled_non_wakeup_gpios;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			__raw_writel(l1, bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
 			__raw_writel(l2, bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
 			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
 		}
 
 		c++;
+
+save_gpio_ctx:
+		pdev = to_platform_device(bank->dev);
+		bank->ctx_lost_cnt_before =
+				omap_device_get_context_loss_count(pdev);
+		omap_gpio_save_context(bank);
 	}
 	if (!c) {
 		workaround_enabled = 0;
@@ -1926,33 +1940,43 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
+	u32 ctx_lost_cnt_after;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+		struct platform_device *pdev;
 		u32 l = 0, gen, gen0, gen1;
 		int j;
 
+		/* If the gpio bank is not used, do nothing */
+		if (!bank->mod_usage)
+			continue;
+
 		if (!bank->looses_context)
 			continue;
 
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_enable(bank->dbck);
 
-		if (!workaround_enabled)
+		pdev = to_platform_device(bank->dev);
+		ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
+
+		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
 			continue;
 
+		if (!workaround_enabled)
+			goto restore_gpio_ctx;
+
 		if (!(bank->enabled_non_wakeup_gpios))
-			continue;
+			goto restore_gpio_ctx;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			__raw_writel(bank->saved_fallingdetect,
 				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
 			__raw_writel(bank->saved_risingdetect,
 				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
 			l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			__raw_writel(bank->saved_fallingdetect,
 				 bank->base + OMAP4_GPIO_FALLINGDETECT);
 			__raw_writel(bank->saved_risingdetect,
@@ -1960,10 +1984,12 @@ void omap2_gpio_resume_after_idle(void)
 			l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
 		}
 
-		/* Check if any of the non-wakeup interrupt GPIOs have changed
+		/*
+		 * Check if any of the non-wakeup interrupt GPIOs have changed
 		 * state.  If so, generate an IRQ by software.  This is
 		 * horribly racy, but it's the best we can do to work around
-		 * this silicon bug. */
+		 * this silicon bug.
+		 */
 		l ^= bank->saved_datain;
 		l &= bank->enabled_non_wakeup_gpios;
 
@@ -1986,7 +2012,7 @@ void omap2_gpio_resume_after_idle(void)
 		if (gen) {
 			u32 old0, old1;
 
-			if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+			if (bank->method == METHOD_GPIO_24XX) {
 				old0 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT0);
 				old1 = __raw_readl(bank->base +
@@ -1999,9 +2025,7 @@ void omap2_gpio_resume_after_idle(void)
 					OMAP24XX_GPIO_LEVELDETECT0);
 				__raw_writel(old1, bank->base +
 					OMAP24XX_GPIO_LEVELDETECT1);
-			}
-
-			if (cpu_is_omap44xx()) {
+			} else if (bank->method == METHOD_GPIO_44XX) {
 				old0 = __raw_readl(bank->base +
 						OMAP4_GPIO_LEVELDETECT0);
 				old1 = __raw_readl(bank->base +
@@ -2016,123 +2040,107 @@ void omap2_gpio_resume_after_idle(void)
 						OMAP4_GPIO_LEVELDETECT1);
 			}
 		}
+
+restore_gpio_ctx:
+		omap_gpio_restore_context(bank);
 	}
 
 }
 
-#endif
-
-void omap_gpio_save_context(void)
+void omap_gpio_save_context(struct gpio_bank *bank)
 {
-	int i;
-
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-
-		if (!bank->looses_context)
-			continue;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			bank->context.irqenable1 = __raw_readl(
+	if (bank->method == METHOD_GPIO_24XX) {
+		bank->context.irqenable1 = __raw_readl(
 					bank->base + OMAP24XX_GPIO_IRQENABLE1);
-			bank->context.irqenable2 = __raw_readl(
+		bank->context.irqenable2 = __raw_readl(
 					bank->base + OMAP24XX_GPIO_IRQENABLE2);
-			bank->context.wake_en = __raw_readl(
+		bank->context.wake_en = __raw_readl(
 					bank->base + OMAP24XX_GPIO_WAKE_EN);
-			bank->context.ctrl = __raw_readl(
+		bank->context.ctrl = __raw_readl(
 					bank->base + OMAP24XX_GPIO_CTRL);
-			bank->context.oe = __raw_readl(
+		bank->context.oe = __raw_readl(
 					bank->base + OMAP24XX_GPIO_OE);
-			bank->context.leveldetect0 = __raw_readl(bank->base +
+		bank->context.leveldetect0 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT0);
-			bank->context.leveldetect1 = __raw_readl(bank->base +
+		bank->context.leveldetect1 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT1);
-			bank->context.risingdetect = __raw_readl(bank->base +
+		bank->context.risingdetect = __raw_readl(bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-			bank->context.fallingdetect = __raw_readl(bank->base +
+		bank->context.fallingdetect = __raw_readl(bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
-			bank->context.dataout = __raw_readl(
+		bank->context.dataout = __raw_readl(
 					bank->base + OMAP24XX_GPIO_DATAOUT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			bank->context.irqenable1 = __raw_readl(
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		bank->context.irqenable1 = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQSTATUSSET0);
-			bank->context.irqenable2 = __raw_readl(
+		bank->context.irqenable2 = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQSTATUSSET1);
-			bank->context.wake_en = __raw_readl(
+		bank->context.wake_en = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQWAKEN0);
-			bank->context.ctrl = __raw_readl(
+		bank->context.ctrl = __raw_readl(
 					bank->base + OMAP4_GPIO_CTRL);
-			bank->context.oe = __raw_readl(
+		bank->context.oe = __raw_readl(
 					bank->base + OMAP24XX_GPIO_OE);
-			bank->context.leveldetect0 = __raw_readl(bank->base +
+		bank->context.leveldetect0 = __raw_readl(bank->base +
 					OMAP4_GPIO_LEVELDETECT0);
-			bank->context.leveldetect1 = __raw_readl(bank->base +
+		bank->context.leveldetect1 = __raw_readl(bank->base +
 					OMAP4_GPIO_LEVELDETECT1);
-			bank->context.risingdetect = __raw_readl(bank->base +
+		bank->context.risingdetect = __raw_readl(bank->base +
 					OMAP4_GPIO_RISINGDETECT);
-			bank->context.fallingdetect = __raw_readl(bank->base +
+		bank->context.fallingdetect = __raw_readl(bank->base +
 					OMAP4_GPIO_FALLINGDETECT);
-			bank->context.dataout = __raw_readl(
+		bank->context.dataout = __raw_readl(
 					bank->base + OMAP4_GPIO_DATAOUT);
-		}
 	}
 }
 
-void omap_gpio_restore_context(void)
+void omap_gpio_restore_context(struct gpio_bank *bank)
 {
-	int i;
-
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-
-		if (!bank->looses_context)
-			continue;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(bank->context.irqenable1, bank->base +
-						OMAP24XX_GPIO_IRQENABLE1);
-			__raw_writel(bank->context.irqenable2, bank->base +
-						OMAP24XX_GPIO_IRQENABLE2);
-			__raw_writel(bank->context.wake_en, bank->base +
-						OMAP24XX_GPIO_WAKE_EN);
-			__raw_writel(bank->context.ctrl, bank->base +
-						OMAP24XX_GPIO_CTRL);
-			__raw_writel(bank->context.oe, bank->base +
-						OMAP24XX_GPIO_OE);
-			__raw_writel(bank->context.leveldetect0, bank->base +
-						OMAP24XX_GPIO_LEVELDETECT0);
-			__raw_writel(bank->context.leveldetect1, bank->base +
-						OMAP24XX_GPIO_LEVELDETECT1);
-			__raw_writel(bank->context.risingdetect, bank->base +
-						OMAP24XX_GPIO_RISINGDETECT);
-			__raw_writel(bank->context.fallingdetect, bank->base +
-						OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(bank->context.dataout, bank->base +
-						OMAP24XX_GPIO_DATAOUT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(bank->context.irqenable1, bank->base +
-						OMAP4_GPIO_IRQSTATUSSET0);
-			__raw_writel(bank->context.irqenable2, bank->base +
-						OMAP4_GPIO_IRQSTATUSSET1);
-			__raw_writel(bank->context.wake_en, bank->base +
-						OMAP4_GPIO_IRQWAKEN0);
-			__raw_writel(bank->context.ctrl, bank->base +
-						OMAP4_GPIO_CTRL);
-			__raw_writel(bank->context.oe, bank->base +
-						OMAP24XX_GPIO_OE);
-			__raw_writel(bank->context.leveldetect0, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-			__raw_writel(bank->context.leveldetect1, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-			__raw_writel(bank->context.risingdetect, bank->base +
-						OMAP4_GPIO_RISINGDETECT);
-			__raw_writel(bank->context.fallingdetect, bank->base +
-						OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(bank->context.dataout, bank->base +
-						OMAP4_GPIO_DATAOUT);
-		}
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(bank->context.irqenable1, bank->base +
+					OMAP24XX_GPIO_IRQENABLE1);
+		__raw_writel(bank->context.irqenable2, bank->base +
+					OMAP24XX_GPIO_IRQENABLE2);
+		__raw_writel(bank->context.wake_en, bank->base +
+					OMAP24XX_GPIO_WAKE_EN);
+		__raw_writel(bank->context.ctrl, bank->base +
+					OMAP24XX_GPIO_CTRL);
+		__raw_writel(bank->context.oe, bank->base +
+					OMAP24XX_GPIO_OE);
+		__raw_writel(bank->context.leveldetect0, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+		__raw_writel(bank->context.leveldetect1, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+		__raw_writel(bank->context.risingdetect, bank->base +
+					OMAP24XX_GPIO_RISINGDETECT);
+		__raw_writel(bank->context.fallingdetect, bank->base +
+					OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(bank->context.dataout, bank->base +
+					OMAP24XX_GPIO_DATAOUT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(bank->context.irqenable1, bank->base +
+					OMAP4_GPIO_IRQSTATUSSET0);
+		__raw_writel(bank->context.irqenable2, bank->base +
+					OMAP4_GPIO_IRQSTATUSSET1);
+		__raw_writel(bank->context.wake_en, bank->base +
+					OMAP4_GPIO_IRQWAKEN0);
+		__raw_writel(bank->context.ctrl, bank->base +
+					OMAP4_GPIO_CTRL);
+		__raw_writel(bank->context.oe, bank->base +
+					OMAP24XX_GPIO_OE);
+		__raw_writel(bank->context.leveldetect0, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+		__raw_writel(bank->context.leveldetect1, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+		__raw_writel(bank->context.risingdetect, bank->base +
+					OMAP4_GPIO_RISINGDETECT);
+		__raw_writel(bank->context.fallingdetect, bank->base +
+					OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(bank->context.dataout, bank->base +
+					OMAP4_GPIO_DATAOUT);
 	}
 }
+#endif
 
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 15aeb71..84b9106 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -87,8 +87,6 @@ extern void omap2_gpio_prepare_for_idle(int off_mode);
 extern void omap2_gpio_resume_after_idle(void);
 extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
-extern void omap_gpio_save_context(void);
-extern void omap_gpio_restore_context(void);
 /*-------------------------------------------------------------------------*/
 
 /* Wrappers for "new style" GPIO calls, using the new infrastructure
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 4/7] OMAP: GPIO: handle save/restore ctx in GPIO driver
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Modify omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle()
functions to handle save context & restore context respectively in the
OMAP GPIO driver itself instead of calling these functions from pm specific
files. For this, in gpio_prepare_for_idle(), use
omap_device_get_context_loss_count() and in gpio_resume_after_idle()
call it again. If the count is different, do restore context.

context lost count is modified in omap_sram_idle() path when
pwrdm_post_transition() is called. But pwrdm_post_transition() is called
only after omap_gpio_resume_after_idle() is called. Hence correct this
so that context lost count is modified before calling
omap_gpio_resume_after_idle().

omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle()
do nothing if none of the GPIOs in a bank is being used.

Also remove usage of cpu_is_* checks from the above mentioned
functions and fix the multi-line comment style

Signed-off-by: Charulatha V <charu@ti.com>
---
Note that the usage of bank->method checks would be re-addressed
during OMAP GPIO cleanup series which would follow this patch series

 arch/arm/mach-omap2/pm34xx.c           |   22 +---
 arch/arm/plat-omap/gpio.c              |  226 ++++++++++++++++---------------
 arch/arm/plat-omap/include/plat/gpio.h |    2 -
 3 files changed, 122 insertions(+), 128 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 0c5e3a4..682d147 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -91,16 +91,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
-static inline void omap3_per_save_context(void)
-{
-	omap_gpio_save_context();
-}
-
-static inline void omap3_per_restore_context(void)
-{
-	omap_gpio_restore_context();
-}
-
 static void omap3_enable_io_chain(void)
 {
 	int timeout = 0;
@@ -395,8 +385,10 @@ void omap_sram_idle(void)
 	if (!is_suspending())
 		if (per_next_state < PWRDM_POWER_ON ||
 		    core_next_state < PWRDM_POWER_ON)
-			if (!console_trylock())
+			if (!console_trylock()) {
+				pwrdm_post_transition();
 				goto console_still_active;
+			}
 
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
@@ -404,8 +396,6 @@ void omap_sram_idle(void)
 		omap_uart_prepare_idle(2);
 		omap_uart_prepare_idle(3);
 		omap2_gpio_prepare_for_idle(per_going_off);
-		if (per_next_state == PWRDM_POWER_OFF)
-				omap3_per_save_context();
 	}
 
 	/* CORE */
@@ -467,12 +457,12 @@ void omap_sram_idle(void)
 	}
 	omap3_intc_resume_idle();
 
+	pwrdm_post_transition();
+
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
 		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
 		omap2_gpio_resume_after_idle();
-		if (per_prev_state == PWRDM_POWER_OFF)
-			omap3_per_restore_context();
 		omap_uart_resume_idle(2);
 		omap_uart_resume_idle(3);
 	}
@@ -490,8 +480,6 @@ console_still_active:
 		omap3_disable_io_chain();
 	}
 
-	pwrdm_post_transition();
-
 	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index e68da08..5d4ed6c 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -24,6 +24,8 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 
+#include <plat/omap_device.h>
+
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
@@ -173,6 +175,7 @@ struct gpio_bank {
 	bool dbck_flag;
 	int stride;
 	bool looses_context;
+	u32 ctx_lost_cnt_before;
 };
 
 /*
@@ -1852,6 +1855,8 @@ static struct sys_device omap_gpio_device = {
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+static void omap_gpio_save_context(struct gpio_bank *bank);
+static void omap_gpio_restore_context(struct gpio_bank *bank);
 
 static int workaround_enabled;
 
@@ -1861,9 +1866,14 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+		struct platform_device *pdev;
 		u32 l1 = 0, l2 = 0;
 		int j;
 
+		/* If the gpio bank is not used, do nothing */
+		if (!bank->mod_usage)
+			continue;
+
 		if (!bank->looses_context)
 			continue;
 
@@ -1873,22 +1883,22 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 		if (!off_mode)
 			continue;
 
-		/* If going to OFF, remove triggering for all
+		/*
+		 * If going to OFF, remove triggering for all
 		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
-		 * generated.  See OMAP2420 Errata item 1.101. */
+		 * generated.  See OMAP2420 Errata item 1.101.
+		 */
 		if (!(bank->enabled_non_wakeup_gpios))
-			continue;
+			goto save_gpio_ctx;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			bank->saved_datain = __raw_readl(bank->base +
 					OMAP24XX_GPIO_DATAIN);
 			l1 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
 			l2 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			bank->saved_datain = __raw_readl(bank->base +
 						OMAP4_GPIO_DATAIN);
 			l1 = __raw_readl(bank->base +
@@ -1902,19 +1912,23 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 		l1 &= ~bank->enabled_non_wakeup_gpios;
 		l2 &= ~bank->enabled_non_wakeup_gpios;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			__raw_writel(l1, bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
 			__raw_writel(l2, bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
 			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
 		}
 
 		c++;
+
+save_gpio_ctx:
+		pdev = to_platform_device(bank->dev);
+		bank->ctx_lost_cnt_before =
+				omap_device_get_context_loss_count(pdev);
+		omap_gpio_save_context(bank);
 	}
 	if (!c) {
 		workaround_enabled = 0;
@@ -1926,33 +1940,43 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
+	u32 ctx_lost_cnt_after;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
+		struct platform_device *pdev;
 		u32 l = 0, gen, gen0, gen1;
 		int j;
 
+		/* If the gpio bank is not used, do nothing */
+		if (!bank->mod_usage)
+			continue;
+
 		if (!bank->looses_context)
 			continue;
 
 		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
 			clk_enable(bank->dbck);
 
-		if (!workaround_enabled)
+		pdev = to_platform_device(bank->dev);
+		ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
+
+		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
 			continue;
 
+		if (!workaround_enabled)
+			goto restore_gpio_ctx;
+
 		if (!(bank->enabled_non_wakeup_gpios))
-			continue;
+			goto restore_gpio_ctx;
 
-		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		if (bank->method == METHOD_GPIO_24XX) {
 			__raw_writel(bank->saved_fallingdetect,
 				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
 			__raw_writel(bank->saved_risingdetect,
 				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
 			l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
-		}
-
-		if (cpu_is_omap44xx()) {
+		} else if (bank->method == METHOD_GPIO_44XX) {
 			__raw_writel(bank->saved_fallingdetect,
 				 bank->base + OMAP4_GPIO_FALLINGDETECT);
 			__raw_writel(bank->saved_risingdetect,
@@ -1960,10 +1984,12 @@ void omap2_gpio_resume_after_idle(void)
 			l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
 		}
 
-		/* Check if any of the non-wakeup interrupt GPIOs have changed
+		/*
+		 * Check if any of the non-wakeup interrupt GPIOs have changed
 		 * state.  If so, generate an IRQ by software.  This is
 		 * horribly racy, but it's the best we can do to work around
-		 * this silicon bug. */
+		 * this silicon bug.
+		 */
 		l ^= bank->saved_datain;
 		l &= bank->enabled_non_wakeup_gpios;
 
@@ -1986,7 +2012,7 @@ void omap2_gpio_resume_after_idle(void)
 		if (gen) {
 			u32 old0, old1;
 
-			if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+			if (bank->method == METHOD_GPIO_24XX) {
 				old0 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT0);
 				old1 = __raw_readl(bank->base +
@@ -1999,9 +2025,7 @@ void omap2_gpio_resume_after_idle(void)
 					OMAP24XX_GPIO_LEVELDETECT0);
 				__raw_writel(old1, bank->base +
 					OMAP24XX_GPIO_LEVELDETECT1);
-			}
-
-			if (cpu_is_omap44xx()) {
+			} else if (bank->method == METHOD_GPIO_44XX) {
 				old0 = __raw_readl(bank->base +
 						OMAP4_GPIO_LEVELDETECT0);
 				old1 = __raw_readl(bank->base +
@@ -2016,123 +2040,107 @@ void omap2_gpio_resume_after_idle(void)
 						OMAP4_GPIO_LEVELDETECT1);
 			}
 		}
+
+restore_gpio_ctx:
+		omap_gpio_restore_context(bank);
 	}
 
 }
 
-#endif
-
-void omap_gpio_save_context(void)
+void omap_gpio_save_context(struct gpio_bank *bank)
 {
-	int i;
-
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-
-		if (!bank->looses_context)
-			continue;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			bank->context.irqenable1 = __raw_readl(
+	if (bank->method == METHOD_GPIO_24XX) {
+		bank->context.irqenable1 = __raw_readl(
 					bank->base + OMAP24XX_GPIO_IRQENABLE1);
-			bank->context.irqenable2 = __raw_readl(
+		bank->context.irqenable2 = __raw_readl(
 					bank->base + OMAP24XX_GPIO_IRQENABLE2);
-			bank->context.wake_en = __raw_readl(
+		bank->context.wake_en = __raw_readl(
 					bank->base + OMAP24XX_GPIO_WAKE_EN);
-			bank->context.ctrl = __raw_readl(
+		bank->context.ctrl = __raw_readl(
 					bank->base + OMAP24XX_GPIO_CTRL);
-			bank->context.oe = __raw_readl(
+		bank->context.oe = __raw_readl(
 					bank->base + OMAP24XX_GPIO_OE);
-			bank->context.leveldetect0 = __raw_readl(bank->base +
+		bank->context.leveldetect0 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT0);
-			bank->context.leveldetect1 = __raw_readl(bank->base +
+		bank->context.leveldetect1 = __raw_readl(bank->base +
 					OMAP24XX_GPIO_LEVELDETECT1);
-			bank->context.risingdetect = __raw_readl(bank->base +
+		bank->context.risingdetect = __raw_readl(bank->base +
 					OMAP24XX_GPIO_RISINGDETECT);
-			bank->context.fallingdetect = __raw_readl(bank->base +
+		bank->context.fallingdetect = __raw_readl(bank->base +
 					OMAP24XX_GPIO_FALLINGDETECT);
-			bank->context.dataout = __raw_readl(
+		bank->context.dataout = __raw_readl(
 					bank->base + OMAP24XX_GPIO_DATAOUT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			bank->context.irqenable1 = __raw_readl(
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		bank->context.irqenable1 = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQSTATUSSET0);
-			bank->context.irqenable2 = __raw_readl(
+		bank->context.irqenable2 = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQSTATUSSET1);
-			bank->context.wake_en = __raw_readl(
+		bank->context.wake_en = __raw_readl(
 					bank->base + OMAP4_GPIO_IRQWAKEN0);
-			bank->context.ctrl = __raw_readl(
+		bank->context.ctrl = __raw_readl(
 					bank->base + OMAP4_GPIO_CTRL);
-			bank->context.oe = __raw_readl(
+		bank->context.oe = __raw_readl(
 					bank->base + OMAP24XX_GPIO_OE);
-			bank->context.leveldetect0 = __raw_readl(bank->base +
+		bank->context.leveldetect0 = __raw_readl(bank->base +
 					OMAP4_GPIO_LEVELDETECT0);
-			bank->context.leveldetect1 = __raw_readl(bank->base +
+		bank->context.leveldetect1 = __raw_readl(bank->base +
 					OMAP4_GPIO_LEVELDETECT1);
-			bank->context.risingdetect = __raw_readl(bank->base +
+		bank->context.risingdetect = __raw_readl(bank->base +
 					OMAP4_GPIO_RISINGDETECT);
-			bank->context.fallingdetect = __raw_readl(bank->base +
+		bank->context.fallingdetect = __raw_readl(bank->base +
 					OMAP4_GPIO_FALLINGDETECT);
-			bank->context.dataout = __raw_readl(
+		bank->context.dataout = __raw_readl(
 					bank->base + OMAP4_GPIO_DATAOUT);
-		}
 	}
 }
 
-void omap_gpio_restore_context(void)
+void omap_gpio_restore_context(struct gpio_bank *bank)
 {
-	int i;
-
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-
-		if (!bank->looses_context)
-			continue;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(bank->context.irqenable1, bank->base +
-						OMAP24XX_GPIO_IRQENABLE1);
-			__raw_writel(bank->context.irqenable2, bank->base +
-						OMAP24XX_GPIO_IRQENABLE2);
-			__raw_writel(bank->context.wake_en, bank->base +
-						OMAP24XX_GPIO_WAKE_EN);
-			__raw_writel(bank->context.ctrl, bank->base +
-						OMAP24XX_GPIO_CTRL);
-			__raw_writel(bank->context.oe, bank->base +
-						OMAP24XX_GPIO_OE);
-			__raw_writel(bank->context.leveldetect0, bank->base +
-						OMAP24XX_GPIO_LEVELDETECT0);
-			__raw_writel(bank->context.leveldetect1, bank->base +
-						OMAP24XX_GPIO_LEVELDETECT1);
-			__raw_writel(bank->context.risingdetect, bank->base +
-						OMAP24XX_GPIO_RISINGDETECT);
-			__raw_writel(bank->context.fallingdetect, bank->base +
-						OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(bank->context.dataout, bank->base +
-						OMAP24XX_GPIO_DATAOUT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(bank->context.irqenable1, bank->base +
-						OMAP4_GPIO_IRQSTATUSSET0);
-			__raw_writel(bank->context.irqenable2, bank->base +
-						OMAP4_GPIO_IRQSTATUSSET1);
-			__raw_writel(bank->context.wake_en, bank->base +
-						OMAP4_GPIO_IRQWAKEN0);
-			__raw_writel(bank->context.ctrl, bank->base +
-						OMAP4_GPIO_CTRL);
-			__raw_writel(bank->context.oe, bank->base +
-						OMAP24XX_GPIO_OE);
-			__raw_writel(bank->context.leveldetect0, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-			__raw_writel(bank->context.leveldetect1, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-			__raw_writel(bank->context.risingdetect, bank->base +
-						OMAP4_GPIO_RISINGDETECT);
-			__raw_writel(bank->context.fallingdetect, bank->base +
-						OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(bank->context.dataout, bank->base +
-						OMAP4_GPIO_DATAOUT);
-		}
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(bank->context.irqenable1, bank->base +
+					OMAP24XX_GPIO_IRQENABLE1);
+		__raw_writel(bank->context.irqenable2, bank->base +
+					OMAP24XX_GPIO_IRQENABLE2);
+		__raw_writel(bank->context.wake_en, bank->base +
+					OMAP24XX_GPIO_WAKE_EN);
+		__raw_writel(bank->context.ctrl, bank->base +
+					OMAP24XX_GPIO_CTRL);
+		__raw_writel(bank->context.oe, bank->base +
+					OMAP24XX_GPIO_OE);
+		__raw_writel(bank->context.leveldetect0, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+		__raw_writel(bank->context.leveldetect1, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+		__raw_writel(bank->context.risingdetect, bank->base +
+					OMAP24XX_GPIO_RISINGDETECT);
+		__raw_writel(bank->context.fallingdetect, bank->base +
+					OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(bank->context.dataout, bank->base +
+					OMAP24XX_GPIO_DATAOUT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(bank->context.irqenable1, bank->base +
+					OMAP4_GPIO_IRQSTATUSSET0);
+		__raw_writel(bank->context.irqenable2, bank->base +
+					OMAP4_GPIO_IRQSTATUSSET1);
+		__raw_writel(bank->context.wake_en, bank->base +
+					OMAP4_GPIO_IRQWAKEN0);
+		__raw_writel(bank->context.ctrl, bank->base +
+					OMAP4_GPIO_CTRL);
+		__raw_writel(bank->context.oe, bank->base +
+					OMAP24XX_GPIO_OE);
+		__raw_writel(bank->context.leveldetect0, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+		__raw_writel(bank->context.leveldetect1, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+		__raw_writel(bank->context.risingdetect, bank->base +
+					OMAP4_GPIO_RISINGDETECT);
+		__raw_writel(bank->context.fallingdetect, bank->base +
+					OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(bank->context.dataout, bank->base +
+					OMAP4_GPIO_DATAOUT);
 	}
 }
+#endif
 
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 15aeb71..84b9106 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -87,8 +87,6 @@ extern void omap2_gpio_prepare_for_idle(int off_mode);
 extern void omap2_gpio_resume_after_idle(void);
 extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
-extern void omap_gpio_save_context(void);
-extern void omap_gpio_restore_context(void);
 /*-------------------------------------------------------------------------*/
 
 /* Wrappers for "new style" GPIO calls, using the new infrastructure
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 5/7] OMAP2+: GPIO: make workaround_enabled bank specific
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Make workaround_enabled flag bank-specific instead of using a single
flag for all the banks together. This would be helpful while making
use of runtime framework in OMAP GPIO driver which would make the
driver handle each GPIO bank independently.

Also rename workaround_enabled flag to off_mode_wkup_wa_enabled

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |   16 ++++++----------
 1 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 5d4ed6c..5933c98 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -176,6 +176,7 @@ struct gpio_bank {
 	int stride;
 	bool looses_context;
 	u32 ctx_lost_cnt_before;
+	bool off_mode_wkup_wa_enabled;
 };
 
 /*
@@ -1636,6 +1637,7 @@ static void __init omap_gpio_chip_init(struct gpio_bank *bank)
 	static int gpio;
 
 	bank->mod_usage = 0;
+	bank->off_mode_wkup_wa_enabled = false;
 	/*
 	 * REVISIT eventually switch from OMAP-specific gpio structs
 	 * over to the generic ones
@@ -1858,11 +1860,9 @@ static struct sys_device omap_gpio_device = {
 static void omap_gpio_save_context(struct gpio_bank *bank);
 static void omap_gpio_restore_context(struct gpio_bank *bank);
 
-static int workaround_enabled;
-
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
-	int i, c = 0;
+	int i;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
@@ -1922,7 +1922,7 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
 		}
 
-		c++;
+		bank->off_mode_wkup_wa_enabled = true;
 
 save_gpio_ctx:
 		pdev = to_platform_device(bank->dev);
@@ -1930,11 +1930,6 @@ save_gpio_ctx:
 				omap_device_get_context_loss_count(pdev);
 		omap_gpio_save_context(bank);
 	}
-	if (!c) {
-		workaround_enabled = 0;
-		return;
-	}
-	workaround_enabled = 1;
 }
 
 void omap2_gpio_resume_after_idle(void)
@@ -1964,7 +1959,7 @@ void omap2_gpio_resume_after_idle(void)
 		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
 			continue;
 
-		if (!workaround_enabled)
+		if (!bank->off_mode_wkup_wa_enabled)
 			goto restore_gpio_ctx;
 
 		if (!(bank->enabled_non_wakeup_gpios))
@@ -2042,6 +2037,7 @@ void omap2_gpio_resume_after_idle(void)
 		}
 
 restore_gpio_ctx:
+		bank->off_mode_wkup_wa_enabled = false;
 		omap_gpio_restore_context(bank);
 	}
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 5/7] OMAP2+: GPIO: make workaround_enabled bank specific
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Make workaround_enabled flag bank-specific instead of using a single
flag for all the banks together. This would be helpful while making
use of runtime framework in OMAP GPIO driver which would make the
driver handle each GPIO bank independently.

Also rename workaround_enabled flag to off_mode_wkup_wa_enabled

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |   16 ++++++----------
 1 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 5d4ed6c..5933c98 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -176,6 +176,7 @@ struct gpio_bank {
 	int stride;
 	bool looses_context;
 	u32 ctx_lost_cnt_before;
+	bool off_mode_wkup_wa_enabled;
 };
 
 /*
@@ -1636,6 +1637,7 @@ static void __init omap_gpio_chip_init(struct gpio_bank *bank)
 	static int gpio;
 
 	bank->mod_usage = 0;
+	bank->off_mode_wkup_wa_enabled = false;
 	/*
 	 * REVISIT eventually switch from OMAP-specific gpio structs
 	 * over to the generic ones
@@ -1858,11 +1860,9 @@ static struct sys_device omap_gpio_device = {
 static void omap_gpio_save_context(struct gpio_bank *bank);
 static void omap_gpio_restore_context(struct gpio_bank *bank);
 
-static int workaround_enabled;
-
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
-	int i, c = 0;
+	int i;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
@@ -1922,7 +1922,7 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
 		}
 
-		c++;
+		bank->off_mode_wkup_wa_enabled = true;
 
 save_gpio_ctx:
 		pdev = to_platform_device(bank->dev);
@@ -1930,11 +1930,6 @@ save_gpio_ctx:
 				omap_device_get_context_loss_count(pdev);
 		omap_gpio_save_context(bank);
 	}
-	if (!c) {
-		workaround_enabled = 0;
-		return;
-	}
-	workaround_enabled = 1;
 }
 
 void omap2_gpio_resume_after_idle(void)
@@ -1964,7 +1959,7 @@ void omap2_gpio_resume_after_idle(void)
 		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
 			continue;
 
-		if (!workaround_enabled)
+		if (!bank->off_mode_wkup_wa_enabled)
 			goto restore_gpio_ctx;
 
 		if (!(bank->enabled_non_wakeup_gpios))
@@ -2042,6 +2037,7 @@ void omap2_gpio_resume_after_idle(void)
 		}
 
 restore_gpio_ctx:
+		bank->off_mode_wkup_wa_enabled = false;
 		omap_gpio_restore_context(bank);
 	}
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 6/7] OMAP: GPIO: Cleanup prepare_for_idle/resume
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Use a function named gpio_bank_handle_idle() in
omap_gpio_prepare_for_idle() to do the following:

* debounce clock disable
* if the next powerdomain state for the bank is off-mode:
  - remove triggering for all non-wakeup GPIOs (this is handled by
    a new function named omap_gpio_idle_handle_errata_i468())
  - save context

Also handle omap_gpio_resume_after_idle() in a
similar way, using a function gpio_bank_handle_resume().

This would be helpful while modifying OMAP GPIO driver to use
PM runtime framework.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  350 ++++++++++++++++++++++++---------------------
 1 files changed, 187 insertions(+), 163 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 5933c98..7660c06 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -1747,6 +1747,187 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
+static int is_pwrdm_nxt_state_off;
+
+static inline void omap_gpio_idle_handle_errata_i468(struct gpio_bank *bank)
+{
+	u32 l1 = 0, l2 = 0;
+
+	/*
+	 * If going to OFF, remove triggering for all
+	 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
+	 * generated.  See OMAP2420 Errata item 1.101.
+	 */
+	if (!(bank->enabled_non_wakeup_gpios))
+		return;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		bank->saved_datain = __raw_readl(bank->base +
+						OMAP24XX_GPIO_DATAIN);
+
+		l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		bank->saved_datain = __raw_readl(bank->base +
+						OMAP4_GPIO_DATAIN);
+
+		l1 = __raw_readl(bank->base + OMAP4_GPIO_FALLINGDETECT);
+		l2 = __raw_readl(bank->base + OMAP4_GPIO_RISINGDETECT);
+	}
+
+	bank->saved_fallingdetect = l1;
+	bank->saved_risingdetect = l2;
+	l1 &= ~bank->enabled_non_wakeup_gpios;
+	l2 &= ~bank->enabled_non_wakeup_gpios;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
+	}
+
+	bank->off_mode_wkup_wa_enabled = true;
+}
+
+static inline void omap_gpio_resume_handle_errata_i468(struct gpio_bank *bank)
+{
+	u32 l = 0, gen, gen0, gen1;
+
+	if (!bank->off_mode_wkup_wa_enabled)
+		return;
+
+	bank->off_mode_wkup_wa_enabled = false;
+
+	if (!(bank->enabled_non_wakeup_gpios))
+		return;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(bank->saved_fallingdetect,
+				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(bank->saved_risingdetect,
+				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
+
+		l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(bank->saved_fallingdetect,
+				 bank->base + OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(bank->saved_risingdetect,
+				 bank->base + OMAP4_GPIO_RISINGDETECT);
+
+		l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
+	}
+
+	/*
+	 * Check if any of the non-wakeup interrupt GPIOs have changed
+	 * state.  If so, generate an IRQ by software.  This is
+	 * horribly racy, but it's the best we can do to work around
+	 * this silicon bug.
+	 */
+	l ^= bank->saved_datain;
+	l &= bank->enabled_non_wakeup_gpios;
+
+	/*
+	 * No need to generate IRQs for the rising edge for gpio IRQs
+	 * configured with falling edge only; and vice versa.
+	 */
+	gen0 = l & bank->saved_fallingdetect;
+	gen0 &= bank->saved_datain;
+	gen1 = l & bank->saved_risingdetect;
+	gen1 &= ~(bank->saved_datain);
+
+	/* FIXME: Consider GPIO IRQs with level detections properly! */
+	gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect));
+
+	/* Consider all GPIO IRQs needed to be updated */
+	gen |= gen0 | gen1;
+
+	if (gen) {
+		u32 old0, old1;
+
+		if (bank->method == METHOD_GPIO_24XX) {
+			old0 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			old1 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			old0 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			old1 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | l, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | l, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(old0, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(old1, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+		}
+	}
+}
+
+static int gpio_bank_handle_idle(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	int j;
+
+	/* If the gpio bank is not used, do nothing */
+	if (!bank->mod_usage || !bank->looses_context)
+		return 0;
+
+	for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+		clk_disable(bank->dbck);
+
+	/* Save the context lost count */
+	bank->ctx_lost_cnt_before =
+				omap_device_get_context_loss_count(pdev);
+
+	if (is_pwrdm_nxt_state_off) {
+		omap_gpio_idle_handle_errata_i468(bank);
+		omap_gpio_save_context(bank);
+	}
+
+	return 0;
+}
+
+static int gpio_bank_handle_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	u32 ctx_lost_cnt_after;
+	int j;
+
+	/* If the gpio bank is not used, do nothing */
+	if (!bank->mod_usage || !bank->looses_context)
+		return 0;
+
+	for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+		clk_enable(bank->dbck);
+
+	pdev = to_platform_device(bank->dev);
+	ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
+
+	if (ctx_lost_cnt_after != bank->ctx_lost_cnt_before) {
+		omap_gpio_resume_handle_errata_i468(bank);
+		omap_gpio_restore_context(bank);
+	}
+
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
 static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
 {
@@ -1864,183 +2045,26 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i;
 
+	is_pwrdm_nxt_state_off = off_mode;
+
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		struct platform_device *pdev;
-		u32 l1 = 0, l2 = 0;
-		int j;
-
-		/* If the gpio bank is not used, do nothing */
-		if (!bank->mod_usage)
-			continue;
-
-		if (!bank->looses_context)
-			continue;
-
-		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-			clk_disable(bank->dbck);
-
-		if (!off_mode)
-			continue;
-
-		/*
-		 * If going to OFF, remove triggering for all
-		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
-		 * generated.  See OMAP2420 Errata item 1.101.
-		 */
-		if (!(bank->enabled_non_wakeup_gpios))
-			goto save_gpio_ctx;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			bank->saved_datain = __raw_readl(bank->base +
-					OMAP24XX_GPIO_DATAIN);
-			l1 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_FALLINGDETECT);
-			l2 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_RISINGDETECT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			bank->saved_datain = __raw_readl(bank->base +
-						OMAP4_GPIO_DATAIN);
-			l1 = __raw_readl(bank->base +
-						OMAP4_GPIO_FALLINGDETECT);
-			l2 = __raw_readl(bank->base +
-						OMAP4_GPIO_RISINGDETECT);
-		}
-
-		bank->saved_fallingdetect = l1;
-		bank->saved_risingdetect = l2;
-		l1 &= ~bank->enabled_non_wakeup_gpios;
-		l2 &= ~bank->enabled_non_wakeup_gpios;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(l1, bank->base +
-					OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(l2, bank->base +
-					OMAP24XX_GPIO_RISINGDETECT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
-		}
-
-		bank->off_mode_wkup_wa_enabled = true;
 
-save_gpio_ctx:
-		pdev = to_platform_device(bank->dev);
-		bank->ctx_lost_cnt_before =
-				omap_device_get_context_loss_count(pdev);
-		omap_gpio_save_context(bank);
+		gpio_bank_handle_idle(bank->dev);
 	}
 }
 
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
-	u32 ctx_lost_cnt_after;
+
+	is_pwrdm_nxt_state_off = 0;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		struct platform_device *pdev;
-		u32 l = 0, gen, gen0, gen1;
-		int j;
-
-		/* If the gpio bank is not used, do nothing */
-		if (!bank->mod_usage)
-			continue;
-
-		if (!bank->looses_context)
-			continue;
-
-		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-			clk_enable(bank->dbck);
-
-		pdev = to_platform_device(bank->dev);
-		ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
-
-		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
-			continue;
-
-		if (!bank->off_mode_wkup_wa_enabled)
-			goto restore_gpio_ctx;
-
-		if (!(bank->enabled_non_wakeup_gpios))
-			goto restore_gpio_ctx;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(bank->saved_fallingdetect,
-				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(bank->saved_risingdetect,
-				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
-			l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(bank->saved_fallingdetect,
-				 bank->base + OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(bank->saved_risingdetect,
-				 bank->base + OMAP4_GPIO_RISINGDETECT);
-			l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
-		}
-
-		/*
-		 * Check if any of the non-wakeup interrupt GPIOs have changed
-		 * state.  If so, generate an IRQ by software.  This is
-		 * horribly racy, but it's the best we can do to work around
-		 * this silicon bug.
-		 */
-		l ^= bank->saved_datain;
-		l &= bank->enabled_non_wakeup_gpios;
 
-		/*
-		 * No need to generate IRQs for the rising edge for gpio IRQs
-		 * configured with falling edge only; and vice versa.
-		 */
-		gen0 = l & bank->saved_fallingdetect;
-		gen0 &= bank->saved_datain;
-
-		gen1 = l & bank->saved_risingdetect;
-		gen1 &= ~(bank->saved_datain);
-
-		/* FIXME: Consider GPIO IRQs with level detections properly! */
-		gen = l & (~(bank->saved_fallingdetect) &
-				~(bank->saved_risingdetect));
-		/* Consider all GPIO IRQs needed to be updated */
-		gen |= gen0 | gen1;
-
-		if (gen) {
-			u32 old0, old1;
-
-			if (bank->method == METHOD_GPIO_24XX) {
-				old0 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				old1 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-				__raw_writel(old0 | gen, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				__raw_writel(old1 | gen, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-				__raw_writel(old0, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				__raw_writel(old1, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-			} else if (bank->method == METHOD_GPIO_44XX) {
-				old0 = __raw_readl(bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				old1 = __raw_readl(bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-				__raw_writel(old0 | l, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				__raw_writel(old1 | l, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-				__raw_writel(old0, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				__raw_writel(old1, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-			}
-		}
-
-restore_gpio_ctx:
-		bank->off_mode_wkup_wa_enabled = false;
-		omap_gpio_restore_context(bank);
+		gpio_bank_handle_resume(bank->dev);
 	}
-
 }
 
 void omap_gpio_save_context(struct gpio_bank *bank)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 6/7] OMAP: GPIO: Cleanup prepare_for_idle/resume
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Use a function named gpio_bank_handle_idle() in
omap_gpio_prepare_for_idle() to do the following:

* debounce clock disable
* if the next powerdomain state for the bank is off-mode:
  - remove triggering for all non-wakeup GPIOs (this is handled by
    a new function named omap_gpio_idle_handle_errata_i468())
  - save context

Also handle omap_gpio_resume_after_idle() in a
similar way, using a function gpio_bank_handle_resume().

This would be helpful while modifying OMAP GPIO driver to use
PM runtime framework.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  350 ++++++++++++++++++++++++---------------------
 1 files changed, 187 insertions(+), 163 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 5933c98..7660c06 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -1747,6 +1747,187 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
+static int is_pwrdm_nxt_state_off;
+
+static inline void omap_gpio_idle_handle_errata_i468(struct gpio_bank *bank)
+{
+	u32 l1 = 0, l2 = 0;
+
+	/*
+	 * If going to OFF, remove triggering for all
+	 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
+	 * generated.  See OMAP2420 Errata item 1.101.
+	 */
+	if (!(bank->enabled_non_wakeup_gpios))
+		return;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		bank->saved_datain = __raw_readl(bank->base +
+						OMAP24XX_GPIO_DATAIN);
+
+		l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		bank->saved_datain = __raw_readl(bank->base +
+						OMAP4_GPIO_DATAIN);
+
+		l1 = __raw_readl(bank->base + OMAP4_GPIO_FALLINGDETECT);
+		l2 = __raw_readl(bank->base + OMAP4_GPIO_RISINGDETECT);
+	}
+
+	bank->saved_fallingdetect = l1;
+	bank->saved_risingdetect = l2;
+	l1 &= ~bank->enabled_non_wakeup_gpios;
+	l2 &= ~bank->enabled_non_wakeup_gpios;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
+	}
+
+	bank->off_mode_wkup_wa_enabled = true;
+}
+
+static inline void omap_gpio_resume_handle_errata_i468(struct gpio_bank *bank)
+{
+	u32 l = 0, gen, gen0, gen1;
+
+	if (!bank->off_mode_wkup_wa_enabled)
+		return;
+
+	bank->off_mode_wkup_wa_enabled = false;
+
+	if (!(bank->enabled_non_wakeup_gpios))
+		return;
+
+	if (bank->method == METHOD_GPIO_24XX) {
+		__raw_writel(bank->saved_fallingdetect,
+				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+		__raw_writel(bank->saved_risingdetect,
+				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
+
+		l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+	} else if (bank->method == METHOD_GPIO_44XX) {
+		__raw_writel(bank->saved_fallingdetect,
+				 bank->base + OMAP4_GPIO_FALLINGDETECT);
+		__raw_writel(bank->saved_risingdetect,
+				 bank->base + OMAP4_GPIO_RISINGDETECT);
+
+		l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
+	}
+
+	/*
+	 * Check if any of the non-wakeup interrupt GPIOs have changed
+	 * state.  If so, generate an IRQ by software.  This is
+	 * horribly racy, but it's the best we can do to work around
+	 * this silicon bug.
+	 */
+	l ^= bank->saved_datain;
+	l &= bank->enabled_non_wakeup_gpios;
+
+	/*
+	 * No need to generate IRQs for the rising edge for gpio IRQs
+	 * configured with falling edge only; and vice versa.
+	 */
+	gen0 = l & bank->saved_fallingdetect;
+	gen0 &= bank->saved_datain;
+	gen1 = l & bank->saved_risingdetect;
+	gen1 &= ~(bank->saved_datain);
+
+	/* FIXME: Consider GPIO IRQs with level detections properly! */
+	gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect));
+
+	/* Consider all GPIO IRQs needed to be updated */
+	gen |= gen0 | gen1;
+
+	if (gen) {
+		u32 old0, old1;
+
+		if (bank->method == METHOD_GPIO_24XX) {
+			old0 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			old1 = __raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | gen, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+			__raw_writel(old0, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0);
+			__raw_writel(old1, bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+		} else if (bank->method == METHOD_GPIO_44XX) {
+			old0 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			old1 = __raw_readl(bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(old0 | l, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(old1 | l, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+			__raw_writel(old0, bank->base +
+					OMAP4_GPIO_LEVELDETECT0);
+			__raw_writel(old1, bank->base +
+					OMAP4_GPIO_LEVELDETECT1);
+		}
+	}
+}
+
+static int gpio_bank_handle_idle(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	int j;
+
+	/* If the gpio bank is not used, do nothing */
+	if (!bank->mod_usage || !bank->looses_context)
+		return 0;
+
+	for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+		clk_disable(bank->dbck);
+
+	/* Save the context lost count */
+	bank->ctx_lost_cnt_before =
+				omap_device_get_context_loss_count(pdev);
+
+	if (is_pwrdm_nxt_state_off) {
+		omap_gpio_idle_handle_errata_i468(bank);
+		omap_gpio_save_context(bank);
+	}
+
+	return 0;
+}
+
+static int gpio_bank_handle_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	u32 ctx_lost_cnt_after;
+	int j;
+
+	/* If the gpio bank is not used, do nothing */
+	if (!bank->mod_usage || !bank->looses_context)
+		return 0;
+
+	for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+		clk_enable(bank->dbck);
+
+	pdev = to_platform_device(bank->dev);
+	ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
+
+	if (ctx_lost_cnt_after != bank->ctx_lost_cnt_before) {
+		omap_gpio_resume_handle_errata_i468(bank);
+		omap_gpio_restore_context(bank);
+	}
+
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
 static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
 {
@@ -1864,183 +2045,26 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i;
 
+	is_pwrdm_nxt_state_off = off_mode;
+
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		struct platform_device *pdev;
-		u32 l1 = 0, l2 = 0;
-		int j;
-
-		/* If the gpio bank is not used, do nothing */
-		if (!bank->mod_usage)
-			continue;
-
-		if (!bank->looses_context)
-			continue;
-
-		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-			clk_disable(bank->dbck);
-
-		if (!off_mode)
-			continue;
-
-		/*
-		 * If going to OFF, remove triggering for all
-		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
-		 * generated.  See OMAP2420 Errata item 1.101.
-		 */
-		if (!(bank->enabled_non_wakeup_gpios))
-			goto save_gpio_ctx;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			bank->saved_datain = __raw_readl(bank->base +
-					OMAP24XX_GPIO_DATAIN);
-			l1 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_FALLINGDETECT);
-			l2 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_RISINGDETECT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			bank->saved_datain = __raw_readl(bank->base +
-						OMAP4_GPIO_DATAIN);
-			l1 = __raw_readl(bank->base +
-						OMAP4_GPIO_FALLINGDETECT);
-			l2 = __raw_readl(bank->base +
-						OMAP4_GPIO_RISINGDETECT);
-		}
-
-		bank->saved_fallingdetect = l1;
-		bank->saved_risingdetect = l2;
-		l1 &= ~bank->enabled_non_wakeup_gpios;
-		l2 &= ~bank->enabled_non_wakeup_gpios;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(l1, bank->base +
-					OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(l2, bank->base +
-					OMAP24XX_GPIO_RISINGDETECT);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
-		}
-
-		bank->off_mode_wkup_wa_enabled = true;
 
-save_gpio_ctx:
-		pdev = to_platform_device(bank->dev);
-		bank->ctx_lost_cnt_before =
-				omap_device_get_context_loss_count(pdev);
-		omap_gpio_save_context(bank);
+		gpio_bank_handle_idle(bank->dev);
 	}
 }
 
 void omap2_gpio_resume_after_idle(void)
 {
 	int i;
-	u32 ctx_lost_cnt_after;
+
+	is_pwrdm_nxt_state_off = 0;
 
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
-		struct platform_device *pdev;
-		u32 l = 0, gen, gen0, gen1;
-		int j;
-
-		/* If the gpio bank is not used, do nothing */
-		if (!bank->mod_usage)
-			continue;
-
-		if (!bank->looses_context)
-			continue;
-
-		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-			clk_enable(bank->dbck);
-
-		pdev = to_platform_device(bank->dev);
-		ctx_lost_cnt_after = omap_device_get_context_loss_count(pdev);
-
-		if (ctx_lost_cnt_after == bank->ctx_lost_cnt_before)
-			continue;
-
-		if (!bank->off_mode_wkup_wa_enabled)
-			goto restore_gpio_ctx;
-
-		if (!(bank->enabled_non_wakeup_gpios))
-			goto restore_gpio_ctx;
-
-		if (bank->method == METHOD_GPIO_24XX) {
-			__raw_writel(bank->saved_fallingdetect,
-				 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-			__raw_writel(bank->saved_risingdetect,
-				 bank->base + OMAP24XX_GPIO_RISINGDETECT);
-			l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
-		} else if (bank->method == METHOD_GPIO_44XX) {
-			__raw_writel(bank->saved_fallingdetect,
-				 bank->base + OMAP4_GPIO_FALLINGDETECT);
-			__raw_writel(bank->saved_risingdetect,
-				 bank->base + OMAP4_GPIO_RISINGDETECT);
-			l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
-		}
-
-		/*
-		 * Check if any of the non-wakeup interrupt GPIOs have changed
-		 * state.  If so, generate an IRQ by software.  This is
-		 * horribly racy, but it's the best we can do to work around
-		 * this silicon bug.
-		 */
-		l ^= bank->saved_datain;
-		l &= bank->enabled_non_wakeup_gpios;
 
-		/*
-		 * No need to generate IRQs for the rising edge for gpio IRQs
-		 * configured with falling edge only; and vice versa.
-		 */
-		gen0 = l & bank->saved_fallingdetect;
-		gen0 &= bank->saved_datain;
-
-		gen1 = l & bank->saved_risingdetect;
-		gen1 &= ~(bank->saved_datain);
-
-		/* FIXME: Consider GPIO IRQs with level detections properly! */
-		gen = l & (~(bank->saved_fallingdetect) &
-				~(bank->saved_risingdetect));
-		/* Consider all GPIO IRQs needed to be updated */
-		gen |= gen0 | gen1;
-
-		if (gen) {
-			u32 old0, old1;
-
-			if (bank->method == METHOD_GPIO_24XX) {
-				old0 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				old1 = __raw_readl(bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-				__raw_writel(old0 | gen, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				__raw_writel(old1 | gen, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-				__raw_writel(old0, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT0);
-				__raw_writel(old1, bank->base +
-					OMAP24XX_GPIO_LEVELDETECT1);
-			} else if (bank->method == METHOD_GPIO_44XX) {
-				old0 = __raw_readl(bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				old1 = __raw_readl(bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-				__raw_writel(old0 | l, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				__raw_writel(old1 | l, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-				__raw_writel(old0, bank->base +
-						OMAP4_GPIO_LEVELDETECT0);
-				__raw_writel(old1, bank->base +
-						OMAP4_GPIO_LEVELDETECT1);
-			}
-		}
-
-restore_gpio_ctx:
-		bank->off_mode_wkup_wa_enabled = false;
-		omap_gpio_restore_context(bank);
+		gpio_bank_handle_resume(bank->dev);
 	}
-
 }
 
 void omap_gpio_save_context(struct gpio_bank *bank)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 7/7] OMAP: GPIO: use PM runtime framework
       [not found] <no>
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
                     ` (37 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-omap, linux-arm-kernel; +Cc: tony, khilman, paul, Charulatha V

From: Charulatha V <charu@ti.com>

Call runtime pm APIs pm_runtime_get_sync() and pm_runtime_put_sync()
for enabling/disabling the clocks, sysconfig settings and remove usage
of clock FW APIs.
Note: OMAP16xx & OMAP2 has interface and functional clocks whereas
OMAP3 & 4 has interface and debounce clocks.

GPIO driver is modified to use dev_pm_ops instead of sysdev_class.
With this approach, omap_gpio_suspend() & omap_gpio_resume()
are not part of sys_dev_class.

Usage of PM runtime get/put APIs in GPIO driver is as given below:
pm_runtime_get_sync():
* in the probe before accessing the GPIO registers
* at the beginning of omap_gpio_request()
	-only when one of the gpios is requested on a bank, in which,
	 no other gpio is being used (when mod_usage becomes non-zero).
	 This is because omap_gpio_request() is called for all the GPIOs in
	 a bank.
* at the beginning of omap_gpio_resume_after_idle()
* at the beginning of gpio_irq_handler()

pm_runtime_put_sync():
* in the probe after completing GPIO register access
* at the end of omap_gpio_free()
	- only when the last used gpio in the gpio bank is
	  freed (when mod_usage becomes 0).
* at the end of omap_gpio_prepare_for_idle()
* at the end of gpio_irq_handler()

In omap_gpio_suspend/resume() it is not required to call PM runtime APIs
because omap_gpio_prepare_for_idle()/omap_gpio_resume_after_idle() would
be handling them.

OMAP GPIO Request/ Free:
*During a gpio_request when mod_usage becomes non-zero, the bank
 registers are configured with init time configurations inorder to
 make sure that the GPIO init time configurations are not lost if
 the context was earlier lost when the GPIO bank was not in use.
*omap_gpio_request()/free() functions are called for each GPIO pin in a
 given bank whereas PM runtime get_sync/put_sync needs to be called only
 once per bank whenever it is required to enable/disable clocks. Hence it
 is required to use bank->mod_usage flag in omap_gpio_request()/free()
 functions.

TODO:
*Cleanup GPIO driver to avoid usage of gpio_bank_count &
 cpu_is_* checks. This would be sent very soon on top of
 this patch series.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  298 +++++++++++++++++++++++---------------------
 1 files changed, 156 insertions(+), 142 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 7660c06..88ef9d7 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -179,6 +179,8 @@ struct gpio_bank {
 	bool off_mode_wkup_wa_enabled;
 };
 
+static void omap_gpio_mod_init(struct gpio_bank *bank, int id);
+
 /*
  * TODO: Cleanup gpio_bank usage as it is having information
  * related to all instances of the device
@@ -1037,8 +1039,28 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
 	unsigned long flags;
 
+	/*
+	 * If this is the first gpio_request for the bank,
+	 * enable the bank module
+	 */
+	if (!bank->mod_usage) {
+		struct platform_device *pdev = to_platform_device(bank->dev);
+
+		if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev))) {
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_get_sync failed\n",
+					__func__, pdev->id);
+			return -EINVAL;
+		}
+
+		/* Initialize the gpio bank registers to init time value */
+		omap_gpio_mod_init(bank, pdev->id);
+	}
+
 	spin_lock_irqsave(&bank->lock, flags);
 
+	bank->mod_usage |= 1 << offset;
+
 	/* Set trigger to none. You need to enable the desired trigger with
 	 * request_irq() or set_irq_type().
 	 */
@@ -1053,22 +1075,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 		__raw_writel(__raw_readl(reg) | (1 << offset), reg);
 	}
 #endif
-	if (!cpu_class_is_omap1()) {
-		if (!bank->mod_usage) {
-			void __iomem *reg = bank->base;
-			u32 ctrl;
-
-			if (cpu_is_omap24xx() || cpu_is_omap34xx())
-				reg += OMAP24XX_GPIO_CTRL;
-			else if (cpu_is_omap44xx())
-				reg += OMAP4_GPIO_CTRL;
-			ctrl = __raw_readl(reg);
-			/* Module is enabled, clocks are not gated */
-			ctrl &= 0xFFFFFFFE;
-			__raw_writel(ctrl, reg);
-		}
-		bank->mod_usage |= 1 << offset;
-	}
+
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	return 0;
@@ -1101,24 +1108,40 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
 		__raw_writel(1 << offset, reg);
 	}
 #endif
-	if (!cpu_class_is_omap1()) {
-		bank->mod_usage &= ~(1 << offset);
-		if (!bank->mod_usage) {
-			void __iomem *reg = bank->base;
-			u32 ctrl;
-
-			if (cpu_is_omap24xx() || cpu_is_omap34xx())
-				reg += OMAP24XX_GPIO_CTRL;
-			else if (cpu_is_omap44xx())
-				reg += OMAP4_GPIO_CTRL;
-			ctrl = __raw_readl(reg);
-			/* Module is disabled, clocks are gated */
-			ctrl |= 1;
-			__raw_writel(ctrl, reg);
-		}
+	bank->mod_usage &= ~(1 << offset);
+	if (!bank->mod_usage) {
+		void __iomem *reg = bank->base;
+		u32 ctrl;
+
+		if (bank->method == METHOD_GPIO_24XX)
+			reg += OMAP24XX_GPIO_CTRL;
+		else if (bank->method == METHOD_GPIO_44XX)
+			reg += OMAP4_GPIO_CTRL;
+		else
+			goto reset_gpio;
+
+		ctrl = __raw_readl(reg);
+		/* Module is disabled, clocks are gated */
+		ctrl |= 1;
+		__raw_writel(ctrl, reg);
 	}
+reset_gpio:
 	_reset_gpio(bank, bank->chip.base + offset);
 	spin_unlock_irqrestore(&bank->lock, flags);
+
+	/*
+	 * If this is the last gpio to be freed in the bank,
+	 * disable the bank module
+	 */
+	if (!bank->mod_usage) {
+		if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0)) {
+			struct platform_device *pdev =
+					to_platform_device(bank->dev);
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_put_sync failed\n",
+					__func__, pdev->id);
+		}
+	}
 }
 
 /*
@@ -1142,6 +1165,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	bank = irq_get_handler_data(irq);
+
+	pm_runtime_get_sync(bank->dev);
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (bank->method == METHOD_MPUIO)
 		isr_reg = bank->base +
@@ -1233,6 +1259,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 exit:
 	if (!unmasked)
 		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+
+	pm_runtime_put_sync(bank->dev);
 }
 
 static void gpio_irq_shutdown(struct irq_data *d)
@@ -1735,12 +1763,25 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(bank->dev);
-	pm_runtime_get_sync(bank->dev);
+	pm_runtime_irq_safe(bank->dev);
+
+	if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev) < 0)) {
+		dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync "
+				"failed\n", __func__, id);
+		iounmap(bank->base);
+		return -EINVAL;
+	}
 
-	omap_gpio_mod_init(bank, id);
 	omap_gpio_chip_init(bank);
 	omap_gpio_show_rev(bank);
 
+	if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0)) {
+		dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync "
+				"failed\n", __func__, id);
+		iounmap(bank->base);
+		return -EINVAL;
+	}
+
 	if (!gpio_init_done)
 		gpio_init_done = 1;
 
@@ -1748,6 +1789,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+static void omap_gpio_save_context(struct gpio_bank *bank);
+static void omap_gpio_restore_context(struct gpio_bank *bank);
+
 static int is_pwrdm_nxt_state_off;
 
 static inline void omap_gpio_idle_handle_errata_i468(struct gpio_bank *bank)
@@ -1876,9 +1920,11 @@ static inline void omap_gpio_resume_handle_errata_i468(struct gpio_bank *bank)
 		}
 	}
 }
+#endif
 
-static int gpio_bank_handle_idle(struct device *dev)
+static int omap_gpio_pm_runtime_suspend(struct device *dev)
 {
+#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank *bank = &gpio_bank[pdev->id];
 	int j;
@@ -1898,12 +1944,14 @@ static int gpio_bank_handle_idle(struct device *dev)
 		omap_gpio_idle_handle_errata_i468(bank);
 		omap_gpio_save_context(bank);
 	}
+#endif
 
 	return 0;
 }
 
-static int gpio_bank_handle_resume(struct device *dev)
+static int omap_gpio_pm_runtime_resume(struct device *dev)
 {
+#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank *bank = &gpio_bank[pdev->id];
 	u32 ctx_lost_cnt_after;
@@ -1923,124 +1971,89 @@ static int gpio_bank_handle_resume(struct device *dev)
 		omap_gpio_resume_handle_errata_i468(bank);
 		omap_gpio_restore_context(bank);
 	}
+#endif
 
 	return 0;
 }
-#endif
 
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+static int omap_gpio_suspend(struct device *dev)
 {
-	int i;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	void __iomem *wake_status;
+	void __iomem *wake_clear;
+	void __iomem *wake_set;
 
-	if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+	if (!bank->mod_usage)
 		return 0;
 
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-		void __iomem *wake_status;
-		void __iomem *wake_clear;
-		void __iomem *wake_set;
-		unsigned long flags;
+	switch (bank->method) {
+	case METHOD_GPIO_1610:
+		wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
+		wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+		wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+		break;
 
-		switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-		case METHOD_GPIO_1610:
-			wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
-			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-			break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-		case METHOD_GPIO_24XX:
-			wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
-			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-			break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-		case METHOD_GPIO_44XX:
-			wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			break;
-#endif
-		default:
-			continue;
-		}
+	case METHOD_GPIO_24XX:
+		wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
+		wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+		wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+		break;
 
-		spin_lock_irqsave(&bank->lock, flags);
-		bank->saved_wakeup = __raw_readl(wake_status);
-		__raw_writel(0xffffffff, wake_clear);
-		__raw_writel(bank->suspend_wakeup, wake_set);
-		spin_unlock_irqrestore(&bank->lock, flags);
+	case METHOD_GPIO_44XX:
+		wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		break;
+
+	default:
+		return 0;
 	}
 
+	bank->saved_wakeup = __raw_readl(wake_status);
+	__raw_writel(0xffffffff, wake_clear);
+	__raw_writel(bank->suspend_wakeup, wake_set);
+
 	return 0;
 }
 
-static int omap_gpio_resume(struct sys_device *dev)
+static int omap_gpio_resume(struct device *dev)
 {
-	int i;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	void __iomem *wake_clear;
+	void __iomem *wake_set;
 
-	if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+	if (!bank->mod_usage)
 		return 0;
 
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-		void __iomem *wake_clear;
-		void __iomem *wake_set;
-		unsigned long flags;
+	switch (bank->method) {
+	case METHOD_GPIO_1610:
+		wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+		wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+		break;
 
-		switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-		case METHOD_GPIO_1610:
-			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-			break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-		case METHOD_GPIO_24XX:
-			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-			break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-		case METHOD_GPIO_44XX:
-			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			break;
-#endif
-		default:
-			continue;
-		}
+	case METHOD_GPIO_24XX:
+		wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+		wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+		break;
 
-		spin_lock_irqsave(&bank->lock, flags);
-		__raw_writel(0xffffffff, wake_clear);
-		__raw_writel(bank->saved_wakeup, wake_set);
-		spin_unlock_irqrestore(&bank->lock, flags);
+	case METHOD_GPIO_44XX:
+		wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		break;
+
+	default:
+		return 0;
 	}
 
+	__raw_writel(0xffffffff, wake_clear);
+	__raw_writel(bank->saved_wakeup, wake_set);
+
 	return 0;
 }
 
-static struct sysdev_class omap_gpio_sysclass = {
-	.name		= "gpio",
-	.suspend	= omap_gpio_suspend,
-	.resume		= omap_gpio_resume,
-};
-
-static struct sys_device omap_gpio_device = {
-	.id		= 0,
-	.cls		= &omap_gpio_sysclass,
-};
-
-#endif
-
 #ifdef CONFIG_ARCH_OMAP2PLUS
-static void omap_gpio_save_context(struct gpio_bank *bank);
-static void omap_gpio_restore_context(struct gpio_bank *bank);
-
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i;
@@ -2050,7 +2063,10 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
-		gpio_bank_handle_idle(bank->dev);
+		if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0))
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_put_sync failed\n",
+					__func__, i);
 	}
 }
 
@@ -2063,7 +2079,10 @@ void omap2_gpio_resume_after_idle(void)
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
-		gpio_bank_handle_resume(bank->dev);
+		if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev) < 0))
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_get_sync failed\n",
+					__func__, i);
 	}
 }
 
@@ -2162,10 +2181,18 @@ void omap_gpio_restore_context(struct gpio_bank *bank)
 }
 #endif
 
+static const struct dev_pm_ops gpio_pm_ops = {
+	.runtime_suspend	= omap_gpio_pm_runtime_suspend,
+	.runtime_resume		= omap_gpio_pm_runtime_resume,
+	.suspend		= omap_gpio_suspend,
+	.resume			= omap_gpio_resume,
+};
+
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
 	.driver		= {
 		.name	= "omap_gpio",
+		.pm	= &gpio_pm_ops,
 	},
 };
 
@@ -2182,21 +2209,8 @@ postcore_initcall(omap_gpio_drv_reg);
 
 static int __init omap_gpio_sysinit(void)
 {
-	int ret = 0;
-
 	mpuio_init();
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-		if (ret == 0) {
-			ret = sysdev_class_register(&omap_gpio_sysclass);
-			if (ret == 0)
-				ret = sysdev_register(&omap_gpio_device);
-		}
-	}
-#endif
-
-	return ret;
+	return 0;
 }
 
 arch_initcall(omap_gpio_sysinit);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 7/7] OMAP: GPIO: use PM runtime framework
@ 2011-04-18 15:06   ` Varadarajan, Charulatha
  0 siblings, 0 replies; 206+ messages in thread
From: Varadarajan, Charulatha @ 2011-04-18 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

From: Charulatha V <charu@ti.com>

Call runtime pm APIs pm_runtime_get_sync() and pm_runtime_put_sync()
for enabling/disabling the clocks, sysconfig settings and remove usage
of clock FW APIs.
Note: OMAP16xx & OMAP2 has interface and functional clocks whereas
OMAP3 & 4 has interface and debounce clocks.

GPIO driver is modified to use dev_pm_ops instead of sysdev_class.
With this approach, omap_gpio_suspend() & omap_gpio_resume()
are not part of sys_dev_class.

Usage of PM runtime get/put APIs in GPIO driver is as given below:
pm_runtime_get_sync():
* in the probe before accessing the GPIO registers
* at the beginning of omap_gpio_request()
	-only when one of the gpios is requested on a bank, in which,
	 no other gpio is being used (when mod_usage becomes non-zero).
	 This is because omap_gpio_request() is called for all the GPIOs in
	 a bank.
* at the beginning of omap_gpio_resume_after_idle()
* at the beginning of gpio_irq_handler()

pm_runtime_put_sync():
* in the probe after completing GPIO register access
* at the end of omap_gpio_free()
	- only when the last used gpio in the gpio bank is
	  freed (when mod_usage becomes 0).
* at the end of omap_gpio_prepare_for_idle()
* at the end of gpio_irq_handler()

In omap_gpio_suspend/resume() it is not required to call PM runtime APIs
because omap_gpio_prepare_for_idle()/omap_gpio_resume_after_idle() would
be handling them.

OMAP GPIO Request/ Free:
*During a gpio_request when mod_usage becomes non-zero, the bank
 registers are configured with init time configurations inorder to
 make sure that the GPIO init time configurations are not lost if
 the context was earlier lost when the GPIO bank was not in use.
*omap_gpio_request()/free() functions are called for each GPIO pin in a
 given bank whereas PM runtime get_sync/put_sync needs to be called only
 once per bank whenever it is required to enable/disable clocks. Hence it
 is required to use bank->mod_usage flag in omap_gpio_request()/free()
 functions.

TODO:
*Cleanup GPIO driver to avoid usage of gpio_bank_count &
 cpu_is_* checks. This would be sent very soon on top of
 this patch series.

Signed-off-by: Charulatha V <charu@ti.com>
---
 arch/arm/plat-omap/gpio.c |  298 +++++++++++++++++++++++---------------------
 1 files changed, 156 insertions(+), 142 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 7660c06..88ef9d7 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -179,6 +179,8 @@ struct gpio_bank {
 	bool off_mode_wkup_wa_enabled;
 };
 
+static void omap_gpio_mod_init(struct gpio_bank *bank, int id);
+
 /*
  * TODO: Cleanup gpio_bank usage as it is having information
  * related to all instances of the device
@@ -1037,8 +1039,28 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
 	unsigned long flags;
 
+	/*
+	 * If this is the first gpio_request for the bank,
+	 * enable the bank module
+	 */
+	if (!bank->mod_usage) {
+		struct platform_device *pdev = to_platform_device(bank->dev);
+
+		if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev))) {
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_get_sync failed\n",
+					__func__, pdev->id);
+			return -EINVAL;
+		}
+
+		/* Initialize the gpio bank registers to init time value */
+		omap_gpio_mod_init(bank, pdev->id);
+	}
+
 	spin_lock_irqsave(&bank->lock, flags);
 
+	bank->mod_usage |= 1 << offset;
+
 	/* Set trigger to none. You need to enable the desired trigger with
 	 * request_irq() or set_irq_type().
 	 */
@@ -1053,22 +1075,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 		__raw_writel(__raw_readl(reg) | (1 << offset), reg);
 	}
 #endif
-	if (!cpu_class_is_omap1()) {
-		if (!bank->mod_usage) {
-			void __iomem *reg = bank->base;
-			u32 ctrl;
-
-			if (cpu_is_omap24xx() || cpu_is_omap34xx())
-				reg += OMAP24XX_GPIO_CTRL;
-			else if (cpu_is_omap44xx())
-				reg += OMAP4_GPIO_CTRL;
-			ctrl = __raw_readl(reg);
-			/* Module is enabled, clocks are not gated */
-			ctrl &= 0xFFFFFFFE;
-			__raw_writel(ctrl, reg);
-		}
-		bank->mod_usage |= 1 << offset;
-	}
+
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	return 0;
@@ -1101,24 +1108,40 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
 		__raw_writel(1 << offset, reg);
 	}
 #endif
-	if (!cpu_class_is_omap1()) {
-		bank->mod_usage &= ~(1 << offset);
-		if (!bank->mod_usage) {
-			void __iomem *reg = bank->base;
-			u32 ctrl;
-
-			if (cpu_is_omap24xx() || cpu_is_omap34xx())
-				reg += OMAP24XX_GPIO_CTRL;
-			else if (cpu_is_omap44xx())
-				reg += OMAP4_GPIO_CTRL;
-			ctrl = __raw_readl(reg);
-			/* Module is disabled, clocks are gated */
-			ctrl |= 1;
-			__raw_writel(ctrl, reg);
-		}
+	bank->mod_usage &= ~(1 << offset);
+	if (!bank->mod_usage) {
+		void __iomem *reg = bank->base;
+		u32 ctrl;
+
+		if (bank->method == METHOD_GPIO_24XX)
+			reg += OMAP24XX_GPIO_CTRL;
+		else if (bank->method == METHOD_GPIO_44XX)
+			reg += OMAP4_GPIO_CTRL;
+		else
+			goto reset_gpio;
+
+		ctrl = __raw_readl(reg);
+		/* Module is disabled, clocks are gated */
+		ctrl |= 1;
+		__raw_writel(ctrl, reg);
 	}
+reset_gpio:
 	_reset_gpio(bank, bank->chip.base + offset);
 	spin_unlock_irqrestore(&bank->lock, flags);
+
+	/*
+	 * If this is the last gpio to be freed in the bank,
+	 * disable the bank module
+	 */
+	if (!bank->mod_usage) {
+		if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0)) {
+			struct platform_device *pdev =
+					to_platform_device(bank->dev);
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_put_sync failed\n",
+					__func__, pdev->id);
+		}
+	}
 }
 
 /*
@@ -1142,6 +1165,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
 	bank = irq_get_handler_data(irq);
+
+	pm_runtime_get_sync(bank->dev);
+
 #ifdef CONFIG_ARCH_OMAP1
 	if (bank->method == METHOD_MPUIO)
 		isr_reg = bank->base +
@@ -1233,6 +1259,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 exit:
 	if (!unmasked)
 		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+
+	pm_runtime_put_sync(bank->dev);
 }
 
 static void gpio_irq_shutdown(struct irq_data *d)
@@ -1735,12 +1763,25 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	}
 
 	pm_runtime_enable(bank->dev);
-	pm_runtime_get_sync(bank->dev);
+	pm_runtime_irq_safe(bank->dev);
+
+	if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev) < 0)) {
+		dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_get_sync "
+				"failed\n", __func__, id);
+		iounmap(bank->base);
+		return -EINVAL;
+	}
 
-	omap_gpio_mod_init(bank, id);
 	omap_gpio_chip_init(bank);
 	omap_gpio_show_rev(bank);
 
+	if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0)) {
+		dev_err(bank->dev, "%s: GPIO bank %d pm_runtime_put_sync "
+				"failed\n", __func__, id);
+		iounmap(bank->base);
+		return -EINVAL;
+	}
+
 	if (!gpio_init_done)
 		gpio_init_done = 1;
 
@@ -1748,6 +1789,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+static void omap_gpio_save_context(struct gpio_bank *bank);
+static void omap_gpio_restore_context(struct gpio_bank *bank);
+
 static int is_pwrdm_nxt_state_off;
 
 static inline void omap_gpio_idle_handle_errata_i468(struct gpio_bank *bank)
@@ -1876,9 +1920,11 @@ static inline void omap_gpio_resume_handle_errata_i468(struct gpio_bank *bank)
 		}
 	}
 }
+#endif
 
-static int gpio_bank_handle_idle(struct device *dev)
+static int omap_gpio_pm_runtime_suspend(struct device *dev)
 {
+#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank *bank = &gpio_bank[pdev->id];
 	int j;
@@ -1898,12 +1944,14 @@ static int gpio_bank_handle_idle(struct device *dev)
 		omap_gpio_idle_handle_errata_i468(bank);
 		omap_gpio_save_context(bank);
 	}
+#endif
 
 	return 0;
 }
 
-static int gpio_bank_handle_resume(struct device *dev)
+static int omap_gpio_pm_runtime_resume(struct device *dev)
 {
+#ifdef CONFIG_ARCH_OMAP2PLUS
 	struct platform_device *pdev = to_platform_device(dev);
 	struct gpio_bank *bank = &gpio_bank[pdev->id];
 	u32 ctx_lost_cnt_after;
@@ -1923,124 +1971,89 @@ static int gpio_bank_handle_resume(struct device *dev)
 		omap_gpio_resume_handle_errata_i468(bank);
 		omap_gpio_restore_context(bank);
 	}
+#endif
 
 	return 0;
 }
-#endif
 
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+static int omap_gpio_suspend(struct device *dev)
 {
-	int i;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	void __iomem *wake_status;
+	void __iomem *wake_clear;
+	void __iomem *wake_set;
 
-	if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+	if (!bank->mod_usage)
 		return 0;
 
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-		void __iomem *wake_status;
-		void __iomem *wake_clear;
-		void __iomem *wake_set;
-		unsigned long flags;
+	switch (bank->method) {
+	case METHOD_GPIO_1610:
+		wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
+		wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+		wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+		break;
 
-		switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-		case METHOD_GPIO_1610:
-			wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
-			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-			break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-		case METHOD_GPIO_24XX:
-			wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
-			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-			break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-		case METHOD_GPIO_44XX:
-			wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			break;
-#endif
-		default:
-			continue;
-		}
+	case METHOD_GPIO_24XX:
+		wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
+		wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+		wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+		break;
 
-		spin_lock_irqsave(&bank->lock, flags);
-		bank->saved_wakeup = __raw_readl(wake_status);
-		__raw_writel(0xffffffff, wake_clear);
-		__raw_writel(bank->suspend_wakeup, wake_set);
-		spin_unlock_irqrestore(&bank->lock, flags);
+	case METHOD_GPIO_44XX:
+		wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		break;
+
+	default:
+		return 0;
 	}
 
+	bank->saved_wakeup = __raw_readl(wake_status);
+	__raw_writel(0xffffffff, wake_clear);
+	__raw_writel(bank->suspend_wakeup, wake_set);
+
 	return 0;
 }
 
-static int omap_gpio_resume(struct sys_device *dev)
+static int omap_gpio_resume(struct device *dev)
 {
-	int i;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_bank *bank = &gpio_bank[pdev->id];
+	void __iomem *wake_clear;
+	void __iomem *wake_set;
 
-	if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+	if (!bank->mod_usage)
 		return 0;
 
-	for (i = 0; i < gpio_bank_count; i++) {
-		struct gpio_bank *bank = &gpio_bank[i];
-		void __iomem *wake_clear;
-		void __iomem *wake_set;
-		unsigned long flags;
+	switch (bank->method) {
+	case METHOD_GPIO_1610:
+		wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+		wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+		break;
 
-		switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-		case METHOD_GPIO_1610:
-			wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-			wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-			break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-		case METHOD_GPIO_24XX:
-			wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-			wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-			break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-		case METHOD_GPIO_44XX:
-			wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-			break;
-#endif
-		default:
-			continue;
-		}
+	case METHOD_GPIO_24XX:
+		wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+		wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+		break;
 
-		spin_lock_irqsave(&bank->lock, flags);
-		__raw_writel(0xffffffff, wake_clear);
-		__raw_writel(bank->saved_wakeup, wake_set);
-		spin_unlock_irqrestore(&bank->lock, flags);
+	case METHOD_GPIO_44XX:
+		wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+		break;
+
+	default:
+		return 0;
 	}
 
+	__raw_writel(0xffffffff, wake_clear);
+	__raw_writel(bank->saved_wakeup, wake_set);
+
 	return 0;
 }
 
-static struct sysdev_class omap_gpio_sysclass = {
-	.name		= "gpio",
-	.suspend	= omap_gpio_suspend,
-	.resume		= omap_gpio_resume,
-};
-
-static struct sys_device omap_gpio_device = {
-	.id		= 0,
-	.cls		= &omap_gpio_sysclass,
-};
-
-#endif
-
 #ifdef CONFIG_ARCH_OMAP2PLUS
-static void omap_gpio_save_context(struct gpio_bank *bank);
-static void omap_gpio_restore_context(struct gpio_bank *bank);
-
 void omap2_gpio_prepare_for_idle(int off_mode)
 {
 	int i;
@@ -2050,7 +2063,10 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
-		gpio_bank_handle_idle(bank->dev);
+		if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0))
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_put_sync failed\n",
+					__func__, i);
 	}
 }
 
@@ -2063,7 +2079,10 @@ void omap2_gpio_resume_after_idle(void)
 	for (i = 0; i < gpio_bank_count; i++) {
 		struct gpio_bank *bank = &gpio_bank[i];
 
-		gpio_bank_handle_resume(bank->dev);
+		if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev) < 0))
+			dev_err(bank->dev, "%s: GPIO bank %d "
+					"pm_runtime_get_sync failed\n",
+					__func__, i);
 	}
 }
 
@@ -2162,10 +2181,18 @@ void omap_gpio_restore_context(struct gpio_bank *bank)
 }
 #endif
 
+static const struct dev_pm_ops gpio_pm_ops = {
+	.runtime_suspend	= omap_gpio_pm_runtime_suspend,
+	.runtime_resume		= omap_gpio_pm_runtime_resume,
+	.suspend		= omap_gpio_suspend,
+	.resume			= omap_gpio_resume,
+};
+
 static struct platform_driver omap_gpio_driver = {
 	.probe		= omap_gpio_probe,
 	.driver		= {
 		.name	= "omap_gpio",
+		.pm	= &gpio_pm_ops,
 	},
 };
 
@@ -2182,21 +2209,8 @@ postcore_initcall(omap_gpio_drv_reg);
 
 static int __init omap_gpio_sysinit(void)
 {
-	int ret = 0;
-
 	mpuio_init();
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-		if (ret == 0) {
-			ret = sysdev_class_register(&omap_gpio_sysclass);
-			if (ret == 0)
-				ret = sysdev_register(&omap_gpio_device);
-		}
-	}
-#endif
-
-	return ret;
+	return 0;
 }
 
 arch_initcall(omap_gpio_sysinit);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-18 15:06   ` Varadarajan, Charulatha
@ 2011-04-19  6:26     ` Tony Lindgren
  -1 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-19  6:26 UTC (permalink / raw)
  To: Varadarajan, Charulatha; +Cc: linux-omap, linux-arm-kernel, khilman, paul

* Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
> From: Charulatha V <charu@ti.com>
> 
> Use PM runtime framework in OMAP GPIO driver.
...
 
>  arch/arm/mach-omap2/gpio.c             |    6 +
>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>  4 files changed, 439 insertions(+), 358 deletions(-)

Before this series gets merged we first need to do the following:

- Pass some registers in platform_data so we can have common
  functions in gpio.c instead of having to test for the bank->method
  in each function. This allows getting rid of the ifdefs as
  discussed in the ARM Linux consolidation thread.

- Move it to drivers/gpio

- Further consolidate with whatever common GPIO code might
  be coming up.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-19  6:26     ` Tony Lindgren
  0 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-19  6:26 UTC (permalink / raw)
  To: linux-arm-kernel

* Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
> From: Charulatha V <charu@ti.com>
> 
> Use PM runtime framework in OMAP GPIO driver.
...
 
>  arch/arm/mach-omap2/gpio.c             |    6 +
>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>  4 files changed, 439 insertions(+), 358 deletions(-)

Before this series gets merged we first need to do the following:

- Pass some registers in platform_data so we can have common
  functions in gpio.c instead of having to test for the bank->method
  in each function. This allows getting rid of the ifdefs as
  discussed in the ARM Linux consolidation thread.

- Move it to drivers/gpio

- Further consolidate with whatever common GPIO code might
  be coming up.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-19  6:26     ` Tony Lindgren
@ 2011-04-20 23:59       ` Kevin Hilman
  -1 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-20 23:59 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Varadarajan, Charulatha, linux-omap, linux-arm-kernel, paul

Hi Tony,

Tony Lindgren <tony@atomide.com> writes:

> * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
>> From: Charulatha V <charu@ti.com>
>> 
>> Use PM runtime framework in OMAP GPIO driver.
> ...
>  
>>  arch/arm/mach-omap2/gpio.c             |    6 +
>>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>>  4 files changed, 439 insertions(+), 358 deletions(-)
>
> Before this series gets merged we first need to do the following:
> - Pass some registers in platform_data so we can have common
>   functions in gpio.c instead of having to test for the bank->method
>   in each function. This allows getting rid of the ifdefs as
>   discussed in the ARM Linux consolidation thread.

I have a series that starts this process, will post it shortly.

> - Move it to drivers/gpio
>
> - Further consolidate with whatever common GPIO code might
>   be coming up.

Is the above order required?

IMO, before we move it to drivers/gpio, this code needs to be runtime PM
converted (using this series from Charu.)  The runtime PM conversion
removes a bunch of platform-specific hacks that should be moved into
drivers/*.

Personally, I think we should go in this order

- runtime PM conversion
- #ifdef cleanup
- move to drivers/gpio
- look at consolidation with other drivers

I'm willing to queue the GPIO work in my tree while it's under way if
you like as well.

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-20 23:59       ` Kevin Hilman
  0 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-20 23:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

Tony Lindgren <tony@atomide.com> writes:

> * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
>> From: Charulatha V <charu@ti.com>
>> 
>> Use PM runtime framework in OMAP GPIO driver.
> ...
>  
>>  arch/arm/mach-omap2/gpio.c             |    6 +
>>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>>  4 files changed, 439 insertions(+), 358 deletions(-)
>
> Before this series gets merged we first need to do the following:
> - Pass some registers in platform_data so we can have common
>   functions in gpio.c instead of having to test for the bank->method
>   in each function. This allows getting rid of the ifdefs as
>   discussed in the ARM Linux consolidation thread.

I have a series that starts this process, will post it shortly.

> - Move it to drivers/gpio
>
> - Further consolidate with whatever common GPIO code might
>   be coming up.

Is the above order required?

IMO, before we move it to drivers/gpio, this code needs to be runtime PM
converted (using this series from Charu.)  The runtime PM conversion
removes a bunch of platform-specific hacks that should be moved into
drivers/*.

Personally, I think we should go in this order

- runtime PM conversion
- #ifdef cleanup
- move to drivers/gpio
- look at consolidation with other drivers

I'm willing to queue the GPIO work in my tree while it's under way if
you like as well.

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 3/7] OMAP4: GPIO: Save/restore context
  2011-04-18 15:06   ` Varadarajan, Charulatha
@ 2011-04-21  0:26     ` Kevin Hilman
  -1 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-21  0:26 UTC (permalink / raw)
  To: Varadarajan, Charulatha; +Cc: linux-omap, linux-arm-kernel, tony, paul

"Varadarajan, Charulatha" <charu@ti.com> writes:

> From: Charulatha V <charu@ti.com>
>
> Modify the omap_gpio_save/restore_context to support OMAP4
> architecture so that the OMAP GPIO driver need not be modified
> when OMAP4 off mode support is available.
>
> Signed-off-by: Charulatha V <charu@ti.com>
> ---
>  arch/arm/plat-omap/gpio.c |  131 +++++++++++++++++++++++++++++---------------
>  1 files changed, 86 insertions(+), 45 deletions(-)
>
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index 74085b5..e68da08 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -2022,43 +2022,62 @@ void omap2_gpio_resume_after_idle(void)
>  
>  #endif
>  
> -#ifdef CONFIG_ARCH_OMAP3
> -/* save the registers of bank 2-6 */
>  void omap_gpio_save_context(void)
>  {
>  	int i;
>  
> -	/* saving banks from 2-6 only since GPIO1 is in WKUP */

Minor: these comment removals belong in the previous patch.

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 3/7] OMAP4: GPIO: Save/restore context
@ 2011-04-21  0:26     ` Kevin Hilman
  0 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-21  0:26 UTC (permalink / raw)
  To: linux-arm-kernel

"Varadarajan, Charulatha" <charu@ti.com> writes:

> From: Charulatha V <charu@ti.com>
>
> Modify the omap_gpio_save/restore_context to support OMAP4
> architecture so that the OMAP GPIO driver need not be modified
> when OMAP4 off mode support is available.
>
> Signed-off-by: Charulatha V <charu@ti.com>
> ---
>  arch/arm/plat-omap/gpio.c |  131 +++++++++++++++++++++++++++++---------------
>  1 files changed, 86 insertions(+), 45 deletions(-)
>
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index 74085b5..e68da08 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -2022,43 +2022,62 @@ void omap2_gpio_resume_after_idle(void)
>  
>  #endif
>  
> -#ifdef CONFIG_ARCH_OMAP3
> -/* save the registers of bank 2-6 */
>  void omap_gpio_save_context(void)
>  {
>  	int i;
>  
> -	/* saving banks from 2-6 only since GPIO1 is in WKUP */

Minor: these comment removals belong in the previous patch.

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-20 23:59       ` Kevin Hilman
@ 2011-04-21  5:42         ` Tony Lindgren
  -1 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-21  5:42 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Varadarajan, Charulatha, linux-omap, linux-arm-kernel, paul

* Kevin Hilman <khilman@ti.com> [110421 02:56]:
> Hi Tony,
> 
> Tony Lindgren <tony@atomide.com> writes:
> 
> > * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
> >> From: Charulatha V <charu@ti.com>
> >> 
> >> Use PM runtime framework in OMAP GPIO driver.
> > ...
> >  
> >>  arch/arm/mach-omap2/gpio.c             |    6 +
> >>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
> >>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
> >>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
> >>  4 files changed, 439 insertions(+), 358 deletions(-)
> >
> > Before this series gets merged we first need to do the following:
> > - Pass some registers in platform_data so we can have common
> >   functions in gpio.c instead of having to test for the bank->method
> >   in each function. This allows getting rid of the ifdefs as
> >   discussed in the ARM Linux consolidation thread.
> 
> I have a series that starts this process, will post it shortly.

Saw that, looks good :) Need to post it also to lakml BTW.
 
> > - Move it to drivers/gpio
> >
> > - Further consolidate with whatever common GPIO code might
> >   be coming up.
> 
> Is the above order required?

Yes please. Otherwise we'll have more of the "crazy churn" in
arch/arm/*omap*/ and the runtime PM patches should apply easily
in drivers/gpio too.
 
> IMO, before we move it to drivers/gpio, this code needs to be runtime PM
> converted (using this series from Charu.)  The runtime PM conversion
> removes a bunch of platform-specific hacks that should be moved into
> drivers/*.
> 
> Personally, I think we should go in this order
> 
> - runtime PM conversion

Let's do this after the consolidation and move to drivers/gpio.
This way any additions can be reviewed by the drivers/gpio maintainers.

> - #ifdef cleanup

Looks like you got this already done :)

> - move to drivers/gpio

With this part there may be more comments from the drivers/gpio
maintainers so we need to get to this point ASAP.

> - look at consolidation with other drivers
> 
> I'm willing to queue the GPIO work in my tree while it's under way if
> you like as well.

If so, please put all the consolidation patches into a separate
branch with absolutely zero additional new code. And let's merge
those branches into linux-omap devel-cleanup branch on regular
basis for testing.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-21  5:42         ` Tony Lindgren
  0 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-21  5:42 UTC (permalink / raw)
  To: linux-arm-kernel

* Kevin Hilman <khilman@ti.com> [110421 02:56]:
> Hi Tony,
> 
> Tony Lindgren <tony@atomide.com> writes:
> 
> > * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
> >> From: Charulatha V <charu@ti.com>
> >> 
> >> Use PM runtime framework in OMAP GPIO driver.
> > ...
> >  
> >>  arch/arm/mach-omap2/gpio.c             |    6 +
> >>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
> >>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
> >>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
> >>  4 files changed, 439 insertions(+), 358 deletions(-)
> >
> > Before this series gets merged we first need to do the following:
> > - Pass some registers in platform_data so we can have common
> >   functions in gpio.c instead of having to test for the bank->method
> >   in each function. This allows getting rid of the ifdefs as
> >   discussed in the ARM Linux consolidation thread.
> 
> I have a series that starts this process, will post it shortly.

Saw that, looks good :) Need to post it also to lakml BTW.
 
> > - Move it to drivers/gpio
> >
> > - Further consolidate with whatever common GPIO code might
> >   be coming up.
> 
> Is the above order required?

Yes please. Otherwise we'll have more of the "crazy churn" in
arch/arm/*omap*/ and the runtime PM patches should apply easily
in drivers/gpio too.
 
> IMO, before we move it to drivers/gpio, this code needs to be runtime PM
> converted (using this series from Charu.)  The runtime PM conversion
> removes a bunch of platform-specific hacks that should be moved into
> drivers/*.
> 
> Personally, I think we should go in this order
> 
> - runtime PM conversion

Let's do this after the consolidation and move to drivers/gpio.
This way any additions can be reviewed by the drivers/gpio maintainers.

> - #ifdef cleanup

Looks like you got this already done :)

> - move to drivers/gpio

With this part there may be more comments from the drivers/gpio
maintainers so we need to get to this point ASAP.

> - look at consolidation with other drivers
> 
> I'm willing to queue the GPIO work in my tree while it's under way if
> you like as well.

If so, please put all the consolidation patches into a separate
branch with absolutely zero additional new code. And let's merge
those branches into linux-omap devel-cleanup branch on regular
basis for testing.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-21  5:42         ` Tony Lindgren
@ 2011-04-21 15:15           ` Kevin Hilman
  -1 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-21 15:15 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Varadarajan, Charulatha, linux-omap, linux-arm-kernel, paul

Tony Lindgren <tony@atomide.com> writes:

> * Kevin Hilman <khilman@ti.com> [110421 02:56]:
>> Hi Tony,
>> 
>> Tony Lindgren <tony@atomide.com> writes:
>> 
>> > * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
>> >> From: Charulatha V <charu@ti.com>
>> >> 
>> >> Use PM runtime framework in OMAP GPIO driver.
>> > ...
>> >  
>> >>  arch/arm/mach-omap2/gpio.c             |    6 +
>> >>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>> >>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>> >>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>> >>  4 files changed, 439 insertions(+), 358 deletions(-)
>> >
>> > Before this series gets merged we first need to do the following:
>> > - Pass some registers in platform_data so we can have common
>> >   functions in gpio.c instead of having to test for the bank->method
>> >   in each function. This allows getting rid of the ifdefs as
>> >   discussed in the ARM Linux consolidation thread.
>> 
>> I have a series that starts this process, will post it shortly.
>
> Saw that, looks good :) Need to post it also to lakml BTW.

Yeah, I only posted to l-o so far because it's not done.  I only removed
a few of the #ifdef sections, there are still several more to do.

>> > - Move it to drivers/gpio
>> >
>> > - Further consolidate with whatever common GPIO code might
>> >   be coming up.
>> 
>> Is the above order required?
>
> Yes please. Otherwise we'll have more of the "crazy churn" in
> arch/arm/*omap*/ and the runtime PM patches should apply easily
> in drivers/gpio too.
>  
>> IMO, before we move it to drivers/gpio, this code needs to be runtime PM
>> converted (using this series from Charu.)  The runtime PM conversion
>> removes a bunch of platform-specific hacks that should be moved into
>> drivers/*.
>> 
>> Personally, I think we should go in this order
>> 
>> - runtime PM conversion
>
> Let's do this after the consolidation and move to drivers/gpio.
> This way any additions can be reviewed by the drivers/gpio maintainers.

OK

>> - #ifdef cleanup
>
> Looks like you got this already done :)

Well, it's only partially done.  I only converted the direction and data
in/out functions.  There are several others to do still.

>> - move to drivers/gpio
>
> With this part there may be more comments from the drivers/gpio
> maintainers so we need to get to this point ASAP.

OK

>> - look at consolidation with other drivers
>> 
>> I'm willing to queue the GPIO work in my tree while it's under way if
>> you like as well.
>
> If so, please put all the consolidation patches into a separate
> branch with absolutely zero additional new code. And let's merge
> those branches into linux-omap devel-cleanup branch on regular
> basis for testing.
>

OK

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-21 15:15           ` Kevin Hilman
  0 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-04-21 15:15 UTC (permalink / raw)
  To: linux-arm-kernel

Tony Lindgren <tony@atomide.com> writes:

> * Kevin Hilman <khilman@ti.com> [110421 02:56]:
>> Hi Tony,
>> 
>> Tony Lindgren <tony@atomide.com> writes:
>> 
>> > * Varadarajan, Charulatha <charu@ti.com> [110418 18:00]:
>> >> From: Charulatha V <charu@ti.com>
>> >> 
>> >> Use PM runtime framework in OMAP GPIO driver.
>> > ...
>> >  
>> >>  arch/arm/mach-omap2/gpio.c             |    6 +
>> >>  arch/arm/mach-omap2/pm34xx.c           |   22 +-
>> >>  arch/arm/plat-omap/gpio.c              |  766 ++++++++++++++++++--------------
>> >>  arch/arm/plat-omap/include/plat/gpio.h |    3 +-
>> >>  4 files changed, 439 insertions(+), 358 deletions(-)
>> >
>> > Before this series gets merged we first need to do the following:
>> > - Pass some registers in platform_data so we can have common
>> >   functions in gpio.c instead of having to test for the bank->method
>> >   in each function. This allows getting rid of the ifdefs as
>> >   discussed in the ARM Linux consolidation thread.
>> 
>> I have a series that starts this process, will post it shortly.
>
> Saw that, looks good :) Need to post it also to lakml BTW.

Yeah, I only posted to l-o so far because it's not done.  I only removed
a few of the #ifdef sections, there are still several more to do.

>> > - Move it to drivers/gpio
>> >
>> > - Further consolidate with whatever common GPIO code might
>> >   be coming up.
>> 
>> Is the above order required?
>
> Yes please. Otherwise we'll have more of the "crazy churn" in
> arch/arm/*omap*/ and the runtime PM patches should apply easily
> in drivers/gpio too.
>  
>> IMO, before we move it to drivers/gpio, this code needs to be runtime PM
>> converted (using this series from Charu.)  The runtime PM conversion
>> removes a bunch of platform-specific hacks that should be moved into
>> drivers/*.
>> 
>> Personally, I think we should go in this order
>> 
>> - runtime PM conversion
>
> Let's do this after the consolidation and move to drivers/gpio.
> This way any additions can be reviewed by the drivers/gpio maintainers.

OK

>> - #ifdef cleanup
>
> Looks like you got this already done :)

Well, it's only partially done.  I only converted the direction and data
in/out functions.  There are several others to do still.

>> - move to drivers/gpio
>
> With this part there may be more comments from the drivers/gpio
> maintainers so we need to get to this point ASAP.

OK

>> - look at consolidation with other drivers
>> 
>> I'm willing to queue the GPIO work in my tree while it's under way if
>> you like as well.
>
> If so, please put all the consolidation patches into a separate
> branch with absolutely zero additional new code. And let's merge
> those branches into linux-omap devel-cleanup branch on regular
> basis for testing.
>

OK

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-21 15:15           ` Kevin Hilman
@ 2011-04-22  6:11             ` Tony Lindgren
  -1 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-22  6:11 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Varadarajan, Charulatha, linux-omap, linux-arm-kernel, paul

* Kevin Hilman <khilman@ti.com> [110421 18:12]:
> Tony Lindgren <tony@atomide.com> writes:
> >
> > Saw that, looks good :) Need to post it also to lakml BTW.
> 
> Yeah, I only posted to l-o so far because it's not done.  I only removed
> a few of the #ifdef sections, there are still several more to do.

Oh I see. Anyways looks good to me. I can give it a try next week
too on few boards.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-22  6:11             ` Tony Lindgren
  0 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-22  6:11 UTC (permalink / raw)
  To: linux-arm-kernel

* Kevin Hilman <khilman@ti.com> [110421 18:12]:
> Tony Lindgren <tony@atomide.com> writes:
> >
> > Saw that, looks good :) Need to post it also to lakml BTW.
> 
> Yeah, I only posted to l-o so far because it's not done.  I only removed
> a few of the #ifdef sections, there are still several more to do.

Oh I see. Anyways looks good to me. I can give it a try next week
too on few boards.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-21  5:42         ` Tony Lindgren
@ 2011-04-23  8:35           ` Linus Walleij
  -1 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-04-23  8:35 UTC (permalink / raw)
  To: Tony Lindgren, Kevin Hilman
  Cc: paul, linux-omap, linux-arm-kernel, Varadarajan, Charulatha

2011/4/21 Tony Lindgren <tony@atomide.com>:
> * Kevin Hilman <khilman@ti.com> [110421 02:56]:

>> > - Move it to drivers/gpio
>> >
>> > - Further consolidate with whatever common GPIO code might
>> >   be coming up.
>>
>> Is the above order required?
>
> Yes please. Otherwise we'll have more of the "crazy churn" in
> arch/arm/*omap*/ and the runtime PM patches should apply easily
> in drivers/gpio too.

Since you'll probably be dependent on stuff happening in my patches
to move stuff into drivers/gpio I'll be happy to carry the patches in my
gpio-consolidation branch with Tony's ACKs if need be.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-23  8:35           ` Linus Walleij
  0 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-04-23  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/21 Tony Lindgren <tony@atomide.com>:
> * Kevin Hilman <khilman@ti.com> [110421 02:56]:

>> > - Move it to drivers/gpio
>> >
>> > - Further consolidate with whatever common GPIO code might
>> > ? be coming up.
>>
>> Is the above order required?
>
> Yes please. Otherwise we'll have more of the "crazy churn" in
> arch/arm/*omap*/ and the runtime PM patches should apply easily
> in drivers/gpio too.

Since you'll probably be dependent on stuff happening in my patches
to move stuff into drivers/gpio I'll be happy to carry the patches in my
gpio-consolidation branch with Tony's ACKs if need be.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-23  8:35           ` Linus Walleij
@ 2011-04-26  7:29             ` Tony Lindgren
  -1 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-26  7:29 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Kevin Hilman, paul, linux-omap, linux-arm-kernel, Varadarajan,
	Charulatha

* Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
> 2011/4/21 Tony Lindgren <tony@atomide.com>:
> > * Kevin Hilman <khilman@ti.com> [110421 02:56]:
> 
> >> > - Move it to drivers/gpio
> >> >
> >> > - Further consolidate with whatever common GPIO code might
> >> >   be coming up.
> >>
> >> Is the above order required?
> >
> > Yes please. Otherwise we'll have more of the "crazy churn" in
> > arch/arm/*omap*/ and the runtime PM patches should apply easily
> > in drivers/gpio too.
> 
> Since you'll probably be dependent on stuff happening in my patches
> to move stuff into drivers/gpio I'll be happy to carry the patches in my
> gpio-consolidation branch with Tony's ACKs if need be.

Sounds good to me.

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-26  7:29             ` Tony Lindgren
  0 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-04-26  7:29 UTC (permalink / raw)
  To: linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
> 2011/4/21 Tony Lindgren <tony@atomide.com>:
> > * Kevin Hilman <khilman@ti.com> [110421 02:56]:
> 
> >> > - Move it to drivers/gpio
> >> >
> >> > - Further consolidate with whatever common GPIO code might
> >> > ? be coming up.
> >>
> >> Is the above order required?
> >
> > Yes please. Otherwise we'll have more of the "crazy churn" in
> > arch/arm/*omap*/ and the runtime PM patches should apply easily
> > in drivers/gpio too.
> 
> Since you'll probably be dependent on stuff happening in my patches
> to move stuff into drivers/gpio I'll be happy to carry the patches in my
> gpio-consolidation branch with Tony's ACKs if need be.

Sounds good to me.

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-26  7:29             ` Tony Lindgren
@ 2011-04-27 13:18               ` Linus Walleij
  -1 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-04-27 13:18 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Kevin Hilman, paul, linux-omap, linux-arm-kernel, Varadarajan,
	Charulatha

2011/4/26 Tony Lindgren <tony@atomide.com>:
> * Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
>> Since you'll probably be dependent on stuff happening in my patches
>> to move stuff into drivers/gpio I'll be happy to carry the patches in my
>> gpio-consolidation branch with Tony's ACKs if need be.
>
> Sounds good to me.

I've just posted a patch series that moves "our" two GPIO drivers to
drivers/gpio, they should serve as good inspiration... Tell me if I can
help out, stack patches on top of this series and I'll carry them.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-04-27 13:18               ` Linus Walleij
  0 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-04-27 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/26 Tony Lindgren <tony@atomide.com>:
> * Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
>> Since you'll probably be dependent on stuff happening in my patches
>> to move stuff into drivers/gpio I'll be happy to carry the patches in my
>> gpio-consolidation branch with Tony's ACKs if need be.
>
> Sounds good to me.

I've just posted a patch series that moves "our" two GPIO drivers to
drivers/gpio, they should serve as good inspiration... Tell me if I can
help out, stack patches on top of this series and I'll carry them.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-04-27 13:18               ` Linus Walleij
@ 2011-05-03 16:22                 ` Kevin Hilman
  -1 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-05-03 16:22 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Tony Lindgren, paul, linux-omap, linux-arm-kernel, Varadarajan,
	Charulatha

Linus Walleij <linus.walleij@linaro.org> writes:

> 2011/4/26 Tony Lindgren <tony@atomide.com>:
>> * Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
>>> Since you'll probably be dependent on stuff happening in my patches
>>> to move stuff into drivers/gpio I'll be happy to carry the patches in my
>>> gpio-consolidation branch with Tony's ACKs if need be.
>>
>> Sounds good to me.
>
> I've just posted a patch series that moves "our" two GPIO drivers to
> drivers/gpio, they should serve as good inspiration... Tell me if I can
> help out, stack patches on top of this series and I'll carry them.

Great, thanks.

Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
into drivers/gpio first, followed by the cleanup/restructure patches?

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-03 16:22                 ` Kevin Hilman
  0 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-05-03 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

Linus Walleij <linus.walleij@linaro.org> writes:

> 2011/4/26 Tony Lindgren <tony@atomide.com>:
>> * Linus Walleij <linus.walleij@linaro.org> [110423 01:32]:
>>> Since you'll probably be dependent on stuff happening in my patches
>>> to move stuff into drivers/gpio I'll be happy to carry the patches in my
>>> gpio-consolidation branch with Tony's ACKs if need be.
>>
>> Sounds good to me.
>
> I've just posted a patch series that moves "our" two GPIO drivers to
> drivers/gpio, they should serve as good inspiration... Tell me if I can
> help out, stack patches on top of this series and I'll carry them.

Great, thanks.

Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
into drivers/gpio first, followed by the cleanup/restructure patches?

Kevin

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-03 16:22                 ` Kevin Hilman
@ 2011-05-03 21:41                   ` Linus Walleij
  -1 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-05-03 21:41 UTC (permalink / raw)
  To: Kevin Hilman, Grant Likely
  Cc: Tony Lindgren, paul, linux-omap, linux-arm-kernel, Varadarajan,
	Charulatha

2011/5/3 Kevin Hilman <khilman@ti.com>:

> Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> into drivers/gpio first, followed by the cleanup/restructure patches?

In my case I actually did some cleanup after moving the driver for
U300, but I think this is a question to the GPIO maintainer who
I want to ACK this stuff in the end.

Grant?

You can always squash it later ...

Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-03 21:41                   ` Linus Walleij
  0 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-05-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel

2011/5/3 Kevin Hilman <khilman@ti.com>:

> Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> into drivers/gpio first, followed by the cleanup/restructure patches?

In my case I actually did some cleanup after moving the driver for
U300, but I think this is a question to the GPIO maintainer who
I want to ACK this stuff in the end.

Grant?

You can always squash it later ...

Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-03 21:41                   ` Linus Walleij
@ 2011-05-04  6:19                     ` Tony Lindgren
  -1 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-05-04  6:19 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Kevin Hilman, Grant Likely, paul, linux-omap, linux-arm-kernel,
	Varadarajan, Charulatha

* Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
> 2011/5/3 Kevin Hilman <khilman@ti.com>:
> 
> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> > into drivers/gpio first, followed by the cleanup/restructure patches?
> 
> In my case I actually did some cleanup after moving the driver for
> U300, but I think this is a question to the GPIO maintainer who
> I want to ACK this stuff in the end.
> 
> Grant?
> 
> You can always squash it later ...

Personally I would prefer absolutely minimal clean-up of current
code before moving to drivers/gpio to cut down the "crazy churn" in
arch/arm/. Also then further changes are easier for the GPIO
maintainers to review.

Of course I understand that this might cause extra load for the
GPIO maintainers, so it's up to the GPIO maintainers to set the
required standards before accepting the code into drivers/gpio.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-04  6:19                     ` Tony Lindgren
  0 siblings, 0 replies; 206+ messages in thread
From: Tony Lindgren @ 2011-05-04  6:19 UTC (permalink / raw)
  To: linux-arm-kernel

* Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
> 2011/5/3 Kevin Hilman <khilman@ti.com>:
> 
> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> > into drivers/gpio first, followed by the cleanup/restructure patches?
> 
> In my case I actually did some cleanup after moving the driver for
> U300, but I think this is a question to the GPIO maintainer who
> I want to ACK this stuff in the end.
> 
> Grant?
> 
> You can always squash it later ...

Personally I would prefer absolutely minimal clean-up of current
code before moving to drivers/gpio to cut down the "crazy churn" in
arch/arm/. Also then further changes are easier for the GPIO
maintainers to review.

Of course I understand that this might cause extra load for the
GPIO maintainers, so it's up to the GPIO maintainers to set the
required standards before accepting the code into drivers/gpio.

Regards,

Tony

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-04  6:19                     ` Tony Lindgren
@ 2011-05-12  0:57                       ` Linus Walleij
  -1 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-05-12  0:57 UTC (permalink / raw)
  To: Tony Lindgren, Grant Likely
  Cc: Kevin Hilman, paul, linux-omap, linux-arm-kernel, Varadarajan,
	Charulatha

2011/5/4 Tony Lindgren <tony@atomide.com>:
> * Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
>> 2011/5/3 Kevin Hilman <khilman@ti.com>:
>>
>> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
>> > into drivers/gpio first, followed by the cleanup/restructure patches?
>>
>> In my case I actually did some cleanup after moving the driver for
>> U300, but I think this is a question to the GPIO maintainer who
>> I want to ACK this stuff in the end.
>>
>> Grant?
>>
>> You can always squash it later ...
>
> Personally I would prefer absolutely minimal clean-up of current
> code before moving to drivers/gpio to cut down the "crazy churn" in
> arch/arm/. Also then further changes are easier for the GPIO
> maintainers to review.
>
> Of course I understand that this might cause extra load for the
> GPIO maintainers, so it's up to the GPIO maintainers to set the
> required standards before accepting the code into drivers/gpio.

After discussion with Grant (in person) here at UDS I am informed
that he will not be able to review my GPIO consolidation patches in
time to make adjustments needed for this merge window, so we're
aiming at early 2.6.41 for these.

He has indicated that he has problems with the chosen config
mechanism and that we may need to back a few technical
assumptions out, and we need some more time for that.

For example we may need to refer to configurations by a string
or indeed export the struct gpio_chip accessor function
gpio_to_chip() and use custom functions for special stuff,
as was the first idea.

I will do the refactoring once I have a clear indication from the
maintainer where he wants this to end up, so my GPIO
consolidation patches will need to rest for a while.

For TI I guess this currently means you simply cannot work
on GPIO stuff until you know where to go with it unless you
allow the OMAP GPIO authors to keep churning in arch/arm/*...

That's unless Grant is OK with us moving stuff into
drivers/gpio that does *not* use gpiolib and utilize singletons to
get at the gpio_chip addresses (i.e. current form) and keep it
churning like that until it can be refactored.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-12  0:57                       ` Linus Walleij
  0 siblings, 0 replies; 206+ messages in thread
From: Linus Walleij @ 2011-05-12  0:57 UTC (permalink / raw)
  To: linux-arm-kernel

2011/5/4 Tony Lindgren <tony@atomide.com>:
> * Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
>> 2011/5/3 Kevin Hilman <khilman@ti.com>:
>>
>> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
>> > into drivers/gpio first, followed by the cleanup/restructure patches?
>>
>> In my case I actually did some cleanup after moving the driver for
>> U300, but I think this is a question to the GPIO maintainer who
>> I want to ACK this stuff in the end.
>>
>> Grant?
>>
>> You can always squash it later ...
>
> Personally I would prefer absolutely minimal clean-up of current
> code before moving to drivers/gpio to cut down the "crazy churn" in
> arch/arm/. Also then further changes are easier for the GPIO
> maintainers to review.
>
> Of course I understand that this might cause extra load for the
> GPIO maintainers, so it's up to the GPIO maintainers to set the
> required standards before accepting the code into drivers/gpio.

After discussion with Grant (in person) here at UDS I am informed
that he will not be able to review my GPIO consolidation patches in
time to make adjustments needed for this merge window, so we're
aiming at early 2.6.41 for these.

He has indicated that he has problems with the chosen config
mechanism and that we may need to back a few technical
assumptions out, and we need some more time for that.

For example we may need to refer to configurations by a string
or indeed export the struct gpio_chip accessor function
gpio_to_chip() and use custom functions for special stuff,
as was the first idea.

I will do the refactoring once I have a clear indication from the
maintainer where he wants this to end up, so my GPIO
consolidation patches will need to rest for a while.

For TI I guess this currently means you simply cannot work
on GPIO stuff until you know where to go with it unless you
allow the OMAP GPIO authors to keep churning in arch/arm/*...

That's unless Grant is OK with us moving stuff into
drivers/gpio that does *not* use gpiolib and utilize singletons to
get at the gpio_chip addresses (i.e. current form) and keep it
churning like that until it can be refactored.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-12  0:57                       ` Linus Walleij
@ 2011-05-12  9:42                         ` Kevin Hilman
  -1 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-05-12  9:42 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Tony Lindgren, Grant Likely, paul, linux-omap, linux-arm-kernel,
	Varadarajan, Charulatha

Linus Walleij <linus.walleij@linaro.org> writes:

[...]

> For TI I guess this currently means you simply cannot work
> on GPIO stuff until you know where to go with it unless you
> allow the OMAP GPIO authors to keep churning in arch/arm/*...
>
> That's unless Grant is OK with us moving stuff into
> drivers/gpio that does *not* use gpiolib and utilize singletons to
> get at the gpio_chip addresses (i.e. current form) and keep it
> churning like that until it can be refactored.

The churn will happen one way or another.  the only question is whether
it happens in drivers/gpio or arch/arm/*.

Grant, what's your feeling here.  How much ugliness are you willing to
tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
personally be working on the cleanup/move so I can work either way,
although I know Tony has an obvious preference for moving it to
drivers/gpio. :)

The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
driver is the awful ifdeffery used to handle the differences across the
various SoCs in the OMAP family.  I've already got most of that cleaned
up[1].

Kevin

[1] http://marc.info/?l=linux-omap&m=130351321022770&w=2

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-12  9:42                         ` Kevin Hilman
  0 siblings, 0 replies; 206+ messages in thread
From: Kevin Hilman @ 2011-05-12  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

Linus Walleij <linus.walleij@linaro.org> writes:

[...]

> For TI I guess this currently means you simply cannot work
> on GPIO stuff until you know where to go with it unless you
> allow the OMAP GPIO authors to keep churning in arch/arm/*...
>
> That's unless Grant is OK with us moving stuff into
> drivers/gpio that does *not* use gpiolib and utilize singletons to
> get at the gpio_chip addresses (i.e. current form) and keep it
> churning like that until it can be refactored.

The churn will happen one way or another.  the only question is whether
it happens in drivers/gpio or arch/arm/*.

Grant, what's your feeling here.  How much ugliness are you willing to
tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
personally be working on the cleanup/move so I can work either way,
although I know Tony has an obvious preference for moving it to
drivers/gpio. :)

The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
driver is the awful ifdeffery used to handle the differences across the
various SoCs in the OMAP family.  I've already got most of that cleaned
up[1].

Kevin

[1] http://marc.info/?l=linux-omap&m=130351321022770&w=2

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-12  0:57                       ` Linus Walleij
@ 2011-05-19 19:05                         ` Grant Likely
  -1 siblings, 0 replies; 206+ messages in thread
From: Grant Likely @ 2011-05-19 19:05 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Tony Lindgren, Kevin Hilman, paul, linux-omap, linux-arm-kernel,
	Varadarajan, Charulatha

On Thu, May 12, 2011 at 02:57:04AM +0200, Linus Walleij wrote:
> 2011/5/4 Tony Lindgren <tony@atomide.com>:
> > * Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
> >> 2011/5/3 Kevin Hilman <khilman@ti.com>:
> >>
> >> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> >> > into drivers/gpio first, followed by the cleanup/restructure patches?
> >>
> >> In my case I actually did some cleanup after moving the driver for
> >> U300, but I think this is a question to the GPIO maintainer who
> >> I want to ACK this stuff in the end.
> >>
> >> Grant?
> >>
> >> You can always squash it later ...
> >
> > Personally I would prefer absolutely minimal clean-up of current
> > code before moving to drivers/gpio to cut down the "crazy churn" in
> > arch/arm/. Also then further changes are easier for the GPIO
> > maintainers to review.
> >
> > Of course I understand that this might cause extra load for the
> > GPIO maintainers, so it's up to the GPIO maintainers to set the
> > required standards before accepting the code into drivers/gpio.
> 
> After discussion with Grant (in person) here at UDS I am informed
> that he will not be able to review my GPIO consolidation patches in
> time to make adjustments needed for this merge window, so we're
> aiming at early 2.6.41 for these.
> 
> He has indicated that he has problems with the chosen config
> mechanism and that we may need to back a few technical
> assumptions out, and we need some more time for that.
> 
> For example we may need to refer to configurations by a string
> or indeed export the struct gpio_chip accessor function
> gpio_to_chip() and use custom functions for special stuff,
> as was the first idea.
> 
> I will do the refactoring once I have a clear indication from the
> maintainer where he wants this to end up, so my GPIO
> consolidation patches will need to rest for a while.
> 
> For TI I guess this currently means you simply cannot work
> on GPIO stuff until you know where to go with it unless you
> allow the OMAP GPIO authors to keep churning in arch/arm/*...
> 
> That's unless Grant is OK with us moving stuff into
> drivers/gpio that does *not* use gpiolib and utilize singletons to
> get at the gpio_chip addresses (i.e. current form) and keep it
> churning like that until it can be refactored.

I'm okay with non-gpiolib drivers being moved in before they are
cleaned up.

g.


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-19 19:05                         ` Grant Likely
  0 siblings, 0 replies; 206+ messages in thread
From: Grant Likely @ 2011-05-19 19:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 12, 2011 at 02:57:04AM +0200, Linus Walleij wrote:
> 2011/5/4 Tony Lindgren <tony@atomide.com>:
> > * Linus Walleij <linus.walleij@linaro.org> [110504 00:37]:
> >> 2011/5/3 Kevin Hilman <khilman@ti.com>:
> >>
> >> > Are you OK with a move of the current OMAP GPIO drivers (rather ugly)
> >> > into drivers/gpio first, followed by the cleanup/restructure patches?
> >>
> >> In my case I actually did some cleanup after moving the driver for
> >> U300, but I think this is a question to the GPIO maintainer who
> >> I want to ACK this stuff in the end.
> >>
> >> Grant?
> >>
> >> You can always squash it later ...
> >
> > Personally I would prefer absolutely minimal clean-up of current
> > code before moving to drivers/gpio to cut down the "crazy churn" in
> > arch/arm/. Also then further changes are easier for the GPIO
> > maintainers to review.
> >
> > Of course I understand that this might cause extra load for the
> > GPIO maintainers, so it's up to the GPIO maintainers to set the
> > required standards before accepting the code into drivers/gpio.
> 
> After discussion with Grant (in person) here at UDS I am informed
> that he will not be able to review my GPIO consolidation patches in
> time to make adjustments needed for this merge window, so we're
> aiming at early 2.6.41 for these.
> 
> He has indicated that he has problems with the chosen config
> mechanism and that we may need to back a few technical
> assumptions out, and we need some more time for that.
> 
> For example we may need to refer to configurations by a string
> or indeed export the struct gpio_chip accessor function
> gpio_to_chip() and use custom functions for special stuff,
> as was the first idea.
> 
> I will do the refactoring once I have a clear indication from the
> maintainer where he wants this to end up, so my GPIO
> consolidation patches will need to rest for a while.
> 
> For TI I guess this currently means you simply cannot work
> on GPIO stuff until you know where to go with it unless you
> allow the OMAP GPIO authors to keep churning in arch/arm/*...
> 
> That's unless Grant is OK with us moving stuff into
> drivers/gpio that does *not* use gpiolib and utilize singletons to
> get at the gpio_chip addresses (i.e. current form) and keep it
> churning like that until it can be refactored.

I'm okay with non-gpiolib drivers being moved in before they are
cleaned up.

g.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-12  9:42                         ` Kevin Hilman
@ 2011-05-19 19:08                           ` Grant Likely
  -1 siblings, 0 replies; 206+ messages in thread
From: Grant Likely @ 2011-05-19 19:08 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Linus Walleij, Tony Lindgren, paul, linux-omap, linux-arm-kernel,
	Varadarajan, Charulatha

On Thu, May 12, 2011 at 11:42:39AM +0200, Kevin Hilman wrote:
> Linus Walleij <linus.walleij@linaro.org> writes:
> 
> [...]
> 
> > For TI I guess this currently means you simply cannot work
> > on GPIO stuff until you know where to go with it unless you
> > allow the OMAP GPIO authors to keep churning in arch/arm/*...
> >
> > That's unless Grant is OK with us moving stuff into
> > drivers/gpio that does *not* use gpiolib and utilize singletons to
> > get at the gpio_chip addresses (i.e. current form) and keep it
> > churning like that until it can be refactored.
> 
> The churn will happen one way or another.  the only question is whether
> it happens in drivers/gpio or arch/arm/*.
> 
> Grant, what's your feeling here.  How much ugliness are you willing to
> tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
> personally be working on the cleanup/move so I can work either way,
> although I know Tony has an obvious preference for moving it to
> drivers/gpio. :)
> 
> The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
> driver is the awful ifdeffery used to handle the differences across the
> various SoCs in the OMAP family.  I've already got most of that cleaned
> up[1].

Go ahead and move stuff.  I may as well have the junk in my tree.

I request however to have at least some semblance of organization.
I'd like each driver filename to be named something like gpio_*.c, and
put things into the Makefile/Kconfig in alphabetical order as much as
possible.

Also, for an awful lot of these SoC gpio controllers there is almost
zero value in having a user visible Kconfig entry for it because they
are so tiny.  I'd rather see on-chip gpio controllers configured in
automatically without any user selectable options.

g.


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-19 19:08                           ` Grant Likely
  0 siblings, 0 replies; 206+ messages in thread
From: Grant Likely @ 2011-05-19 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 12, 2011 at 11:42:39AM +0200, Kevin Hilman wrote:
> Linus Walleij <linus.walleij@linaro.org> writes:
> 
> [...]
> 
> > For TI I guess this currently means you simply cannot work
> > on GPIO stuff until you know where to go with it unless you
> > allow the OMAP GPIO authors to keep churning in arch/arm/*...
> >
> > That's unless Grant is OK with us moving stuff into
> > drivers/gpio that does *not* use gpiolib and utilize singletons to
> > get at the gpio_chip addresses (i.e. current form) and keep it
> > churning like that until it can be refactored.
> 
> The churn will happen one way or another.  the only question is whether
> it happens in drivers/gpio or arch/arm/*.
> 
> Grant, what's your feeling here.  How much ugliness are you willing to
> tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
> personally be working on the cleanup/move so I can work either way,
> although I know Tony has an obvious preference for moving it to
> drivers/gpio. :)
> 
> The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
> driver is the awful ifdeffery used to handle the differences across the
> various SoCs in the OMAP family.  I've already got most of that cleaned
> up[1].

Go ahead and move stuff.  I may as well have the junk in my tree.

I request however to have at least some semblance of organization.
I'd like each driver filename to be named something like gpio_*.c, and
put things into the Makefile/Kconfig in alphabetical order as much as
possible.

Also, for an awful lot of these SoC gpio controllers there is almost
zero value in having a user visible Kconfig entry for it because they
are so tiny.  I'd rather see on-chip gpio controllers configured in
automatically without any user selectable options.

g.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [v2 0/7] OMAP: GPIO: Use PM runtime framework
  2011-05-19 19:08                           ` Grant Likely
@ 2011-05-20  3:34                             ` Shawn Guo
  -1 siblings, 0 replies; 206+ messages in thread
From: Shawn Guo @ 2011-05-20  3:34 UTC (permalink / raw)
  To: Grant Likely
  Cc: Kevin Hilman, paul, Tony Lindgren, Linus Walleij, linux-omap,
	linux-arm-kernel, Varadarajan, Charulatha

On Thu, May 19, 2011 at 01:08:41PM -0600, Grant Likely wrote:
> On Thu, May 12, 2011 at 11:42:39AM +0200, Kevin Hilman wrote:
> > Linus Walleij <linus.walleij@linaro.org> writes:
> > 
> > [...]
> > 
> > > For TI I guess this currently means you simply cannot work
> > > on GPIO stuff until you know where to go with it unless you
> > > allow the OMAP GPIO authors to keep churning in arch/arm/*...
> > >
> > > That's unless Grant is OK with us moving stuff into
> > > drivers/gpio that does *not* use gpiolib and utilize singletons to
> > > get at the gpio_chip addresses (i.e. current form) and keep it
> > > churning like that until it can be refactored.
> > 
> > The churn will happen one way or another.  the only question is whether
> > it happens in drivers/gpio or arch/arm/*.
> > 
> > Grant, what's your feeling here.  How much ugliness are you willing to
> > tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
> > personally be working on the cleanup/move so I can work either way,
> > although I know Tony has an obvious preference for moving it to
> > drivers/gpio. :)
> > 
> > The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
> > driver is the awful ifdeffery used to handle the differences across the
> > various SoCs in the OMAP family.  I've already got most of that cleaned
> > up[1].
> 
> Go ahead and move stuff.  I may as well have the junk in my tree.
> 
> I request however to have at least some semblance of organization.
> I'd like each driver filename to be named something like gpio_*.c, and

Just confirm that you really mean gpio_*.c than *_gpio.c, because I
see there have been several *_gpio.c but none gpio_*.c under
drivers/gpio.

> put things into the Makefile/Kconfig in alphabetical order as much as
> possible.
> 

-- 
Regards,
Shawn


^ permalink raw reply	[flat|nested] 206+ messages in thread

* [v2 0/7] OMAP: GPIO: Use PM runtime framework
@ 2011-05-20  3:34                             ` Shawn Guo
  0 siblings, 0 replies; 206+ messages in thread
From: Shawn Guo @ 2011-05-20  3:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 19, 2011 at 01:08:41PM -0600, Grant Likely wrote:
> On Thu, May 12, 2011 at 11:42:39AM +0200, Kevin Hilman wrote:
> > Linus Walleij <linus.walleij@linaro.org> writes:
> > 
> > [...]
> > 
> > > For TI I guess this currently means you simply cannot work
> > > on GPIO stuff until you know where to go with it unless you
> > > allow the OMAP GPIO authors to keep churning in arch/arm/*...
> > >
> > > That's unless Grant is OK with us moving stuff into
> > > drivers/gpio that does *not* use gpiolib and utilize singletons to
> > > get at the gpio_chip addresses (i.e. current form) and keep it
> > > churning like that until it can be refactored.
> > 
> > The churn will happen one way or another.  the only question is whether
> > it happens in drivers/gpio or arch/arm/*.
> > 
> > Grant, what's your feeling here.  How much ugliness are you willing to
> > tolerate in a bulk move to drivers/gpio.  At least for OMAP, I am
> > personally be working on the cleanup/move so I can work either way,
> > although I know Tony has an obvious preference for moving it to
> > drivers/gpio. :)
> > 
> > The OMAP driver is already using gpiolib.  The main ugliness in the OMAP
> > driver is the awful ifdeffery used to handle the differences across the
> > various SoCs in the OMAP family.  I've already got most of that cleaned
> > up[1].
> 
> Go ahead and move stuff.  I may as well have the junk in my tree.
> 
> I request however to have at least some semblance of organization.
> I'd like each driver filename to be named something like gpio_*.c, and

Just confirm that you really mean gpio_*.c than *_gpio.c, because I
see there have been several *_gpio.c but none gpio_*.c under
drivers/gpio.

> put things into the Makefile/Kconfig in alphabetical order as much as
> possible.
> 

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-Display
       [not found] <no>
                   ` (23 preceding siblings ...)
  2011-04-18 15:06   ` Varadarajan, Charulatha
@ 2011-07-05  7:17 ` Ajay Bhargav
  2011-07-06  5:49   ` Prafulla Wadaskar
  2011-07-14  9:37 ` [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h Tanmay Upadhyay
                   ` (13 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Ajay Bhargav @ 2011-07-05  7:17 UTC (permalink / raw)
  To: u-boot

This patch adds basic board support with DRAM and UART functionality

v2 - Updated MAINTAINERS file as suggested by Prafulla.

Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
Acked-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 MAINTAINERS                               |    4 +
 MAKEALL                                   |    1 +
 arch/arm/include/asm/arch-armada100/mfp.h |    4 +-
 board/Marvell/gplugd/Makefile             |   57 +++++++++++++++++++
 board/Marvell/gplugd/gplugd.c             |   62 ++++++++++++++++++++
 boards.cfg                                |    1 +
 include/configs/gplugd.h                  |   87 +++++++++++++++++++++++++++++
 7 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 board/Marvell/gplugd/Makefile
 create mode 100644 board/Marvell/gplugd/gplugd.c
 create mode 100644 include/configs/gplugd.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e2c48a8..0b0c53d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -590,6 +590,10 @@ Eric Benard <eric@eukrea.com>
 	cpu9260		ARM926EJS (AT91SAM9260 SoC)
 	cpu9G20		ARM926EJS (AT91SAM9G20 SoC)
 
+Ajay Bhargav <ajay.bhargav@einfochips.com>
+
+	gplugd		ARM926EJS (ARMADA100 88AP168 SoC)
+
 Rishi Bhattacharya <rishi@ti.com>
 
 	omap5912osk	ARM926EJS
diff --git a/MAKEALL b/MAKEALL
index d592374..259da84 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -388,6 +388,7 @@ LIST_ARM9="			\
 	davinci_dm355leopard	\
 	davinci_dm365evm	\
 	davinci_dm6467evm	\
+	gplugd			\
 "
 
 #########################################################################
diff --git a/arch/arm/include/asm/arch-armada100/mfp.h b/arch/arm/include/asm/arch-armada100/mfp.h
index 73783a7..d6e0494 100644
--- a/arch/arm/include/asm/arch-armada100/mfp.h
+++ b/arch/arm/include/asm/arch-armada100/mfp.h
@@ -57,8 +57,8 @@
 #define MFP89_UART2_TXD		(MFP_REG(0x0164) | MFP_AF2 | MFP_DRIVE_MEDIUM)
 
 /* UART3 */
-#define MFPO8_UART3_RXD		(MFP_REG(0x06c) | MFP_AF2 | MFP_DRIVE_MEDIUM)
-#define MFPO9_UART3_TXD		(MFP_REG(0x070) | MFP_AF2 | MFP_DRIVE_MEDIUM)
+#define MFPO8_UART3_TXD		(MFP_REG(0x06c) | MFP_AF2 | MFP_DRIVE_MEDIUM)
+#define MFPO9_UART3_RXD		(MFP_REG(0x070) | MFP_AF2 | MFP_DRIVE_MEDIUM)
 
 /* I2c */
 #define MFP105_CI2C_SDA		(MFP_REG(0x1a4) | MFP_AF1 | MFP_DRIVE_MEDIUM)
diff --git a/board/Marvell/gplugd/Makefile b/board/Marvell/gplugd/Makefile
new file mode 100644
index 0000000..2d8bba0
--- /dev/null
+++ b/board/Marvell/gplugd/Makefile
@@ -0,0 +1,57 @@
+#
+# (C) Copyright 2011
+# eInfochips Ltd. <www.einfochips.com>
+# Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+#
+# Based on Aspenite:
+# (C) Copyright 2010
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+# Contributor: Mahavir Jain <mjain@marvell.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB     = $(obj)lib$(BOARD).o
+
+COBJS	:= gplugd.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/Marvell/gplugd/gplugd.c b/board/Marvell/gplugd/gplugd.c
new file mode 100644
index 0000000..dc7d89d
--- /dev/null
+++ b/board/Marvell/gplugd/gplugd.c
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2011
+ * eInfochips Ltd. <www.einfochips.com>
+ * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+ *
+ * Based on Aspenite:
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ * Contributor: Mahavir Jain <mjain@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <common.h>
+#include <mvmfp.h>
+#include <asm/arch/mfp.h>
+#include <asm/arch/armada100.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+	u32 mfp_cfg[] = {
+		/* I2C */
+		MFP105_CI2C_SDA,
+		MFP106_CI2C_SCL,
+
+		/* Enable Console on UART3 */
+		MFPO8_UART3_TXD,
+		MFPO9_UART3_RXD,
+		MFP_EOC		/*End of configuration*/
+	};
+	/* configure MFP's */
+	mfp_config(mfp_cfg);
+	return 0;
+}
+
+int board_init(void)
+{
+	/* arch number of Board */
+	gd->bd->bi_arch_number = MACH_TYPE_SHEEVAD;
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = armd1_sdram_base(0) + 0x100;
+	return 0;
+}
diff --git a/boards.cfg b/boards.cfg
index 9f2b118..014d86b 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -72,6 +72,7 @@ netstar                      arm         arm925t
 voiceblue                    arm         arm925t
 omap1510inn                  arm         arm925t     -                   ti
 aspenite                     arm         arm926ejs   -                   Marvell        armada100
+gplugd                       arm         arm926ejs   -                   Marvell        armada100
 afeb9260                     arm         arm926ejs   -                   -              at91
 at91cap9adk                  arm         arm926ejs   -                   atmel          at91
 snapper9260                  arm         arm926ejs   -                   bluewater      at91        snapper9260:AT91SAM9260
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h
new file mode 100644
index 0000000..cc14f49
--- /dev/null
+++ b/include/configs/gplugd.h
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2011
+ * eInfochips Ltd. <www.einfochips.com>
+ * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+ *
+ * Based on Aspenite:
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ * Contributor: Mahavir Jain <mjain@marvell.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __CONFIG_GPLUGD_H
+#define __CONFIG_GPLUGD_H
+
+/*
+ * Version number information
+ */
+#define CONFIG_IDENT_STRING	"\nMarvell-gplugD"
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_SHEEVA_88SV331xV5	1	/* CPU Core subversion */
+#define CONFIG_ARMADA100		1	/* SOC Family Name */
+#define CONFIG_ARMADA168		1	/* SOC Used on this Board */
+#define CONFIG_MACH_SHEEVAD			/* Machine type */
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+
+#define	CONFIG_SYS_TEXT_BASE	0x00f00000
+
+/*
+ * There is no internal RAM in ARMADA100, using DRAM
+ * TBD: dcache to be used for this
+ */
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_TEXT_BASE - 0x00200000)
+#define CONFIG_NR_DRAM_BANKS_MAX	2
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_AUTOSCRIPT
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+#undef CONFIG_ARCH_MISC_INIT
+
+#ifdef CONFIG_SYS_NS16550_COM1
+#undef CONFIG_SYS_NS16550_COM1
+#endif /* CONFIG_SYS_NS16550_COM1 */
+
+#define CONFIG_SYS_NS16550_COM1 ARMD1_UART3_BASE
+
+/*
+ * Environment variables configurations
+ */
+#define CONFIG_ENV_IS_NOWHERE	1	/* if env in SDRAM */
+#define CONFIG_ENV_SIZE	0x20000		/* 64k */
+
+#endif	/* __CONFIG_GPLUGD_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-Display
  2011-07-05  7:17 ` [U-Boot] [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-Display Ajay Bhargav
@ 2011-07-06  5:49   ` Prafulla Wadaskar
  0 siblings, 0 replies; 206+ messages in thread
From: Prafulla Wadaskar @ 2011-07-06  5:49 UTC (permalink / raw)
  To: u-boot



> -----Original Message-----
> From: Ajay Bhargav [mailto:ajay.bhargav at einfochips.com]
> Sent: Tuesday, July 05, 2011 12:47 PM
> To: Prafulla Wadaskar
> Cc: u-boot at lists.denx.de; Ajay Bhargav
> Subject: [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-
> Display
> 
> This patch adds basic board support with DRAM and UART functionality
> 
> v2 - Updated MAINTAINERS file as suggested by Prafulla.
> 
> Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
> Acked-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
> ---
>  MAINTAINERS                               |    4 +
>  MAKEALL                                   |    1 +
>  arch/arm/include/asm/arch-armada100/mfp.h |    4 +-

The change in this file is generic and not related to this board.
So please split the patch into two.

Rest everything looks okay to me.

Regards..
Prafulla . . 

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h
       [not found] <no>
                   ` (24 preceding siblings ...)
  2011-07-05  7:17 ` [U-Boot] [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-Display Ajay Bhargav
@ 2011-07-14  9:37 ` Tanmay Upadhyay
  2011-07-18  6:00   ` Eric Miao
  2011-07-14  9:37 ` [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO Tanmay Upadhyay
                   ` (12 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2011-07-14  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

Move definitions from mfp-gplugd.h to mfp-pxa168.h as they aren't
gplugD specific.

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 arch/arm/mach-mmp/gplugd.c                  |   18 +++++++---
 arch/arm/mach-mmp/include/mach/mfp-gplugd.h |   52 ---------------------------
 arch/arm/mach-mmp/include/mach/mfp-pxa168.h |   37 ++++++++++++++++---
 3 files changed, 45 insertions(+), 62 deletions(-)
 delete mode 100644 arch/arm/mach-mmp/include/mach/mfp-gplugd.h

diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index c070c24..0770e51 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -16,16 +16,18 @@
 #include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
-#include <mach/mfp-gplugd.h>
 
 #include "common.h"
 
 static unsigned long gplugd_pin_config[] __initdata = {
 	/* UART3 */
-	GPIO8_UART3_SOUT,
-	GPIO9_UART3_SIN,
-	GPI1O_UART3_CTS,
-	GPI11_UART3_RTS,
+	GPIO8_UART3_TXD,
+	GPIO9_UART3_RXD,
+	GPIO1O_UART3_CTS,
+	GPIO11_UART3_RTS,
+
+	/* USB OTG PEN */
+	GPIO18_GPIO,
 
 	/* MMC2 */
 	GPIO28_MMC2_CMD,
@@ -109,6 +111,12 @@ static unsigned long gplugd_pin_config[] __initdata = {
 	GPIO105_CI2C_SDA,
 	GPIO106_CI2C_SCL,
 
+	/* SPI NOR Flash on SSP2 */
+	GPIO107_SSP2_RXD,
+	GPIO108_SSP2_TXD,
+	GPIO110_GPIO,     /* SPI_CSn */
+	GPIO111_SSP2_CLK,
+
 	/* Select JTAG */
 	GPIO109_GPIO,
 
diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
deleted file mode 100644
index b8cf38d..0000000
--- a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
- *
- *   MFP definitions used in gplugD
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __MACH_MFP_GPLUGD_H
-#define __MACH_MFP_GPLUGD_H
-
-#include <plat/mfp.h>
-#include <mach/mfp.h>
-
-/* UART3 */
-#define GPIO8_UART3_SOUT       MFP_CFG(GPIO8, AF2)
-#define GPIO9_UART3_SIN        MFP_CFG(GPIO9, AF2)
-#define GPI1O_UART3_CTS        MFP_CFG(GPIO10, AF2)
-#define GPI11_UART3_RTS        MFP_CFG(GPIO11, AF2)
-
-/* MMC2 */
-#define	GPIO28_MMC2_CMD		MFP_CFG_DRV(GPIO28, AF6, FAST)
-#define	GPIO29_MMC2_CLK		MFP_CFG_DRV(GPIO29, AF6, FAST)
-#define	GPIO30_MMC2_DAT0	MFP_CFG_DRV(GPIO30, AF6, FAST)
-#define	GPIO31_MMC2_DAT1	MFP_CFG_DRV(GPIO31, AF6, FAST)
-#define	GPIO32_MMC2_DAT2	MFP_CFG_DRV(GPIO32, AF6, FAST)
-#define	GPIO33_MMC2_DAT3	MFP_CFG_DRV(GPIO33, AF6, FAST)
-
-/* I2S */
-#undef GPIO114_I2S_FRM
-#undef GPIO115_I2S_BCLK
-
-#define GPIO114_I2S_FRM	        MFP_CFG_DRV(GPIO114, AF1, FAST)
-#define GPIO115_I2S_BCLK        MFP_CFG_DRV(GPIO115, AF1, FAST)
-#define GPIO116_I2S_TXD         MFP_CFG_DRV(GPIO116, AF1, FAST)
-
-/* MMC4 */
-#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
-#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
-#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
-#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
-#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
-#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
-
-/* OTG GPIO */
-#define GPIO_USB_OTG_PEN        18
-#define GPIO_USB_OIDIR          20
-
-/* Other GPIOs are 35, 84, 85 */
-#endif /* __MACH_MFP_GPLUGD_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 8c78232..92aaa3c 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -203,6 +203,10 @@
 #define GPIO33_CF_nCD2		MFP_CFG(GPIO33, AF3)
 
 /* UART */
+#define GPIO8_UART3_TXD		MFP_CFG(GPIO8, AF2)
+#define GPIO9_UART3_RXD		MFP_CFG(GPIO9, AF2)
+#define GPIO1O_UART3_CTS	MFP_CFG(GPIO10, AF2)
+#define GPIO11_UART3_RTS	MFP_CFG(GPIO11, AF2)
 #define GPIO88_UART2_TXD	MFP_CFG(GPIO88, AF2)
 #define GPIO89_UART2_RXD	MFP_CFG(GPIO89, AF2)
 #define GPIO107_UART1_TXD	MFP_CFG_DRV(GPIO107, AF1, FAST)
@@ -232,6 +236,22 @@
 #define GPIO53_MMC1_CD		MFP_CFG(GPIO53, AF1)
 #define GPIO46_MMC1_WP		MFP_CFG(GPIO46, AF1)
 
+/* MMC2 */
+#define	GPIO28_MMC2_CMD		MFP_CFG_DRV(GPIO28, AF6, FAST)
+#define	GPIO29_MMC2_CLK		MFP_CFG_DRV(GPIO29, AF6, FAST)
+#define	GPIO30_MMC2_DAT0	MFP_CFG_DRV(GPIO30, AF6, FAST)
+#define	GPIO31_MMC2_DAT1	MFP_CFG_DRV(GPIO31, AF6, FAST)
+#define	GPIO32_MMC2_DAT2	MFP_CFG_DRV(GPIO32, AF6, FAST)
+#define	GPIO33_MMC2_DAT3	MFP_CFG_DRV(GPIO33, AF6, FAST)
+
+/* MMC4 */
+#define GPIO125_MMC4_DAT3       MFP_CFG_DRV(GPIO125, AF7, FAST)
+#define GPIO126_MMC4_DAT2       MFP_CFG_DRV(GPIO126, AF7, FAST)
+#define GPIO127_MMC4_DAT1       MFP_CFG_DRV(GPIO127, AF7, FAST)
+#define GPIO0_2_MMC4_DAT0       MFP_CFG_DRV(GPIO0_2, AF7, FAST)
+#define GPIO1_2_MMC4_CMD        MFP_CFG_DRV(GPIO1_2, AF7, FAST)
+#define GPIO2_2_MMC4_CLK        MFP_CFG_DRV(GPIO2_2, AF7, FAST)
+
 /* LCD */
 #define GPIO84_LCD_CS		MFP_CFG(GPIO84, AF1)
 #define GPIO60_LCD_DD0		MFP_CFG(GPIO60, AF1)
@@ -269,11 +289,12 @@
 #define GPIO106_CI2C_SCL	MFP_CFG(GPIO106, AF1)
 
 /* I2S */
-#define GPIO113_I2S_MCLK	MFP_CFG(GPIO113,AF6)
-#define GPIO114_I2S_FRM		MFP_CFG(GPIO114,AF1)
-#define GPIO115_I2S_BCLK	MFP_CFG(GPIO115,AF1)
-#define GPIO116_I2S_RXD		MFP_CFG(GPIO116,AF2)
-#define GPIO117_I2S_TXD		MFP_CFG(GPIO117,AF2)
+#define GPIO113_I2S_MCLK	MFP_CFG(GPIO113, AF6)
+#define GPIO114_I2S_FRM		MFP_CFG(GPIO114, AF1)
+#define GPIO115_I2S_BCLK	MFP_CFG(GPIO115, AF1)
+#define GPIO116_I2S_RXD		MFP_CFG(GPIO116, AF2)
+#define GPIO116_I2S_TXD         MFP_CFG(GPIO116, AF1)
+#define GPIO117_I2S_TXD		MFP_CFG(GPIO117, AF2)
 
 /* PWM */
 #define GPIO96_PWM3_OUT		MFP_CFG(GPIO96, AF1)
@@ -324,4 +345,10 @@
 #define GPIO101_MII_MDIO	MFP_CFG(GPIO101, AF5)
 #define GPIO103_RX_DV		MFP_CFG(GPIO103, AF5)
 
+/* SSP2 */
+#define GPIO107_SSP2_RXD	MFP_CFG(GPIO107, AF4)
+#define GPIO108_SSP2_TXD	MFP_CFG(GPIO108, AF4)
+#define GPIO111_SSP2_CLK	MFP_CFG(GPIO111, AF4)
+#define GPIO112_SSP2_FRM	MFP_CFG(GPIO112, AF4)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO
       [not found] <no>
                   ` (25 preceding siblings ...)
  2011-07-14  9:37 ` [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h Tanmay Upadhyay
@ 2011-07-14  9:37 ` Tanmay Upadhyay
  2011-07-18  5:59   ` Eric Miao
  2011-09-14  5:59 ` [PATCH] mmc: sdhci-pxa: Check pdata before using its members Tanmay Upadhyay
                   ` (11 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Tanmay Upadhyay @ 2011-07-14  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 arch/arm/mach-mmp/gplugd.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 0770e51..98e25d9 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -162,7 +162,7 @@ static void __init select_disp_freq(void)
 				"frequency\n");
 	} else {
 		gpio_direction_output(35, 1);
-		gpio_free(104);
+		gpio_free(35);
 	}
 
 	if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
@@ -170,7 +170,7 @@ static void __init select_disp_freq(void)
 				"frequency\n");
 	} else {
 		gpio_direction_output(85, 0);
-		gpio_free(104);
+		gpio_free(85);
 	}
 }
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO
  2011-07-14  9:37 ` [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO Tanmay Upadhyay
@ 2011-07-18  5:59   ` Eric Miao
  0 siblings, 0 replies; 206+ messages in thread
From: Eric Miao @ 2011-07-18  5:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 14, 2011 at 5:37 PM, Tanmay Upadhyay
<tanmay.upadhyay@einfochips.com> wrote:
> Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>

Applied to 'devel'.

> ---
> ?arch/arm/mach-mmp/gplugd.c | ? ?4 ++--
> ?1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
> index 0770e51..98e25d9 100644
> --- a/arch/arm/mach-mmp/gplugd.c
> +++ b/arch/arm/mach-mmp/gplugd.c
> @@ -162,7 +162,7 @@ static void __init select_disp_freq(void)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"frequency\n");
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?gpio_direction_output(35, 1);
> - ? ? ? ? ? ? ? gpio_free(104);
> + ? ? ? ? ? ? ? gpio_free(35);
> ? ? ? ?}
>
> ? ? ? ?if (unlikely(gpio_request(85, "DISP_FREQ_SEL_2"))) {
> @@ -170,7 +170,7 @@ static void __init select_disp_freq(void)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"frequency\n");
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?gpio_direction_output(85, 0);
> - ? ? ? ? ? ? ? gpio_free(104);
> + ? ? ? ? ? ? ? gpio_free(85);
> ? ? ? ?}
> ?}
>
> --
> 1.7.0.4
>
>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h
  2011-07-14  9:37 ` [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h Tanmay Upadhyay
@ 2011-07-18  6:00   ` Eric Miao
  0 siblings, 0 replies; 206+ messages in thread
From: Eric Miao @ 2011-07-18  6:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 14, 2011 at 5:37 PM, Tanmay Upadhyay
<tanmay.upadhyay@einfochips.com> wrote:
> Move definitions from mfp-gplugd.h to mfp-pxa168.h as they aren't
> gplugD specific.
>
> Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>

Applied to 'devel'.

> ---
> ?arch/arm/mach-mmp/gplugd.c ? ? ? ? ? ? ? ? ?| ? 18 +++++++---
> ?arch/arm/mach-mmp/include/mach/mfp-gplugd.h | ? 52 ---------------------------
> ?arch/arm/mach-mmp/include/mach/mfp-pxa168.h | ? 37 ++++++++++++++++---
> ?3 files changed, 45 insertions(+), 62 deletions(-)
> ?delete mode 100644 arch/arm/mach-mmp/include/mach/mfp-gplugd.h
>
> diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
> index c070c24..0770e51 100644
> --- a/arch/arm/mach-mmp/gplugd.c
> +++ b/arch/arm/mach-mmp/gplugd.c
> @@ -16,16 +16,18 @@
> ?#include <mach/gpio.h>
> ?#include <mach/pxa168.h>
> ?#include <mach/mfp-pxa168.h>
> -#include <mach/mfp-gplugd.h>
>
> ?#include "common.h"
>
> ?static unsigned long gplugd_pin_config[] __initdata = {
> ? ? ? ?/* UART3 */
> - ? ? ? GPIO8_UART3_SOUT,
> - ? ? ? GPIO9_UART3_SIN,
> - ? ? ? GPI1O_UART3_CTS,
> - ? ? ? GPI11_UART3_RTS,
> + ? ? ? GPIO8_UART3_TXD,
> + ? ? ? GPIO9_UART3_RXD,
> + ? ? ? GPIO1O_UART3_CTS,
> + ? ? ? GPIO11_UART3_RTS,
> +
> + ? ? ? /* USB OTG PEN */
> + ? ? ? GPIO18_GPIO,
>
> ? ? ? ?/* MMC2 */
> ? ? ? ?GPIO28_MMC2_CMD,
> @@ -109,6 +111,12 @@ static unsigned long gplugd_pin_config[] __initdata = {
> ? ? ? ?GPIO105_CI2C_SDA,
> ? ? ? ?GPIO106_CI2C_SCL,
>
> + ? ? ? /* SPI NOR Flash on SSP2 */
> + ? ? ? GPIO107_SSP2_RXD,
> + ? ? ? GPIO108_SSP2_TXD,
> + ? ? ? GPIO110_GPIO, ? ? /* SPI_CSn */
> + ? ? ? GPIO111_SSP2_CLK,
> +
> ? ? ? ?/* Select JTAG */
> ? ? ? ?GPIO109_GPIO,
>
> diff --git a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h b/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
> deleted file mode 100644
> index b8cf38d..0000000
> --- a/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
> +++ /dev/null
> @@ -1,52 +0,0 @@
> -/*
> - * linux/arch/arm/mach-mmp/include/mach/mfp-gplugd.h
> - *
> - * ? MFP definitions used in gplugD
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - */
> -
> -#ifndef __MACH_MFP_GPLUGD_H
> -#define __MACH_MFP_GPLUGD_H
> -
> -#include <plat/mfp.h>
> -#include <mach/mfp.h>
> -
> -/* UART3 */
> -#define GPIO8_UART3_SOUT ? ? ? MFP_CFG(GPIO8, AF2)
> -#define GPIO9_UART3_SIN ? ? ? ?MFP_CFG(GPIO9, AF2)
> -#define GPI1O_UART3_CTS ? ? ? ?MFP_CFG(GPIO10, AF2)
> -#define GPI11_UART3_RTS ? ? ? ?MFP_CFG(GPIO11, AF2)
> -
> -/* MMC2 */
> -#define ? ? ? ?GPIO28_MMC2_CMD ? ? ? ? MFP_CFG_DRV(GPIO28, AF6, FAST)
> -#define ? ? ? ?GPIO29_MMC2_CLK ? ? ? ? MFP_CFG_DRV(GPIO29, AF6, FAST)
> -#define ? ? ? ?GPIO30_MMC2_DAT0 ? ? ? ?MFP_CFG_DRV(GPIO30, AF6, FAST)
> -#define ? ? ? ?GPIO31_MMC2_DAT1 ? ? ? ?MFP_CFG_DRV(GPIO31, AF6, FAST)
> -#define ? ? ? ?GPIO32_MMC2_DAT2 ? ? ? ?MFP_CFG_DRV(GPIO32, AF6, FAST)
> -#define ? ? ? ?GPIO33_MMC2_DAT3 ? ? ? ?MFP_CFG_DRV(GPIO33, AF6, FAST)
> -
> -/* I2S */
> -#undef GPIO114_I2S_FRM
> -#undef GPIO115_I2S_BCLK
> -
> -#define GPIO114_I2S_FRM ? ? ? ? ? ? ? ?MFP_CFG_DRV(GPIO114, AF1, FAST)
> -#define GPIO115_I2S_BCLK ? ? ? ?MFP_CFG_DRV(GPIO115, AF1, FAST)
> -#define GPIO116_I2S_TXD ? ? ? ? MFP_CFG_DRV(GPIO116, AF1, FAST)
> -
> -/* MMC4 */
> -#define GPIO125_MMC4_DAT3 ? ? ? MFP_CFG_DRV(GPIO125, AF7, FAST)
> -#define GPIO126_MMC4_DAT2 ? ? ? MFP_CFG_DRV(GPIO126, AF7, FAST)
> -#define GPIO127_MMC4_DAT1 ? ? ? MFP_CFG_DRV(GPIO127, AF7, FAST)
> -#define GPIO0_2_MMC4_DAT0 ? ? ? MFP_CFG_DRV(GPIO0_2, AF7, FAST)
> -#define GPIO1_2_MMC4_CMD ? ? ? ?MFP_CFG_DRV(GPIO1_2, AF7, FAST)
> -#define GPIO2_2_MMC4_CLK ? ? ? ?MFP_CFG_DRV(GPIO2_2, AF7, FAST)
> -
> -/* OTG GPIO */
> -#define GPIO_USB_OTG_PEN ? ? ? ?18
> -#define GPIO_USB_OIDIR ? ? ? ? ?20
> -
> -/* Other GPIOs are 35, 84, 85 */
> -#endif /* __MACH_MFP_GPLUGD_H */
> diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
> index 8c78232..92aaa3c 100644
> --- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
> +++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
> @@ -203,6 +203,10 @@
> ?#define GPIO33_CF_nCD2 ? ? ? ? MFP_CFG(GPIO33, AF3)
>
> ?/* UART */
> +#define GPIO8_UART3_TXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO8, AF2)
> +#define GPIO9_UART3_RXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO9, AF2)
> +#define GPIO1O_UART3_CTS ? ? ? MFP_CFG(GPIO10, AF2)
> +#define GPIO11_UART3_RTS ? ? ? MFP_CFG(GPIO11, AF2)
> ?#define GPIO88_UART2_TXD ? ? ? MFP_CFG(GPIO88, AF2)
> ?#define GPIO89_UART2_RXD ? ? ? MFP_CFG(GPIO89, AF2)
> ?#define GPIO107_UART1_TXD ? ? ?MFP_CFG_DRV(GPIO107, AF1, FAST)
> @@ -232,6 +236,22 @@
> ?#define GPIO53_MMC1_CD ? ? ? ? MFP_CFG(GPIO53, AF1)
> ?#define GPIO46_MMC1_WP ? ? ? ? MFP_CFG(GPIO46, AF1)
>
> +/* MMC2 */
> +#define ? ? ? ?GPIO28_MMC2_CMD ? ? ? ? MFP_CFG_DRV(GPIO28, AF6, FAST)
> +#define ? ? ? ?GPIO29_MMC2_CLK ? ? ? ? MFP_CFG_DRV(GPIO29, AF6, FAST)
> +#define ? ? ? ?GPIO30_MMC2_DAT0 ? ? ? ?MFP_CFG_DRV(GPIO30, AF6, FAST)
> +#define ? ? ? ?GPIO31_MMC2_DAT1 ? ? ? ?MFP_CFG_DRV(GPIO31, AF6, FAST)
> +#define ? ? ? ?GPIO32_MMC2_DAT2 ? ? ? ?MFP_CFG_DRV(GPIO32, AF6, FAST)
> +#define ? ? ? ?GPIO33_MMC2_DAT3 ? ? ? ?MFP_CFG_DRV(GPIO33, AF6, FAST)
> +
> +/* MMC4 */
> +#define GPIO125_MMC4_DAT3 ? ? ? MFP_CFG_DRV(GPIO125, AF7, FAST)
> +#define GPIO126_MMC4_DAT2 ? ? ? MFP_CFG_DRV(GPIO126, AF7, FAST)
> +#define GPIO127_MMC4_DAT1 ? ? ? MFP_CFG_DRV(GPIO127, AF7, FAST)
> +#define GPIO0_2_MMC4_DAT0 ? ? ? MFP_CFG_DRV(GPIO0_2, AF7, FAST)
> +#define GPIO1_2_MMC4_CMD ? ? ? ?MFP_CFG_DRV(GPIO1_2, AF7, FAST)
> +#define GPIO2_2_MMC4_CLK ? ? ? ?MFP_CFG_DRV(GPIO2_2, AF7, FAST)
> +
> ?/* LCD */
> ?#define GPIO84_LCD_CS ? ? ? ? ?MFP_CFG(GPIO84, AF1)
> ?#define GPIO60_LCD_DD0 ? ? ? ? MFP_CFG(GPIO60, AF1)
> @@ -269,11 +289,12 @@
> ?#define GPIO106_CI2C_SCL ? ? ? MFP_CFG(GPIO106, AF1)
>
> ?/* I2S */
> -#define GPIO113_I2S_MCLK ? ? ? MFP_CFG(GPIO113,AF6)
> -#define GPIO114_I2S_FRM ? ? ? ? ? ? ? ?MFP_CFG(GPIO114,AF1)
> -#define GPIO115_I2S_BCLK ? ? ? MFP_CFG(GPIO115,AF1)
> -#define GPIO116_I2S_RXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO116,AF2)
> -#define GPIO117_I2S_TXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO117,AF2)
> +#define GPIO113_I2S_MCLK ? ? ? MFP_CFG(GPIO113, AF6)
> +#define GPIO114_I2S_FRM ? ? ? ? ? ? ? ?MFP_CFG(GPIO114, AF1)
> +#define GPIO115_I2S_BCLK ? ? ? MFP_CFG(GPIO115, AF1)
> +#define GPIO116_I2S_RXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO116, AF2)
> +#define GPIO116_I2S_TXD ? ? ? ? MFP_CFG(GPIO116, AF1)
> +#define GPIO117_I2S_TXD ? ? ? ? ? ? ? ?MFP_CFG(GPIO117, AF2)
>
> ?/* PWM */
> ?#define GPIO96_PWM3_OUT ? ? ? ? ? ? ? ?MFP_CFG(GPIO96, AF1)
> @@ -324,4 +345,10 @@
> ?#define GPIO101_MII_MDIO ? ? ? MFP_CFG(GPIO101, AF5)
> ?#define GPIO103_RX_DV ? ? ? ? ?MFP_CFG(GPIO103, AF5)
>
> +/* SSP2 */
> +#define GPIO107_SSP2_RXD ? ? ? MFP_CFG(GPIO107, AF4)
> +#define GPIO108_SSP2_TXD ? ? ? MFP_CFG(GPIO108, AF4)
> +#define GPIO111_SSP2_CLK ? ? ? MFP_CFG(GPIO111, AF4)
> +#define GPIO112_SSP2_FRM ? ? ? MFP_CFG(GPIO112, AF4)
> +
> ?#endif /* __ASM_MACH_MFP_PXA168_H */
> --
> 1.7.0.4
>
>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] mmc: sdhci-pxa: Check pdata before using its members
       [not found] <no>
                   ` (26 preceding siblings ...)
  2011-07-14  9:37 ` [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO Tanmay Upadhyay
@ 2011-09-14  5:59 ` Tanmay Upadhyay
  2011-09-14  6:15   ` zhangfei gao
  2011-09-21 18:12   ` Chris Ball
  2011-11-14  9:43 ` [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100 Ajay Bhargav
                   ` (10 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2011-09-14  5:59 UTC (permalink / raw)
  To: zhangfei.gao, dwang4, njun, wuqm, prakity; +Cc: linux-mmc, cjb, Tanmay Upadhyay

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 drivers/mmc/host/sdhci-pxav2.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 38f5899..1114fe2 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -59,7 +59,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
 		 * tune timing of read data/command when crc error happen
 		 * no performance impact
 		 */
-		if (pdata->clk_delay_sel == 1) {
+		if (pdata && pdata->clk_delay_sel == 1) {
 			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 
 			tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT);
@@ -71,7 +71,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
 			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 		}
 
-		if (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING) {
+		if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) {
 			tmp = readw(host->ioaddr + SD_FIFO_PARAM);
 			tmp &= ~CLK_GATE_SETTING_BITS;
 			writew(tmp, host->ioaddr + SD_FIFO_PARAM);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH] mmc: sdhci-pxa: Check pdata before using its members
  2011-09-14  5:59 ` [PATCH] mmc: sdhci-pxa: Check pdata before using its members Tanmay Upadhyay
@ 2011-09-14  6:15   ` zhangfei gao
  2011-09-21 18:12   ` Chris Ball
  1 sibling, 0 replies; 206+ messages in thread
From: zhangfei gao @ 2011-09-14  6:15 UTC (permalink / raw)
  To: Tanmay Upadhyay; +Cc: zhangfei.gao, dwang4, njun, wuqm, prakity, linux-mmc, cjb

On Wed, Sep 14, 2011 at 1:59 PM, Tanmay Upadhyay
<tanmay.upadhyay@einfochips.com> wrote:
> Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>

Acked-by: Zhangfei Gao <zhangfei.gao@marvell.com>

Thanks
> ---
>  drivers/mmc/host/sdhci-pxav2.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] mmc: sdhci-pxa: Check pdata before using its members
  2011-09-14  5:59 ` [PATCH] mmc: sdhci-pxa: Check pdata before using its members Tanmay Upadhyay
  2011-09-14  6:15   ` zhangfei gao
@ 2011-09-21 18:12   ` Chris Ball
  1 sibling, 0 replies; 206+ messages in thread
From: Chris Ball @ 2011-09-21 18:12 UTC (permalink / raw)
  To: Tanmay Upadhyay; +Cc: zhangfei.gao, dwang4, njun, wuqm, prakity, linux-mmc

Hi Tanmay,

Thanks, pushed to mmc-next for 3.2 with Zhangfei's ACK.

- Chris.
-- 
Chris Ball   <cjb@laptop.org>   <http://printf.net/>
One Laptop Per Child

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100
       [not found] <no>
                   ` (27 preceding siblings ...)
  2011-09-14  5:59 ` [PATCH] mmc: sdhci-pxa: Check pdata before using its members Tanmay Upadhyay
@ 2011-11-14  9:43 ` Ajay Bhargav
  2011-11-25 23:44   ` Andy Fleming
  2011-12-06 11:07 ` [PATCH] USB: pxa168: Fix compilation error Tanmay Upadhyay
                   ` (9 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Ajay Bhargav @ 2011-11-14  9:43 UTC (permalink / raw)
  To: u-boot

sdhci_readw does not work for host version read in Armada100 series
SoCs. This patch fix this issue by making a sdhci_readl call to get host
version.

Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
---
Changes for v2:
	- Added quirk instead of #define (suggested by Marek)

 drivers/mmc/mv_sdhci.c |    5 ++++-
 include/sdhci.h        |    1 +
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index f92caeb..c9b7079 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -48,7 +48,10 @@ int mv_sdh_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
 		mv_ops.write_b = mv_sdhci_writeb;
 	host->ops = &mv_ops;
 #endif
-	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+	if (quirks & SDHCI_QUIRK_REG32_RW)
+		host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+	else
+		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 	add_sdhci(host, max_clk, min_clk);
 	return 0;
 }
diff --git a/include/sdhci.h b/include/sdhci.h
index 0690938..800f9d9 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -215,6 +215,7 @@
  * quirks
  */
 #define SDHCI_QUIRK_32BIT_DMA_ADDR	(1 << 0)
+#define SDHCI_QUIRK_REG32_RW		(1 << 1)
 
 /* to make gcc happy */
 struct sdhci_host;
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100
  2011-11-14  9:43 ` [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100 Ajay Bhargav
@ 2011-11-25 23:44   ` Andy Fleming
  0 siblings, 0 replies; 206+ messages in thread
From: Andy Fleming @ 2011-11-25 23:44 UTC (permalink / raw)
  To: u-boot

On Mon, Nov 14, 2011 at 3:43 AM, Ajay Bhargav
<ajay.bhargav@einfochips.com> wrote:
> sdhci_readw does not work for host version read in Armada100 series
> SoCs. This patch fix this issue by making a sdhci_readl call to get host
> version.
>
> Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>

Applied, thx

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] USB: pxa168: Fix compilation error
       [not found] <no>
                   ` (28 preceding siblings ...)
  2011-11-14  9:43 ` [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100 Ajay Bhargav
@ 2011-12-06 11:07 ` Tanmay Upadhyay
  2011-12-06 11:25   ` Sergei Shtylyov
  2011-12-07 19:57   ` [PATCH] " Alan Stern
  2012-02-07 22:58 ` [PATCH v2] add support for AR6003 2048 byte board file Prasanna Kumar
                   ` (8 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2011-12-06 11:07 UTC (permalink / raw)
  To: linux-arm-kernel

After commit c430131a02d677aa708f56342c1565edfdacb3c0,
HC_LENGTH takes two arguments. This patch fixes following
compilation error:

In file included from drivers/usb/host/ehci-hcd.c:1323:
drivers/usb/host/ehci-pxa168.c:302:54: error: macro "HC_LENGTH" requires 2 arguments, but only 1 given
In file included from drivers/usb/host/ehci-hcd.c:1323:
drivers/usb/host/ehci-pxa168.c: In function 'ehci_pxa168_drv_probe':
drivers/usb/host/ehci-pxa168.c:302: error: 'HC_LENGTH' undeclared (first use in this function)
drivers/usb/host/ehci-pxa168.c:302: error: (Each undeclared identifier is reported only once
drivers/usb/host/ehci-pxa168.c:302: error: for each function it appears in.)

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 drivers/usb/host/ehci-pxa168.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
index ac0c16e..8d0e7a2 100644
--- a/drivers/usb/host/ehci-pxa168.c
+++ b/drivers/usb/host/ehci-pxa168.c
@@ -299,7 +299,7 @@ static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev)
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = hcd->regs + 0x100;
 	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 	hcd->has_tt = 1;
 	ehci->sbrn = 0x20;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH] USB: pxa168: Fix compilation error
  2011-12-06 11:07 ` [PATCH] USB: pxa168: Fix compilation error Tanmay Upadhyay
@ 2011-12-06 11:25   ` Sergei Shtylyov
  2011-12-08  4:33     ` [PATCH v2] " Tanmay Upadhyay
  2011-12-07 19:57   ` [PATCH] " Alan Stern
  1 sibling, 1 reply; 206+ messages in thread
From: Sergei Shtylyov @ 2011-12-06 11:25 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 06-12-2011 15:07, Tanmay Upadhyay wrote:

> After commit c430131a02d677aa708f56342c1565edfdacb3c0,

   Please also specify that commit's summary in parens.

> HC_LENGTH takes two arguments. This patch fixes following
> compilation error:

> In file included from drivers/usb/host/ehci-hcd.c:1323:
> drivers/usb/host/ehci-pxa168.c:302:54: error: macro "HC_LENGTH" requires 2 arguments, but only 1 given
> In file included from drivers/usb/host/ehci-hcd.c:1323:
> drivers/usb/host/ehci-pxa168.c: In function 'ehci_pxa168_drv_probe':
> drivers/usb/host/ehci-pxa168.c:302: error: 'HC_LENGTH' undeclared (first use in this function)
> drivers/usb/host/ehci-pxa168.c:302: error: (Each undeclared identifier is reported only once
> drivers/usb/host/ehci-pxa168.c:302: error: for each function it appears in.)

> Signed-off-by: Tanmay Upadhyay<tanmay.upadhyay@einfochips.com>

WBR, Sergei

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] USB: pxa168: Fix compilation error
  2011-12-06 11:07 ` [PATCH] USB: pxa168: Fix compilation error Tanmay Upadhyay
  2011-12-06 11:25   ` Sergei Shtylyov
@ 2011-12-07 19:57   ` Alan Stern
  1 sibling, 0 replies; 206+ messages in thread
From: Alan Stern @ 2011-12-07 19:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 6 Dec 2011, Tanmay Upadhyay wrote:

> After commit c430131a02d677aa708f56342c1565edfdacb3c0,
> HC_LENGTH takes two arguments. This patch fixes following
> compilation error:
> 
> In file included from drivers/usb/host/ehci-hcd.c:1323:
> drivers/usb/host/ehci-pxa168.c:302:54: error: macro "HC_LENGTH" requires 2 arguments, but only 1 given
> In file included from drivers/usb/host/ehci-hcd.c:1323:
> drivers/usb/host/ehci-pxa168.c: In function 'ehci_pxa168_drv_probe':
> drivers/usb/host/ehci-pxa168.c:302: error: 'HC_LENGTH' undeclared (first use in this function)
> drivers/usb/host/ehci-pxa168.c:302: error: (Each undeclared identifier is reported only once
> drivers/usb/host/ehci-pxa168.c:302: error: for each function it appears in.)
> 
> Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
> ---
>  drivers/usb/host/ehci-pxa168.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
> index ac0c16e..8d0e7a2 100644
> --- a/drivers/usb/host/ehci-pxa168.c
> +++ b/drivers/usb/host/ehci-pxa168.c
> @@ -299,7 +299,7 @@ static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev)
>  	ehci = hcd_to_ehci(hcd);
>  	ehci->caps = hcd->regs + 0x100;
>  	ehci->regs = hcd->regs + 0x100 +
> -		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
> +		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
>  	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
>  	hcd->has_tt = 1;
>  	ehci->sbrn = 0x20;

Acked-by: Alan Stern <stern@rowland.harvard.edu>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] USB: pxa168: Fix compilation error
  2011-12-06 11:25   ` Sergei Shtylyov
@ 2011-12-08  4:33     ` Tanmay Upadhyay
  0 siblings, 0 replies; 206+ messages in thread
From: Tanmay Upadhyay @ 2011-12-08  4:33 UTC (permalink / raw)
  To: linux-arm-kernel

After commit c430131a02d677aa708f56342c1565edfdacb3c0 (Support
controllers with big endian capability regs), HC_LENGTH takes
two arguments. This patch fixes following compilation error:

In file included from drivers/usb/host/ehci-hcd.c:1323:
drivers/usb/host/ehci-pxa168.c:302:54: error: macro "HC_LENGTH" requires 2 arguments, but only 1 given
In file included from drivers/usb/host/ehci-hcd.c:1323:
drivers/usb/host/ehci-pxa168.c: In function 'ehci_pxa168_drv_probe':
drivers/usb/host/ehci-pxa168.c:302: error: 'HC_LENGTH' undeclared (first use in this function)
drivers/usb/host/ehci-pxa168.c:302: error: (Each undeclared identifier is reported only once
drivers/usb/host/ehci-pxa168.c:302: error: for each function it appears in.)

v2 - Added summary of the commit that caused this change

Signed-off-by: Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
---
 drivers/usb/host/ehci-pxa168.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
index ac0c16e..8d0e7a2 100644
--- a/drivers/usb/host/ehci-pxa168.c
+++ b/drivers/usb/host/ehci-pxa168.c
@@ -299,7 +299,7 @@ static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev)
 	ehci = hcd_to_ehci(hcd);
 	ehci->caps = hcd->regs + 0x100;
 	ehci->regs = hcd->regs + 0x100 +
-		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 	hcd->has_tt = 1;
 	ehci->sbrn = 0x20;
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH v2] add support for AR6003 2048 byte board file
       [not found] <no>
                   ` (29 preceding siblings ...)
  2011-12-06 11:07 ` [PATCH] USB: pxa168: Fix compilation error Tanmay Upadhyay
@ 2012-02-07 22:58 ` Prasanna Kumar
  2012-02-08  9:41   ` Kalle Valo
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
                   ` (7 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Prasanna Kumar @ 2012-02-07 22:58 UTC (permalink / raw)
  To: kvalo; +Cc: ath6kl-devel, linux-wireless

AR6003 2.1.1 supports both 1792 and 2048 byte board files.
Add support for 2048 byte board file.

Signed-off-by: Prasanna Kumar <kumarpra@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/init.c   |    2 ++
 drivers/net/wireless/ath/ath6kl/target.h |    1 +
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index d1d89b5..47b9897 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1142,6 +1142,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
 	case TARGET_TYPE_AR6003:
 		board_data_size = AR6003_BOARD_DATA_SZ;
 		board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
+		if (ar->fw_board_len > (board_data_size + board_ext_data_size))
+			board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ_V2;
 		break;
 	case TARGET_TYPE_AR6004:
 		board_data_size = AR6004_BOARD_DATA_SZ;
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
index 108a723..b51cd19 100644
--- a/drivers/net/wireless/ath/ath6kl/target.h
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -19,6 +19,7 @@
 
 #define AR6003_BOARD_DATA_SZ		1024
 #define AR6003_BOARD_EXT_DATA_SZ	768
+#define AR6003_BOARD_EXT_DATA_SZ_V2	1024
 
 #define AR6004_BOARD_DATA_SZ     6144
 #define AR6004_BOARD_EXT_DATA_SZ 0
-- 
1.7.0.2


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH v2] add support for AR6003 2048 byte board file
  2012-02-07 22:58 ` [PATCH v2] add support for AR6003 2048 byte board file Prasanna Kumar
@ 2012-02-08  9:41   ` Kalle Valo
  0 siblings, 0 replies; 206+ messages in thread
From: Kalle Valo @ 2012-02-08  9:41 UTC (permalink / raw)
  To: Prasanna Kumar; +Cc: ath6kl-devel, linux-wireless

On 02/08/2012 12:58 AM, Prasanna Kumar wrote:
> AR6003 2.1.1 supports both 1792 and 2048 byte board files.
> Add support for 2048 byte board file.
> 
> Signed-off-by: Prasanna Kumar <kumarpra@qca.qualcomm.com>

Thanks, applied but I added "ath6kl:" to the title.

Kalle

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs
       [not found] <no>
                   ` (30 preceding siblings ...)
  2012-02-07 22:58 ` [PATCH v2] add support for AR6003 2048 byte board file Prasanna Kumar
@ 2012-07-10 13:46 ` Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: removed cached qemu_irq from PCI host bus Alexey Kardashevskiy
                     ` (4 more replies)
  2012-07-25  5:20 ` [PATCH] fixed a macro coding style issue Baodong Chen
                   ` (6 subsequent siblings)
  38 siblings, 5 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, qemu-devel, agraf, qemu-ppc, David Gibson

sPAPR IOMMU RTAS handler is split to common h_put_tce() part and
emulated IOMMU implementation called put_tce_emu().

Further patches will extend h_put_tce() with put_tce_vfio() in
order to support other types of IOMMU such as VFIO.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/spapr_iommu.c |   25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
index 388ffa4..3021bfe 100644
--- a/hw/spapr_iommu.c
+++ b/hw/spapr_iommu.c
@@ -162,21 +162,25 @@ void spapr_tce_free(DMAContext *dma)
     }
 }
 
-static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
-                                target_ulong tce)
+static int put_tce_emu(target_ulong liobn, target_ulong ioba, target_ulong tce)
 {
+    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
     sPAPRTCE *tcep;
 
+    if (!tcet) {
+        return 1;
+    }
+
     if (ioba >= tcet->window_size) {
         hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
                       TARGET_FMT_lx "\n", ioba);
-        return H_PARAMETER;
+        return -1;
     }
 
     tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
     tcep->tce = tce;
 
-    return H_SUCCESS;
+    return 0;
 }
 
 static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -185,7 +189,7 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
     target_ulong liobn = args[0];
     target_ulong ioba = args[1];
     target_ulong tce = args[2];
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    int ret;
 
     if (liobn & 0xFFFFFFFF00000000ULL) {
         hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
@@ -195,13 +199,14 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
 
     ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
 
-    if (tcet) {
-        return put_tce_emu(tcet, ioba, tce);
+    ret = put_tce_emu(liobn, ioba, tce);
+    if (0 >= ret) {
+        return ret ? H_PARAMETER : H_SUCCESS;
     }
 #ifdef DEBUG_TCE
-    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
-            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
-            __func__, liobn, /*dev->qdev.id, */ioba, tce);
+    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx
+            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx " ret=%d\n",
+            __func__, liobn, ioba, tce, ret);
 #endif
 
     return H_PARAMETER;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] pseries pci: removed cached qemu_irq from PCI host bus
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
@ 2012-07-10 13:46   ` Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries: added allocator for a block of IRQs Alexey Kardashevskiy
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, qemu-devel, Alexander Graf, qemu-ppc, David Gibson

As it is a very quick operation to resolve qirq from IRQ number,
it makes no sense to cache it anywhere but its original source i.e. XICS.

Also, the upcoming support for MSIX is going to add much more IRQs per
PHB. So we will have to cache them as well for consistency, and for that
we will have to create an array of qemu_irq pointers.

So it is simplier to keep only IRQ numbers (one per INTx line) and the first
MSI IRQ number with vectors number (will be added later).

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/spapr_pci.c |   14 +++++---------
 hw/spapr_pci.h |    1 -
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index b3032d2..1318390 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -223,7 +223,9 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
      */
     sPAPRPHBState *phb = opaque;
 
-    qemu_set_irq(phb->lsi_table[irq_num].qirq, level);
+    qemu_set_irq(xics_assign_irq(spapr->icp,
+                                 phb->lsi_table[irq_num].dt_irq, XICS_LSI),
+                 level);
 }
 
 static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
@@ -329,16 +331,10 @@ static int spapr_phb_init(SysBusDevice *s)
 
     /* Initialize the LSI table */
     for (i = 0; i < PCI_NUM_PINS; i++) {
-        qemu_irq qirq;
-        uint32_t num;
-
-        qirq = spapr_allocate_lsi(0, &num);
-        if (!qirq) {
+        if (!spapr_allocate_lsi(0, &phb->lsi_table[i].dt_irq)) {
+            fprintf(stderr, "Failed to allocate LSI IRQ pin %u\n", i);
             return -1;
         }
-
-        phb->lsi_table[i].dt_irq = num;
-        phb->lsi_table[i].qirq = qirq;
     }
 
     return 0;
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index dd66f4b..11c3ee1 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -41,7 +41,6 @@ typedef struct sPAPRPHBState {
 
     struct {
         uint32_t dt_irq;
-        qemu_irq qirq;
     } lsi_table[PCI_NUM_PINS];
 
     QLIST_ENTRY(sPAPRPHBState) list;
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] pseries: added allocator for a block of IRQs
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: removed cached qemu_irq from PCI host bus Alexey Kardashevskiy
@ 2012-07-10 13:46   ` Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: enable debugging with disabled emulated PCI bus Alexey Kardashevskiy
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, qemu-devel, Alexander Graf, qemu-ppc, David Gibson

The patch adds a simple helper which allocates a consecutive sequence
of IRQs calling spapr_allocate_irq for each and checks that allocated
IRQs go consequently.

The patch is required for upcoming support of MSI/MSIX on POWER.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/spapr.c |   20 ++++++++++++++++++++
 hw/spapr.h |    1 +
 2 files changed, 21 insertions(+)

diff --git a/hw/spapr.c b/hw/spapr.c
index 6a9a7ca..f47c109 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -113,6 +113,26 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
     return qirq;
 }
 
+/* Allocate block of consequtive IRQs, returns a number of the first */
+int spapr_allocate_irq_block(uint32_t num, enum xics_irq_type type)
+{
+    int i, ret;
+    uint32_t irq = -1;
+
+    for (i = 0; i < num; ++i) {
+        if (!spapr_allocate_irq(0, &irq, type)) {
+            return -1;
+        }
+        if (0 == i) {
+            ret = irq;
+        }
+        if (ret + i != irq) {
+            return -1;
+        }
+    }
+    return ret;
+}
+
 static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
 {
     int ret = 0, offset;
diff --git a/hw/spapr.h b/hw/spapr.h
index d0c1749..4a3520f 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -289,6 +289,7 @@ target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
 
 qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
                             enum xics_irq_type type);
+int spapr_allocate_irq_block(uint32_t num, enum xics_irq_type type);
 
 static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num)
 {
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] pseries pci: enable debugging with disabled emulated PCI bus
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: removed cached qemu_irq from PCI host bus Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries: added allocator for a block of IRQs Alexey Kardashevskiy
@ 2012-07-10 13:46   ` Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries dma: DMA window params added to PHB and DT population changed Alexey Kardashevskiy
  4 siblings, 0 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, qemu-devel, Alexander Graf, qemu-ppc, David Gibson

Sometime when debugging PCI buses other than default emulated bus
it helps to disable emulated PCI. To disable it by commenting out
spapr_create_phb(SPAPR_PCI_BUID) call, this patch is submitted.

The patch does 2 things:
1. adds a check to init the emulated VGA only if the emulated PCI
bus has been created.

2. moves RTAS PCI config space access hooks out of the emulated
PCI bus init code.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/spapr.c     |    4 +++-
 hw/spapr_pci.c |   13 ++++++++-----
 hw/spapr_pci.h |    2 ++
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/hw/spapr.c b/hw/spapr.c
index f47c109..af3f479 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -764,6 +764,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* Set up PCI */
+    pci_common_init();
     spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID,
                      SPAPR_PCI_MEM_WIN_ADDR,
                      SPAPR_PCI_MEM_WIN_SIZE,
@@ -788,7 +789,8 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     }
 
     /* Graphics */
-    if (spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) {
+    if (QLIST_FIRST(&spapr->phbs) &&
+        spapr_vga_init(QLIST_FIRST(&spapr->phbs)->host_state.bus)) {
         spapr_has_graphics = 1;
         usb_enabled = 1;
     }
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 1318390..7a17d54 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -357,11 +357,6 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
 
     sdc->init = spapr_phb_init;
     dc->props = spapr_phb_properties;
-
-    spapr_rtas_register("read-pci-config", rtas_read_pci_config);
-    spapr_rtas_register("write-pci-config", rtas_write_pci_config);
-    spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
-    spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
 }
 
 static TypeInfo spapr_phb_info = {
@@ -486,6 +481,14 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
     return 0;
 }
 
+void pci_common_init(void)
+{
+    spapr_rtas_register("read-pci-config", rtas_read_pci_config);
+    spapr_rtas_register("write-pci-config", rtas_write_pci_config);
+    spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
+    spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
+}
+
 static void register_types(void)
 {
     type_register_static(&spapr_phb_info);
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 11c3ee1..05447b4 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -58,4 +58,6 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
                           uint32_t xics_phandle,
                           void *fdt);
 
+void pci_common_init(void);
+
 #endif /* __HW_SPAPR_PCI_H__ */
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
                     ` (2 preceding siblings ...)
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: enable debugging with disabled emulated PCI bus Alexey Kardashevskiy
@ 2012-07-10 13:46   ` Alexey Kardashevskiy
  2012-07-13  8:04     ` Alexey Kardashevskiy
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries dma: DMA window params added to PHB and DT population changed Alexey Kardashevskiy
  4 siblings, 1 reply; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, Jan Kiszka, qemu-devel, Alexander Graf,
	qemu-ppc, David Gibson

Normally when the host driver gets called via interrupt, it disables IRQ
first, then handles it and enables back. In the case of PCI pass through,
the actual handling is done by the guest so the host driver needs to know
when to enable IRQ back.

The patch introduces add/remove callback API and EOI initialization for
the XICS interrupt controller.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/xics.c |   18 ++++++++++++++++++
 hw/xics.h |    5 +++++
 2 files changed, 23 insertions(+)

diff --git a/hw/xics.c b/hw/xics.c
index 668a0d6..de7833e 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -170,6 +170,7 @@ struct ics_irq_state {
     int sent:1;
     int rejected:1;
     int masked_pending:1;
+    NotifierList eoi_notifier;
 };
 
 struct ics_state {
@@ -309,6 +310,8 @@ static void ics_eoi(struct ics_state *ics, int nr)
     if (irq->type == XICS_LSI) {
         irq->sent = 0;
     }
+
+    notifier_list_notify(&irq->eoi_notifier, NULL);
 }
 
 /*
@@ -536,6 +539,7 @@ struct icp_state *xics_system_init(int nr_irqs)
     for (i = 0; i < nr_irqs; i++) {
         ics->irqs[i].priority = 0xff;
         ics->irqs[i].saved_priority = 0xff;
+        notifier_list_init(&ics->irqs[i].eoi_notifier);
     }
 
     ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
@@ -552,3 +556,17 @@ struct icp_state *xics_system_init(int nr_irqs)
 
     return icp;
 }
+
+void xics_add_eoi_notifier(Notifier *notify, uint32_t srcno)
+{
+    struct ics_state *ics = spapr->icp->ics;
+    struct ics_irq_state *irq = &ics->irqs[srcno - ics->offset];
+
+    notifier_list_add(&irq->eoi_notifier, notify);
+}
+
+void xics_remove_eoi_notifier(Notifier *notify)
+{
+    notifier_remove(notify);
+}
+
diff --git a/hw/xics.h b/hw/xics.h
index 2080159..762243c 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -27,6 +27,8 @@
 #if !defined(__XICS_H__)
 #define __XICS_H__
 
+#include "notify.h"
+
 #define XICS_IPI        0x2
 
 struct icp_state;
@@ -41,4 +43,7 @@ qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
 
 struct icp_state *xics_system_init(int nr_irqs);
 
+void xics_add_eoi_notifier(Notifier *notify, uint32_t srcno);
+void xics_remove_eoi_notifier(Notifier *notify);
+
 #endif /* __XICS_H__ */
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [Qemu-devel] [PATCH] pseries dma: DMA window params added to PHB and DT population changed
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
                     ` (3 preceding siblings ...)
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers Alexey Kardashevskiy
@ 2012-07-10 13:46   ` Alexey Kardashevskiy
  4 siblings, 0 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-10 13:46 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, qemu-devel, Alexander Graf, qemu-ppc, David Gibson

Previously the only PCI bus supported was the emulated PCI bus with
fixed DMA window with start at 0 and size 1GB. As we are going to support
PCI pass through which DMA window properties are set by the host
kernel, we have to support DMA windows with parameters other than default.

This patch adds:

1. DMA window properties to sPAPRPHBState: LIOBN (bus id), start,
size of the window.

2. An additional function spapr_dma_dt() to populate DMA window
properties in the device tree which simply accepts all the parameters
and does not try to guess what kind of IOMMU is given to it.
The original spapr_dma_dt() is renamed to spapr_tcet_dma_dt().

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 hw/spapr.h       |    4 +++-
 hw/spapr_iommu.c |   58 ++++++++++++++++++++++++++++++++++--------------------
 hw/spapr_pci.c   |   11 +++++++----
 hw/spapr_pci.h   |    6 ++++++
 hw/spapr_vio.c   |    2 +-
 5 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/hw/spapr.h b/hw/spapr.h
index 4a3520f..b37f337 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -336,6 +336,8 @@ void spapr_iommu_init(void);
 DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size);
 void spapr_tce_free(DMAContext *dma);
 int spapr_dma_dt(void *fdt, int node_off, const char *propname,
-                 DMAContext *dma);
+                 uint32_t liobn, uint64_t window, uint32_t size);
+int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
+                      DMAContext *dma);
 
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
index 3021bfe..50c288d 100644
--- a/hw/spapr_iommu.c
+++ b/hw/spapr_iommu.c
@@ -221,31 +221,47 @@ void spapr_iommu_init(void)
 }
 
 int spapr_dma_dt(void *fdt, int node_off, const char *propname,
-                 DMAContext *dma)
+                 uint32_t liobn, uint64_t window, uint32_t size)
 {
-    if (dma) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-        uint32_t dma_prop[] = {cpu_to_be32(tcet->liobn),
-                               0, 0,
-                               0, cpu_to_be32(tcet->window_size)};
-        int ret;
-
-        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
-        if (ret < 0) {
-            return ret;
-        }
+    uint32_t dma_prop[5];
+    int ret;
 
-        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
-        if (ret < 0) {
-            return ret;
-        }
+    dma_prop[0] = cpu_to_be32(liobn);
+    dma_prop[1] = cpu_to_be32(window >> 32);
+    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
+    dma_prop[3] = 0; /* window size is 32 bits */
+    dma_prop[4] = cpu_to_be32(size);
 
-        ret = fdt_setprop(fdt, node_off, propname, dma_prop,
-                          sizeof(dma_prop));
-        if (ret < 0) {
-            return ret;
-        }
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop));
+    if (ret < 0) {
+        return ret;
     }
 
     return 0;
 }
+
+int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
+                      DMAContext *iommu)
+{
+    if (!iommu) {
+        return 0;
+    }
+
+    if (iommu->translate == spapr_tce_translate) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
+        return spapr_dma_dt(fdt, node_off, propname,
+                tcet->liobn, 0, tcet->window_size);
+    }
+
+    return -1;
+}
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 7a17d54..f98cd7e 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -282,7 +282,6 @@ static int spapr_phb_init(SysBusDevice *s)
     char *namebuf;
     int i;
     PCIBus *bus;
-    uint32_t liobn;
 
     phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
     namebuf = alloca(strlen(phb->dtbusname) + 32);
@@ -323,8 +322,10 @@ static int spapr_phb_init(SysBusDevice *s)
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
     phb->host_state.bus = bus;
 
-    liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
-    phb->dma = spapr_tce_new_dma_context(liobn, 0x40000000);
+    phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
+    phb->dma_window_start = 0;
+    phb->dma_window_size = 0x40000000;
+    phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size);
     pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
 
     QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
@@ -476,7 +477,9 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
     _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
                      sizeof(interrupt_map)));
 
-    spapr_dma_dt(fdt, bus_off, "ibm,dma-window", phb->dma);
+    spapr_dma_dt(fdt, bus_off, "ibm,dma-window",
+                 phb->dma_liobn, phb->dma_window_start,
+                 phb->dma_window_size);
 
     return 0;
 }
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 05447b4..e54809a 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -37,6 +37,12 @@ typedef struct sPAPRPHBState {
     MemoryRegion memspace, iospace;
     target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size;
     MemoryRegion memwindow, iowindow;
+    target_phys_addr_t msi_win_addr;
+    MemoryRegion msiwindow;
+
+    uint32_t dma_liobn;
+    uint64_t dma_window_start;
+    uint64_t dma_window_size;
     DMAContext *dma;
 
     struct {
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 05b5503..c734eb4 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -142,7 +142,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
         }
     }
 
-    ret = spapr_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
+    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
     if (ret < 0) {
         return ret;
     }
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers
  2012-07-10 13:46   ` [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers Alexey Kardashevskiy
@ 2012-07-13  8:04     ` Alexey Kardashevskiy
  0 siblings, 0 replies; 206+ messages in thread
From: Alexey Kardashevskiy @ 2012-07-13  8:04 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: qemu-devel, Jan Kiszka, qemu-ppc, Alexander Graf, David Gibson

Already outdated :)

On 10/07/12 23:46, Alexey Kardashevskiy wrote:
> Normally when the host driver gets called via interrupt, it disables IRQ
> first, then handles it and enables back. In the case of PCI pass through,
> the actual handling is done by the guest so the host driver needs to know
> when to enable IRQ back.
> 
> The patch introduces add/remove callback API and EOI initialization for
> the XICS interrupt controller.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
>  hw/xics.c |   18 ++++++++++++++++++
>  hw/xics.h |    5 +++++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/hw/xics.c b/hw/xics.c
> index 668a0d6..de7833e 100644
> --- a/hw/xics.c
> +++ b/hw/xics.c
> @@ -170,6 +170,7 @@ struct ics_irq_state {
>      int sent:1;
>      int rejected:1;
>      int masked_pending:1;
> +    NotifierList eoi_notifier;
>  };
>  
>  struct ics_state {
> @@ -309,6 +310,8 @@ static void ics_eoi(struct ics_state *ics, int nr)
>      if (irq->type == XICS_LSI) {
>          irq->sent = 0;
>      }
> +
> +    notifier_list_notify(&irq->eoi_notifier, NULL);
>  }
>  
>  /*
> @@ -536,6 +539,7 @@ struct icp_state *xics_system_init(int nr_irqs)
>      for (i = 0; i < nr_irqs; i++) {
>          ics->irqs[i].priority = 0xff;
>          ics->irqs[i].saved_priority = 0xff;
> +        notifier_list_init(&ics->irqs[i].eoi_notifier);
>      }
>  
>      ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
> @@ -552,3 +556,17 @@ struct icp_state *xics_system_init(int nr_irqs)
>  
>      return icp;
>  }
> +
> +void xics_add_eoi_notifier(Notifier *notify, uint32_t srcno)
> +{
> +    struct ics_state *ics = spapr->icp->ics;
> +    struct ics_irq_state *irq = &ics->irqs[srcno - ics->offset];
> +
> +    notifier_list_add(&irq->eoi_notifier, notify);
> +}
> +
> +void xics_remove_eoi_notifier(Notifier *notify)
> +{
> +    notifier_remove(notify);
> +}
> +
> diff --git a/hw/xics.h b/hw/xics.h
> index 2080159..762243c 100644
> --- a/hw/xics.h
> +++ b/hw/xics.h
> @@ -27,6 +27,8 @@
>  #if !defined(__XICS_H__)
>  #define __XICS_H__
>  
> +#include "notify.h"
> +
>  #define XICS_IPI        0x2
>  
>  struct icp_state;
> @@ -41,4 +43,7 @@ qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
>  
>  struct icp_state *xics_system_init(int nr_irqs);
>  
> +void xics_add_eoi_notifier(Notifier *notify, uint32_t srcno);
> +void xics_remove_eoi_notifier(Notifier *notify);
> +
>  #endif /* __XICS_H__ */
> 


-- 
Alexey

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH] fixed a macro coding style issue
       [not found] <no>
                   ` (31 preceding siblings ...)
  2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
@ 2012-07-25  5:20 ` Baodong Chen
  2012-07-25  5:27   ` Venu Byravarasu
  2012-07-25  5:37   ` Dmitry Torokhov
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
                   ` (5 subsequent siblings)
  38 siblings, 2 replies; 206+ messages in thread
From: Baodong Chen @ 2012-07-25  5:20 UTC (permalink / raw)
  To: dmitry.torokhov; +Cc: linux-input, linux-kernel, Baodong Chen

Fixed a coding style issue in driver/input/input.c

Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
---
 drivers/input/input.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8921c61..c96e983 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
 EXPORT_SYMBOL(input_set_keycode);
 
 #define MATCH_BIT(bit, max) \
+	do { \
 		for (i = 0; i < BITS_TO_LONGS(max); i++) \
 			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
 				break; \
-		if (i != BITS_TO_LONGS(max)) \
-			continue;
+			if (i != BITS_TO_LONGS(max)) \
+				continue; \
+	} while (0)
 
 static const struct input_device_id *input_match_device(struct input_handler *handler,
 							struct input_dev *dev)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* RE: [PATCH] fixed a macro coding style issue
  2012-07-25  5:20 ` [PATCH] fixed a macro coding style issue Baodong Chen
@ 2012-07-25  5:27   ` Venu Byravarasu
  2012-07-25  5:37   ` Dmitry Torokhov
  1 sibling, 0 replies; 206+ messages in thread
From: Venu Byravarasu @ 2012-07-25  5:27 UTC (permalink / raw)
  To: Baodong Chen, dmitry.torokhov; +Cc: linux-input, linux-kernel

> -----Original Message-----
> From: linux-kernel-owner@vger.kernel.org [mailto:linux-kernel-
> owner@vger.kernel.org] On Behalf Of Baodong Chen
> Sent: Wednesday, July 25, 2012 10:51 AM
> To: dmitry.torokhov@gmail.com
> Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; Baodong
> Chen
> Subject: [PATCH] fixed a macro coding style issue
> 
> Fixed a coding style issue in driver/input/input.c
> 
> Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
> ---
>  drivers/input/input.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 8921c61..c96e983 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
>  EXPORT_SYMBOL(input_set_keycode);
> 
>  #define MATCH_BIT(bit, max) \
> +	do { \
>  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
>  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
>  				break; \
> -		if (i != BITS_TO_LONGS(max)) \
> -			continue;
> +			if (i != BITS_TO_LONGS(max)) \
> +				continue; \

What is the need for extra indentation here?

> +	} while (0)
> 
>  static const struct input_device_id *input_match_device(struct
> input_handler *handler,
>  							struct input_dev
> *dev)
> --
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] fixed a macro coding style issue
  2012-07-25  5:20 ` [PATCH] fixed a macro coding style issue Baodong Chen
  2012-07-25  5:27   ` Venu Byravarasu
@ 2012-07-25  5:37   ` Dmitry Torokhov
  2012-07-25  6:09     ` Baodong Chen
  2012-07-25  6:15     ` Al Viro
  1 sibling, 2 replies; 206+ messages in thread
From: Dmitry Torokhov @ 2012-07-25  5:37 UTC (permalink / raw)
  To: Baodong Chen; +Cc: linux-input, linux-kernel

On Wed, Jul 25, 2012 at 01:20:56PM +0800, Baodong Chen wrote:
> Fixed a coding style issue in driver/input/input.c
> 
> Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
> ---
>  drivers/input/input.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index 8921c61..c96e983 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
>  EXPORT_SYMBOL(input_set_keycode);
>  
>  #define MATCH_BIT(bit, max) \
> +	do { \
>  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
>  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
>  				break; \
> -		if (i != BITS_TO_LONGS(max)) \
> -			continue;
> +			if (i != BITS_TO_LONGS(max)) \
> +				continue; \
> +	} while (0)

This changes semantics. While current implementation of MATCH_BIT might
not be great style, it is not supposed to be used outside of
input_match_device(), and the replacement is completely broken.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] fixed a macro coding style issue
  2012-07-25  5:37   ` Dmitry Torokhov
@ 2012-07-25  6:09     ` Baodong Chen
  2012-07-25  6:15     ` Al Viro
  1 sibling, 0 replies; 206+ messages in thread
From: Baodong Chen @ 2012-07-25  6:09 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, linux-kernel

this patch definitely changes semantics.
so please discard it, sorry about that!

On Wed, Jul 25, 2012 at 1:37 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Wed, Jul 25, 2012 at 01:20:56PM +0800, Baodong Chen wrote:
>> Fixed a coding style issue in driver/input/input.c
>>
>> Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
>> ---
>>  drivers/input/input.c |    6 ++++--
>>  1 files changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/input/input.c b/drivers/input/input.c
>> index 8921c61..c96e983 100644
>> --- a/drivers/input/input.c
>> +++ b/drivers/input/input.c
>> @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
>>  EXPORT_SYMBOL(input_set_keycode);
>>
>>  #define MATCH_BIT(bit, max) \
>> +     do { \
>>               for (i = 0; i < BITS_TO_LONGS(max); i++) \
>>                       if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
>>                               break; \
>> -             if (i != BITS_TO_LONGS(max)) \
>> -                     continue;
>> +                     if (i != BITS_TO_LONGS(max)) \
>> +                             continue; \
>> +     } while (0)
>
> This changes semantics. While current implementation of MATCH_BIT might
> not be great style, it is not supposed to be used outside of
> input_match_device(), and the replacement is completely broken.
>
> Thanks.
>
> --
> Dmitry

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] fixed a macro coding style issue
  2012-07-25  5:37   ` Dmitry Torokhov
  2012-07-25  6:09     ` Baodong Chen
@ 2012-07-25  6:15     ` Al Viro
  2012-07-25  6:36       ` Dmitry Torokhov
  1 sibling, 1 reply; 206+ messages in thread
From: Al Viro @ 2012-07-25  6:15 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Baodong Chen, linux-input, linux-kernel

On Tue, Jul 24, 2012 at 10:37:55PM -0700, Dmitry Torokhov wrote:
> On Wed, Jul 25, 2012 at 01:20:56PM +0800, Baodong Chen wrote:
> > Fixed a coding style issue in driver/input/input.c
> > 
> > Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
> > ---
> >  drivers/input/input.c |    6 ++++--
> >  1 files changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/input/input.c b/drivers/input/input.c
> > index 8921c61..c96e983 100644
> > --- a/drivers/input/input.c
> > +++ b/drivers/input/input.c
> > @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
> >  EXPORT_SYMBOL(input_set_keycode);
> >  
> >  #define MATCH_BIT(bit, max) \
> > +	do { \
> >  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
> >  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
> >  				break; \
> > -		if (i != BITS_TO_LONGS(max)) \
> > -			continue;
> > +			if (i != BITS_TO_LONGS(max)) \
> > +				continue; \
> > +	} while (0)
> 
> This changes semantics. While current implementation of MATCH_BIT might
> not be great style, it is not supposed to be used outside of
> input_match_device(), and the replacement is completely broken.

Replacement is certainly completely broken, but "might not be great style"
is quite an understatement.  Everything else aside, it's too obfuscated
and ugly for anything outside of IOCCC and too verbose for IOCCC.

Damnit, at least turn that into
static inline int is_subset(unsigned long *bitmap1, unsigned long *bitmap2, size_t bits)
{
	int i;
	for (i = BITS_TO_LONGS(bits); i; bitmap1++, bitmap2++, i--)
		if ((*bitmap1 & *bitmap2) != *bitmap1)
			return 0;
	return 1;
}
and just before your loop
/* ignore ones that don't have bits required by id */
#define MATCH_BIT(array, bits) if (!is_subset(id->array, dev->array, bits)) continue;
with #undef MATCH_BIT right after the loop, to make it damn clean that it's local.
And frankly, I'd consider expanding that variant and killing the macro off.
Macros that affect control flow are vile and actively confusing for reader.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] fixed a macro coding style issue
  2012-07-25  6:15     ` Al Viro
@ 2012-07-25  6:36       ` Dmitry Torokhov
  2012-07-31  7:27         ` Dmitry Torokhov
  0 siblings, 1 reply; 206+ messages in thread
From: Dmitry Torokhov @ 2012-07-25  6:36 UTC (permalink / raw)
  To: Al Viro; +Cc: Baodong Chen, linux-input, linux-kernel

On Wed, Jul 25, 2012 at 07:15:12AM +0100, Al Viro wrote:
> On Tue, Jul 24, 2012 at 10:37:55PM -0700, Dmitry Torokhov wrote:
> > On Wed, Jul 25, 2012 at 01:20:56PM +0800, Baodong Chen wrote:
> > > Fixed a coding style issue in driver/input/input.c
> > > 
> > > Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
> > > ---
> > >  drivers/input/input.c |    6 ++++--
> > >  1 files changed, 4 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/input/input.c b/drivers/input/input.c
> > > index 8921c61..c96e983 100644
> > > --- a/drivers/input/input.c
> > > +++ b/drivers/input/input.c
> > > @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
> > >  EXPORT_SYMBOL(input_set_keycode);
> > >  
> > >  #define MATCH_BIT(bit, max) \
> > > +	do { \
> > >  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
> > >  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
> > >  				break; \
> > > -		if (i != BITS_TO_LONGS(max)) \
> > > -			continue;
> > > +			if (i != BITS_TO_LONGS(max)) \
> > > +				continue; \
> > > +	} while (0)
> > 
> > This changes semantics. While current implementation of MATCH_BIT might
> > not be great style, it is not supposed to be used outside of
> > input_match_device(), and the replacement is completely broken.
> 
> Replacement is certainly completely broken, but "might not be great style"
> is quite an understatement.  Everything else aside, it's too obfuscated
> and ugly for anything outside of IOCCC and too verbose for IOCCC.
> 
> Damnit, at least turn that into
> static inline int is_subset(unsigned long *bitmap1, unsigned long *bitmap2, size_t bits)
> {
> 	int i;
> 	for (i = BITS_TO_LONGS(bits); i; bitmap1++, bitmap2++, i--)
> 		if ((*bitmap1 & *bitmap2) != *bitmap1)
> 			return 0;
> 	return 1;
> }
> and just before your loop
> /* ignore ones that don't have bits required by id */
> #define MATCH_BIT(array, bits) if (!is_subset(id->array, dev->array, bits)) continue;

Hmm, we already have bitmap_subset(), I think we can simply use it.

> with #undef MATCH_BIT right after the loop, to make it damn clean that it's local.
> And frankly, I'd consider expanding that variant and killing the macro off.
> Macros that affect control flow are vile and actively confusing for reader.

I agree. In my defense it is quite old code...

-- 
Dmitry

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH] fixed a macro coding style issue
  2012-07-25  6:36       ` Dmitry Torokhov
@ 2012-07-31  7:27         ` Dmitry Torokhov
  0 siblings, 0 replies; 206+ messages in thread
From: Dmitry Torokhov @ 2012-07-31  7:27 UTC (permalink / raw)
  To: Al Viro; +Cc: Baodong Chen, linux-input, linux-kernel

On Tue, Jul 24, 2012 at 11:36:24PM -0700, Dmitry Torokhov wrote:
> On Wed, Jul 25, 2012 at 07:15:12AM +0100, Al Viro wrote:
> > On Tue, Jul 24, 2012 at 10:37:55PM -0700, Dmitry Torokhov wrote:
> > > On Wed, Jul 25, 2012 at 01:20:56PM +0800, Baodong Chen wrote:
> > > > Fixed a coding style issue in driver/input/input.c
> > > > 
> > > > Signed-off-by: Baodong Chen <chenbdchenbd@gmail.com>
> > > > ---
> > > >  drivers/input/input.c |    6 ++++--
> > > >  1 files changed, 4 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/input/input.c b/drivers/input/input.c
> > > > index 8921c61..c96e983 100644
> > > > --- a/drivers/input/input.c
> > > > +++ b/drivers/input/input.c
> > > > @@ -845,11 +845,13 @@ int input_set_keycode(struct input_dev *dev,
> > > >  EXPORT_SYMBOL(input_set_keycode);
> > > >  
> > > >  #define MATCH_BIT(bit, max) \
> > > > +	do { \
> > > >  		for (i = 0; i < BITS_TO_LONGS(max); i++) \
> > > >  			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
> > > >  				break; \
> > > > -		if (i != BITS_TO_LONGS(max)) \
> > > > -			continue;
> > > > +			if (i != BITS_TO_LONGS(max)) \
> > > > +				continue; \
> > > > +	} while (0)
> > > 
> > > This changes semantics. While current implementation of MATCH_BIT might
> > > not be great style, it is not supposed to be used outside of
> > > input_match_device(), and the replacement is completely broken.
> > 
> > Replacement is certainly completely broken, but "might not be great style"
> > is quite an understatement.  Everything else aside, it's too obfuscated
> > and ugly for anything outside of IOCCC and too verbose for IOCCC.
> > 
> > Damnit, at least turn that into
> > static inline int is_subset(unsigned long *bitmap1, unsigned long *bitmap2, size_t bits)
> > {
> > 	int i;
> > 	for (i = BITS_TO_LONGS(bits); i; bitmap1++, bitmap2++, i--)
> > 		if ((*bitmap1 & *bitmap2) != *bitmap1)
> > 			return 0;
> > 	return 1;
> > }
> > and just before your loop
> > /* ignore ones that don't have bits required by id */
> > #define MATCH_BIT(array, bits) if (!is_subset(id->array, dev->array, bits)) continue;
> 
> Hmm, we already have bitmap_subset(), I think we can simply use it.
> 
> > with #undef MATCH_BIT right after the loop, to make it damn clean that it's local.
> > And frankly, I'd consider expanding that variant and killing the macro off.
> > Macros that affect control flow are vile and actively confusing for reader.
> 
> I agree. In my defense it is quite old code...

So how about the patch below?

-- 
Dmitry

Input: get rid of MATCH_BIT() macro

From: Dmitry Torokhov <dmitry.torokhov@gmail.com>

MATCH_BIT() is ugly and stupid, we have much nicer bitmap_subset() which
does the same and does not hide control flow.

Reported-by: Baodong Chen <chenbdchenbd@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---

 drivers/input/input.c |   43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)


diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8921c61..768e46b 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -844,18 +844,10 @@ int input_set_keycode(struct input_dev *dev,
 }
 EXPORT_SYMBOL(input_set_keycode);
 
-#define MATCH_BIT(bit, max) \
-		for (i = 0; i < BITS_TO_LONGS(max); i++) \
-			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
-				break; \
-		if (i != BITS_TO_LONGS(max)) \
-			continue;
-
 static const struct input_device_id *input_match_device(struct input_handler *handler,
 							struct input_dev *dev)
 {
 	const struct input_device_id *id;
-	int i;
 
 	for (id = handler->id_table; id->flags || id->driver_info; id++) {
 
@@ -875,15 +867,32 @@ static const struct input_device_id *input_match_device(struct input_handler *ha
 			if (id->version != dev->id.version)
 				continue;
 
-		MATCH_BIT(evbit,  EV_MAX);
-		MATCH_BIT(keybit, KEY_MAX);
-		MATCH_BIT(relbit, REL_MAX);
-		MATCH_BIT(absbit, ABS_MAX);
-		MATCH_BIT(mscbit, MSC_MAX);
-		MATCH_BIT(ledbit, LED_MAX);
-		MATCH_BIT(sndbit, SND_MAX);
-		MATCH_BIT(ffbit,  FF_MAX);
-		MATCH_BIT(swbit,  SW_MAX);
+		if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))
+			continue;
+
+		if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
+			continue;
+
+		if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
+			continue;
+
+		if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
+			continue;
+
+		if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
+			continue;
+
+		if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
+			continue;
+
+		if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
+			continue;
+
+		if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
+			continue;
+
+		if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
+			continue;
 
 		if (!handler->match || handler->match(handler, dev))
 			return id;

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted()
       [not found] <no>
                   ` (32 preceding siblings ...)
  2012-07-25  5:20 ` [PATCH] fixed a macro coding style issue Baodong Chen
@ 2012-09-27 12:51 ` Yan Hong
  2012-09-27 12:51   ` [PATCH 2/8] fs/namespace.c: remove unused macro MNT_WRITER_UNDERFLOW_LIMIT Yan Hong
                     ` (6 more replies)
  2013-01-07 18:11 ` [PATCH] Staging: android: fixed const coding style issue in binder.c Patrik Karlin
                   ` (4 subsequent siblings)
  38 siblings, 7 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

In fs/namespace.c, we verify whether a path is a mountpoint by
comparing path->dentry and path->mnt->mnt_root. Introduce
path_unmounted() to make code more readable.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/namespace.c |   19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 4d31f73..3fdc239 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1234,6 +1234,11 @@ static int do_umount(struct mount *mnt, int flags)
 	return retval;
 }
 
+static inline bool path_unmounted(struct path *path)
+{
+	return path->dentry != path->mnt->mnt_root;
+}
+
 /*
  * Now umount can handle mount points as well as block devices.
  * This is important for filesystems which use unnamed block devices.
@@ -1260,7 +1265,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 		goto out;
 	mnt = real_mount(path.mnt);
 	retval = -EINVAL;
-	if (path.dentry != path.mnt->mnt_root)
+	if (path_unmounted(&path))
 		goto dput_and_out;
 	if (!check_mnt(mnt))
 		goto dput_and_out;
@@ -1613,7 +1618,7 @@ static int do_change_type(struct path *path, int flag)
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (path->dentry != path->mnt->mnt_root)
+	if (path_unmounted(path))
 		return -EINVAL;
 
 	type = flags_to_propagation_type(flag);
@@ -1727,7 +1732,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	if (!check_mnt(mnt))
 		return -EINVAL;
 
-	if (path->dentry != path->mnt->mnt_root)
+	if (path_unmounted(path))
 		return -EINVAL;
 
 	err = security_sb_remount(sb, data);
@@ -1793,7 +1798,7 @@ static int do_move_mount(struct path *path, char *old_name)
 		goto out1;
 
 	err = -EINVAL;
-	if (old_path.dentry != old_path.mnt->mnt_root)
+	if (path_unmounted(&old_path))
 		goto out1;
 
 	if (!mnt_has_parent(old))
@@ -1892,7 +1897,7 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 	/* Refuse the same filesystem on the same mount point */
 	err = -EBUSY;
 	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
-	    path->mnt->mnt_root == path->dentry)
+	    !path_unmounted(path))
 		goto unlock;
 
 	err = -EINVAL;
@@ -2534,11 +2539,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	    old.mnt == root.mnt)
 		goto out4; /* loop, on the same file system  */
 	error = -EINVAL;
-	if (root.mnt->mnt_root != root.dentry)
+	if (path_unmounted(&root))
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(root_mnt))
 		goto out4; /* not attached */
-	if (new.mnt->mnt_root != new.dentry)
+	if (path_unmounted(&new))
 		goto out4; /* not a mountpoint */
 	if (!mnt_has_parent(new_mnt))
 		goto out4; /* not attached */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/8] fs/namespace.c: remove unused macro MNT_WRITER_UNDERFLOW_LIMIT
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 3/8] fs/namespace.c: trivial code clean Yan Hong
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

Its users have gone.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/namespace.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index 3fdc239..dd969f8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -59,7 +59,6 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 	return tmp & (HASH_SIZE - 1);
 }
 
-#define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16)
 
 /*
  * allocation is serialized by namespace_sem, but we need the spinlock to
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 3/8] fs/namespace.c: trivial code clean
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
  2012-09-27 12:51   ` [PATCH 2/8] fs/namespace.c: remove unused macro MNT_WRITER_UNDERFLOW_LIMIT Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 4/8] fs/namespace.c: check permission early in sys_[u]mount Yan Hong
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel


Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/namespace.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index dd969f8..bbe9014 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -763,7 +763,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
 
 	mnt->mnt.mnt_root = root;
 	mnt->mnt.mnt_sb = root->d_sb;
-	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+	mnt->mnt_mountpoint = root;
 	mnt->mnt_parent = mnt;
 	br_write_lock(&vfsmount_lock);
 	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
@@ -798,7 +798,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	atomic_inc(&sb->s_active);
 	mnt->mnt.mnt_sb = sb;
 	mnt->mnt.mnt_root = dget(root);
-	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+	mnt->mnt_mountpoint = root;
 	mnt->mnt_parent = mnt;
 	br_write_lock(&vfsmount_lock);
 	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 4/8] fs/namespace.c: check permission early in sys_[u]mount
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
  2012-09-27 12:51   ` [PATCH 2/8] fs/namespace.c: remove unused macro MNT_WRITER_UNDERFLOW_LIMIT Yan Hong
  2012-09-27 12:51   ` [PATCH 3/8] fs/namespace.c: trivial code clean Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 5/8] fs/namei.c: introduce macro AT_FDINV Yan Hong
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

We have several branches in sys_mount, each of them will check
CAP_SYS_ADMIN capability seperately. Do this check at the beginning
of sys_mount.

Also check permission as early as possible in sys_umount.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/namespace.c |   26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index bbe9014..ca2b6e9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1256,6 +1256,9 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
 		return -EINVAL;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	if (!(flags & UMOUNT_NOFOLLOW))
 		lookup_flags |= LOOKUP_FOLLOW;
 
@@ -1269,10 +1272,6 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 	if (!check_mnt(mnt))
 		goto dput_and_out;
 
-	retval = -EPERM;
-	if (!capable(CAP_SYS_ADMIN))
-		goto dput_and_out;
-
 	retval = do_umount(mnt, flags);
 dput_and_out:
 	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
@@ -1296,9 +1295,7 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
 
 static int mount_is_safe(struct path *path)
 {
-	if (capable(CAP_SYS_ADMIN))
-		return 0;
-	return -EPERM;
+	return 0;
 #ifdef notyet
 	if (S_ISLNK(path->dentry->d_inode->i_mode))
 		return -EPERM;
@@ -1614,9 +1611,6 @@ static int do_change_type(struct path *path, int flag)
 	int type;
 	int err = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (path_unmounted(path))
 		return -EINVAL;
 
@@ -1725,9 +1719,6 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	struct super_block *sb = path->mnt->mnt_sb;
 	struct mount *mnt = real_mount(path->mnt);
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	if (!check_mnt(mnt))
 		return -EINVAL;
 
@@ -1774,8 +1765,6 @@ static int do_move_mount(struct path *path, char *old_name)
 	struct mount *p;
 	struct mount *old;
 	int err = 0;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
 	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
@@ -1924,10 +1913,6 @@ static int do_new_mount(struct path *path, char *type, int flags,
 	if (!type)
 		return -EINVAL;
 
-	/* we need capabilities... */
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	mnt = do_kern_mount(type, flags, name, data);
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
@@ -2410,6 +2395,9 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
 	char *kernel_dev;
 	unsigned long data_page;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	ret = copy_mount_string(type, &kernel_type);
 	if (ret < 0)
 		goto out_type;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 5/8] fs/namei.c: introduce macro AT_FDINV
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
                     ` (2 preceding siblings ...)
  2012-09-27 12:51   ` [PATCH 4/8] fs/namespace.c: check permission early in sys_[u]mount Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 6/8] fs/inode.c: call alloc_inode() in new_inode() directly Yan Hong
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

File descriptor is irrelevent when LOOKUP_ROOT is set.
Introduce AT_FDINV to avoid using hard coded value or reusing
existing macro.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/namei.c            |   11 ++++++-----
 include/linux/fcntl.h |    2 ++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index c5b85b3..5ffd97d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2034,8 +2034,8 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
 	nd.root.dentry = dentry;
 	nd.root.mnt = mnt;
 	BUG_ON(flags & LOOKUP_PARENT);
-	/* the first argument of do_path_lookup() is ignored with LOOKUP_ROOT */
-	err = do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, &nd);
+
+	err = do_path_lookup(AT_FDINV, name, flags | LOOKUP_ROOT, &nd);
 	if (!err)
 		*path = nd.path;
 	return err;
@@ -2969,11 +2969,12 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 	if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
 		return ERR_PTR(-ELOOP);
 
-	file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
+	file = path_openat(AT_FDINV, name, &nd, op, flags | LOOKUP_RCU);
 	if (unlikely(file == ERR_PTR(-ECHILD)))
-		file = path_openat(-1, name, &nd, op, flags);
+		file = path_openat(AT_FDINV, name, &nd, op, flags);
 	if (unlikely(file == ERR_PTR(-ESTALE)))
-		file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
+		file = path_openat(AT_FDINV, name, &nd, op,
+						flags | LOOKUP_REVAL);
 	return file;
 }
 
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index f550f89..abd94fe 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -41,6 +41,8 @@
 #define AT_FDCWD		-100    /* Special value used to indicate
                                            openat should use the current
                                            working directory. */
+#define AT_FDINV		-200	/* Special value used when LOOKUP_ROOT
+					   is set. */
 #define AT_SYMLINK_NOFOLLOW	0x100   /* Do not follow symbolic links.  */
 #define AT_REMOVEDIR		0x200   /* Remove directory instead of
                                            unlinking file.  */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 6/8] fs/inode.c: call alloc_inode() in new_inode() directly
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
                     ` (3 preceding siblings ...)
  2012-09-27 12:51   ` [PATCH 5/8] fs/namei.c: introduce macro AT_FDINV Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 7/8] fs/inode.c: remove outstanding spin lock prefetch Yan Hong
  2012-09-27 12:51   ` [PATCH 8/8] vfs: misc comment clean Yan Hong
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

This saves us a list head initialization.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/inode.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index ac8d904..3a2cd41 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -921,9 +921,11 @@ struct inode *new_inode(struct super_block *sb)
 
 	spin_lock_prefetch(&inode_sb_list_lock);
 
-	inode = new_inode_pseudo(sb);
-	if (inode)
+	inode = alloc_inode(sb);
+	if (inode) {
+		inode->i_state = 0;
 		inode_sb_list_add(inode);
+	}
 	return inode;
 }
 EXPORT_SYMBOL(new_inode);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 7/8] fs/inode.c: remove outstanding spin lock prefetch
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
                     ` (4 preceding siblings ...)
  2012-09-27 12:51   ` [PATCH 6/8] fs/inode.c: call alloc_inode() in new_inode() directly Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  2012-09-27 12:51   ` [PATCH 8/8] vfs: misc comment clean Yan Hong
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

Do we have particular reason to do this here?

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/inode.c |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index 3a2cd41..e89d30c 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -14,7 +14,6 @@
 #include <linux/fsnotify.h>
 #include <linux/mount.h>
 #include <linux/posix_acl.h>
-#include <linux/prefetch.h>
 #include <linux/buffer_head.h> /* for inode_has_buffers */
 #include <linux/ratelimit.h>
 #include "internal.h"
@@ -919,8 +918,6 @@ struct inode *new_inode(struct super_block *sb)
 {
 	struct inode *inode;
 
-	spin_lock_prefetch(&inode_sb_list_lock);
-
 	inode = alloc_inode(sb);
 	if (inode) {
 		inode->i_state = 0;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 8/8] vfs: misc comment clean
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
                     ` (5 preceding siblings ...)
  2012-09-27 12:51   ` [PATCH 7/8] fs/inode.c: remove outstanding spin lock prefetch Yan Hong
@ 2012-09-27 12:51   ` Yan Hong
  6 siblings, 0 replies; 206+ messages in thread
From: Yan Hong @ 2012-09-27 12:51 UTC (permalink / raw)
  To: viro; +Cc: linux-fsdevel, linux-kernel

Mostly fix comments which reference inexist locks or parameters.

Signed-off-by: Yan Hong <clouds.yan@gmail.com>
---
 fs/dcache.c    |   12 ++++--------
 fs/inode.c     |    4 ++--
 fs/namei.c     |    2 +-
 fs/namespace.c |    9 +++------
 4 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index 8086636..2d97518 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -44,8 +44,6 @@
  * Usage:
  * dcache->d_inode->i_lock protects:
  *   - i_dentry, d_alias, d_inode of aliases
- * dcache_hash_bucket lock protects:
- *   - the dcache hash table
  * s_anon bl list spinlock protects:
  *   - the s_anon list (see __d_drop)
  * dcache_lru_lock protects:
@@ -64,7 +62,6 @@
  * dentry->d_inode->i_lock
  *   dentry->d_lock
  *     dcache_lru_lock
- *     dcache_hash_bucket lock
  *     s_anon lock
  *
  * If there is an ancestor relationship:
@@ -145,10 +142,9 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
 
 #include <asm/word-at-a-time.h>
 /*
- * NOTE! 'cs' and 'scount' come from a dentry, so it has a
- * aligned allocation for this particular component. We don't
- * strictly need the load_unaligned_zeropad() safety, but it
- * doesn't hurt either.
+ * NOTE! 'cs' comes from a dentry, so it has an aligned allocation
+ * for this particular component. We don't strictly need the
+ * load_unaligned_zeropad() safety, but it doesn't hurt either.
  *
  * In contrast, 'ct' and 'tcount' can be from a pathname, and do
  * need the careful unaligned handling.
@@ -304,7 +300,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 }
 
 /*
- * dentry_lru_(add|del|prune|move_tail) must be called with d_lock held.
+ * dentry_lru_(add|del|prune|move_list) must be called with d_lock held.
  */
 static void dentry_lru_add(struct dentry *dentry)
 {
diff --git a/fs/inode.c b/fs/inode.c
index e89d30c..46d4f16 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -676,7 +676,7 @@ static int can_unuse(struct inode *inode)
  * Walk the superblock inode LRU for freeable inodes and attempt to free them.
  * This is called from the superblock shrinker function with a number of inodes
  * to trim from the LRU. Inodes to be freed are moved to a temporary list and
- * then are freed outside inode_lock by dispose_list().
+ * then are freed outside s_inode_lru_lock by dispose_list().
  *
  * Any inodes which are pinned purely because of attached pagecache have their
  * pagecache removed.  If the inode has metadata buffers attached to
@@ -777,7 +777,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan)
 
 static void __wait_on_freeing_inode(struct inode *inode);
 /*
- * Called with the inode lock held.
+ * Called with the inode_hash_lock held.
  */
 static struct inode *find_inode(struct super_block *sb,
 				struct hlist_head *head,
diff --git a/fs/namei.c b/fs/namei.c
index 5ffd97d..7b1f714 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -421,7 +421,7 @@ EXPORT_SYMBOL(path_put);
  * Path walking has 2 modes, rcu-walk and ref-walk (see
  * Documentation/filesystems/path-lookup.txt).  In situations when we can't
  * continue in RCU mode, we attempt to drop out of rcu-walk mode and grab
- * normal reference counts on dentries and vfsmounts to transition to rcu-walk
+ * normal reference counts on dentries and vfsmounts to transition to ref-walk
  * mode.  Refcounts are grabbed at the last known good point before rcu-walk
  * got stuck, so ref-walk may continue from there. If this is not successful
  * (eg. a seqcount has changed), then failure is returned and it's up to caller
diff --git a/fs/namespace.c b/fs/namespace.c
index ca2b6e9..b7477ee 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1239,9 +1239,6 @@ static inline bool path_unmounted(struct path *path)
 }
 
 /*
- * Now umount can handle mount points as well as block devices.
- * This is important for filesystems which use unnamed block devices.
- *
  * We now support a flag for forced unmount like the other 'big iron'
  * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
  */
@@ -1431,9 +1428,9 @@ static int invent_group_ids(struct mount *mnt, bool recurse)
 }
 
 /*
- *  @source_mnt : mount tree to be attached
- *  @nd         : place the mount tree @source_mnt is attached
- *  @parent_nd  : if non-null, detach the source_mnt from its parent and
+ *  @source_mnt  : mount tree to be attached
+ *  @path        : place the mount tree @source_mnt is attached
+ *  @parent_path : if non-null, detach the @source_mnt from its parent and
  *  		   store the parent mount and mountpoint dentry.
  *  		   (done when source_mnt is moved)
  *
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH] Staging: android: fixed const coding style issue in binder.c
       [not found] <no>
                   ` (33 preceding siblings ...)
  2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
@ 2013-01-07 18:11 ` Patrik Karlin
  2013-01-07 23:01   ` Greg KH
  2013-11-11  9:27 ` [PATCH 1/2] mklibs: add dependency on dpkg-native Lei Liu
                   ` (3 subsequent siblings)
  38 siblings, 1 reply; 206+ messages in thread
From: Patrik Karlin @ 2013-01-07 18:11 UTC (permalink / raw)
  To: gregkh; +Cc: devel, linux-kernel, Patrik Karlin

This is a patch to add const to the lists of strings in binder.c
as suggested by checkpatch.pl

Signed-off-by: Patrik Kårlin <patrik.karlin@gmail.com>
---
 drivers/staging/android/binder.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 2d12e8a..538ebe2 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -3227,7 +3227,7 @@ static void print_binder_proc(struct seq_file *m,
 		m->count = start_pos;
 }
 
-static const char *binder_return_strings[] = {
+static const char * const binder_return_strings[] = {
 	"BR_ERROR",
 	"BR_OK",
 	"BR_TRANSACTION",
@@ -3248,7 +3248,7 @@ static const char *binder_return_strings[] = {
 	"BR_FAILED_REPLY"
 };
 
-static const char *binder_command_strings[] = {
+static const char * const binder_command_strings[] = {
 	"BC_TRANSACTION",
 	"BC_REPLY",
 	"BC_ACQUIRE_RESULT",
@@ -3268,7 +3268,7 @@ static const char *binder_command_strings[] = {
 	"BC_DEAD_BINDER_DONE"
 };
 
-static const char *binder_objstat_strings[] = {
+static const char * const binder_objstat_strings[] = {
 	"proc",
 	"thread",
 	"node",
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH] Staging: android: fixed const coding style issue in binder.c
  2013-01-07 18:11 ` [PATCH] Staging: android: fixed const coding style issue in binder.c Patrik Karlin
@ 2013-01-07 23:01   ` Greg KH
  0 siblings, 0 replies; 206+ messages in thread
From: Greg KH @ 2013-01-07 23:01 UTC (permalink / raw)
  To: Patrik Karlin; +Cc: devel, linux-kernel

On Mon, Jan 07, 2013 at 07:11:52PM +0100, Patrik Karlin wrote:
> This is a patch to add const to the lists of strings in binder.c
> as suggested by checkpatch.pl
> 
> Signed-off-by: Patrik Kårlin <patrik.karlin@gmail.com>
> ---
>  drivers/staging/android/binder.c |    6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Sorry, I just applied a patch from someone else that did this same
thing, that was sent to me a few weeks ago.

greg k-h

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH 1/2] mklibs: add dependency on dpkg-native
       [not found] <no>
                   ` (34 preceding siblings ...)
  2013-01-07 18:11 ` [PATCH] Staging: android: fixed const coding style issue in binder.c Patrik Karlin
@ 2013-11-11  9:27 ` Lei Liu
  2013-11-11  9:27 ` [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs Lei Liu
                   ` (2 subsequent siblings)
  38 siblings, 0 replies; 206+ messages in thread
From: Lei Liu @ 2013-11-11  9:27 UTC (permalink / raw)
  To: openembedded-core

From: Lei Liu <lei.liu2@windriver.com>

mklibs requires the "dpkg-architecture" utility to work.
Add dependency on dpkg-native.

Signed-off-by: Lei Liu <lei.liu2@windriver.com>
---
 .../mklibs/mklibs-native_0.1.38.bb                 |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/meta/recipes-devtools/mklibs/mklibs-native_0.1.38.bb b/meta/recipes-devtools/mklibs/mklibs-native_0.1.38.bb
index e424052..6367e8f 100644
--- a/meta/recipes-devtools/mklibs/mklibs-native_0.1.38.bb
+++ b/meta/recipes-devtools/mklibs/mklibs-native_0.1.38.bb
@@ -3,7 +3,7 @@ HOMEPAGE = "https://code.launchpad.net/mklibs"
 SECTION = "devel"
 LICENSE = "GPLv2+"
 LIC_FILES_CHKSUM = "file://debian/copyright;md5=98d31037b13d896e33890738ef01af64"
-DEPENDS = "python-native"
+DEPENDS = "python-native dpkg-native"
 
 SRC_URI = "http://ftp.de.debian.org/debian/pool/main/m/mklibs/${BPN}_${PV}.tar.gz \
 	file://ac_init_fix.patch\
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs
       [not found] <no>
                   ` (35 preceding siblings ...)
  2013-11-11  9:27 ` [PATCH 1/2] mklibs: add dependency on dpkg-native Lei Liu
@ 2013-11-11  9:27 ` Lei Liu
  2013-11-12 10:23   ` Richard Purdie
  2014-02-08  2:29 ` [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff shaobingqing
  2019-02-18 11:59 ` [PATCH] net/bonding: fix reset active slave Hari Kumar Vemula
  38 siblings, 1 reply; 206+ messages in thread
From: Lei Liu @ 2013-11-11  9:27 UTC (permalink / raw)
  To: openembedded-core

From: Lei Liu <lei.liu2@windriver.com>

File command in some version could print extra space between
"LSB" and "executable" - it causes mklibs can't find any executables
using grep "LSB executable".  Fix the grep pattern to catch
multiple spaces.

Signed-off-by: Lei Liu <lei.liu2@windriver.com>
---
 meta/classes/image-mklibs.bbclass |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/meta/classes/image-mklibs.bbclass b/meta/classes/image-mklibs.bbclass
index 66b0f52..e975f5d 100644
--- a/meta/classes/image-mklibs.bbclass
+++ b/meta/classes/image-mklibs.bbclass
@@ -9,7 +9,7 @@ mklibs_optimize_image_doit() {
 	du -bs > ${WORKDIR}/mklibs/du.before.mklibs.txt
 	for i in `find .`; do file $i; done \
 		| grep ELF \
-		| grep "LSB executable" \
+		| grep "LSB *executable" \
 		| grep "dynamically linked" \
 		| sed "s/:.*//" \
 		| sed "s+^\./++" \
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs
  2013-11-11  9:27 ` [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs Lei Liu
@ 2013-11-12 10:23   ` Richard Purdie
  2013-11-13  3:05     ` Lei Liu
  0 siblings, 1 reply; 206+ messages in thread
From: Richard Purdie @ 2013-11-12 10:23 UTC (permalink / raw)
  To: Lei Liu; +Cc: openembedded-core

On Mon, 2013-11-11 at 17:27 +0800, Lei Liu wrote:
> From: Lei Liu <lei.liu2@windriver.com>
> 
> File command in some version could print extra space between
> "LSB" and "executable" - it causes mklibs can't find any executables
> using grep "LSB executable".  Fix the grep pattern to catch
> multiple spaces.
> 
> Signed-off-by: Lei Liu <lei.liu2@windriver.com>
> ---
>  meta/classes/image-mklibs.bbclass |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)

I've queued this but please put the area name in the short line of the
commit in future ("image-mklibs: " in this case).

Cheers,

Richard



^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs
  2013-11-12 10:23   ` Richard Purdie
@ 2013-11-13  3:05     ` Lei Liu
  2013-11-22 22:33       ` Nicolas Dechesne
  0 siblings, 1 reply; 206+ messages in thread
From: Lei Liu @ 2013-11-13  3:05 UTC (permalink / raw)
  To: Richard Purdie; +Cc: openembedded-core

On 2013年11月12日 18:23, Richard Purdie wrote:
> On Mon, 2013-11-11 at 17:27 +0800, Lei Liu wrote:
>> From: Lei Liu <lei.liu2@windriver.com>
>>
>> File command in some version could print extra space between
>> "LSB" and "executable" - it causes mklibs can't find any executables
>> using grep "LSB executable".  Fix the grep pattern to catch
>> multiple spaces.
>>
>> Signed-off-by: Lei Liu <lei.liu2@windriver.com>
>> ---
>>  meta/classes/image-mklibs.bbclass |    2 +-
>>  1 files changed, 1 insertions(+), 1 deletions(-)
> I've queued this but please put the area name in the short line of the
> commit in future ("image-mklibs: " in this case).
>

Okay.  Thanks.

Lei


^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs
  2013-11-13  3:05     ` Lei Liu
@ 2013-11-22 22:33       ` Nicolas Dechesne
       [not found]         ` <52955AAB.6000801@gmail.com>
  0 siblings, 1 reply; 206+ messages in thread
From: Nicolas Dechesne @ 2013-11-22 22:33 UTC (permalink / raw)
  To: Lei Liu; +Cc: Patches and discussions about the oe-core layer

[-- Attachment #1: Type: text/plain, Size: 1460 bytes --]

hi,

On Wed, Nov 13, 2013 at 4:05 AM, Lei Liu <layliu@gmail.com> wrote:

> On 2013年11月12日 18:23, Richard Purdie wrote:
> > On Mon, 2013-11-11 at 17:27 +0800, Lei Liu wrote:
> >> From: Lei Liu <lei.liu2@windriver.com>
> >>
> >> File command in some version could print extra space between
> >> "LSB" and "executable" - it causes mklibs can't find any executables
> >> using grep "LSB executable".  Fix the grep pattern to catch
> >> multiple spaces.
> >>
> >> Signed-off-by: Lei Liu <lei.liu2@windriver.com>
> >> ---
> >>  meta/classes/image-mklibs.bbclass |    2 +-
> >>  1 files changed, 1 insertions(+), 1 deletions(-)
> > I've queued this but please put the area name in the short line of the
> > commit in future ("image-mklibs: " in this case).
> >
>
> Okay.  Thanks.


First of all, this patch is needed on dora branch too , and it applies
cleanly, can that be merged?

Now, the real question... i am not able to get mklibs to work at all (even
with this patch). What i am seeing is that mklibs 0.1.38 doesn't support
anymore the use of 'sysroot'. I think this is because of this upstream
change

http://anonscm.debian.org/gitweb/?p=d-i/mklibs.git;a=commit;h=60bda7e2132d197e1c88afb5012f9677b6967db2

If I revert to 0.1.34 (that we had on dylan branch), i can build my image
just fine (note that I am building an arm soft-float image), so are you
able to use image-mklibs with dora or master which have 0.1.38?

[-- Attachment #2: Type: text/html, Size: 2614 bytes --]

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs
       [not found]         ` <52955AAB.6000801@gmail.com>
@ 2013-11-27 13:00           ` Nicolas Dechesne
  0 siblings, 0 replies; 206+ messages in thread
From: Nicolas Dechesne @ 2013-11-27 13:00 UTC (permalink / raw)
  To: Lei Liu; +Cc: Patches and discussions about the oe-core layer

[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]

On Wed, Nov 27, 2013 at 3:36 AM, Lei Liu <layliu@gmail.com> wrote:

> > If I revert to 0.1.34 (that we had on dylan branch), i can build my
> image just fine (note that I am building an arm soft-float image), so are
> you able to use image-mklibs with dora or master which have 0.1.38?
> >
>
> Hi,
>
> I'm testing on master.  And I'm able to build my qemux86 image with
> mklibs-0.1.38.
>

ok, thanks for your answer.

I tested this morning, and confirm that 'master' + mklibs is broken on ARM
(i tested qemuarm), altough qemux86 is working.. i will try to look into
that... in fact to be honest, i still believe that mklibs 0.1.38 is broken,
even on x86 and that it's working for qemux86 because it uses the loader
from your host instead of the one in the sysroot. In my case it's failing
because it doesn't find the loader in /lib (/lib in my host):

Exception: Cannot find lib /lib/ld-linux.so.3

it should in theory look for that file in the sysroot... if you look at the
upstream commit i referenced above, upstream no longer uses 'sysroot'
variable to locate the loader...

[-- Attachment #2: Type: text/html, Size: 1868 bytes --]

^ permalink raw reply	[flat|nested] 206+ messages in thread

* [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff
       [not found] <no>
                   ` (36 preceding siblings ...)
  2013-11-11  9:27 ` [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs Lei Liu
@ 2014-02-08  2:29 ` shaobingqing
  2014-02-08 19:14     ` Sergei Shtylyov
  2014-02-10 17:46     ` Trond Myklebust
  2019-02-18 11:59 ` [PATCH] net/bonding: fix reset active slave Hari Kumar Vemula
  38 siblings, 2 replies; 206+ messages in thread
From: shaobingqing @ 2014-02-08  2:29 UTC (permalink / raw)
  To: trond.myklebust, bfields, davem
  Cc: linux-nfs, netdev, linux-kernel, shaobingqing

In current code, there only one struct rpc_rqst is prealloced. If one
callback request is received from two sk_buff, the xprt_alloc_bc_request
would be execute two times with the same transport->xid. The first time
xprt_alloc_bc_request will alloc one struct rpc_rqst and the TCP_RCV_COPY_DATA
bit of transport->tcp_flags will not be cleared. The second time
xprt_alloc_bc_request could not alloc struct rpc_rqst any more and NULL
pointer will be returned, then xprt_force_disconnect occur. I think one
callback request can be allowed to be received from two sk_buff.

Signed-off-by: shaobingqing <shaobingqing@bwstor.com.cn>
---
 include/linux/sunrpc/xprt.h |    1 +
 net/sunrpc/xprt.c           |    1 +
 net/sunrpc/xprtsock.c       |   13 ++++++++++++-
 3 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index cec7b9b..82bfe01 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -211,6 +211,7 @@ struct rpc_xprt {
 						 * items */
 	struct list_head	bc_pa_list;	/* List of preallocated
 						 * backchannel rpc_rqst's */
+	struct rpc_rqst	*req_first;
 #endif /* CONFIG_SUNRPC_BACKCHANNEL */
 	struct list_head	recv;
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 095363e..93ad8bc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1256,6 +1256,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
 #if defined(CONFIG_SUNRPC_BACKCHANNEL)
 	spin_lock_init(&xprt->bc_pa_lock);
 	INIT_LIST_HEAD(&xprt->bc_pa_list);
+	xprt->req_first = NULL;
 #endif /* CONFIG_SUNRPC_BACKCHANNEL */
 
 	xprt->last_used = jiffies;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ee03d35..c43dca4 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1272,7 +1272,16 @@ static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
 				container_of(xprt, struct sock_xprt, xprt);
 	struct rpc_rqst *req;
 
-	req = xprt_alloc_bc_request(xprt);
+	if (xprt->req_first != NULL &&
+			xprt->req_first->rq_xid == transport->tcp_xid) {
+		req = xprt->req_first;
+	} else if (xprt->req_first != NULL &&
+			xprt->req_first->rq_xid != transport->tcp_xid) {
+		xprt_free_bc_request(xprt);
+		req = xprt_alloc_bc_request(xprt);
+	} else {
+		req = xprt_alloc_bc_request(xprt);
+	}
 	if (req == NULL) {
 		printk(KERN_WARNING "Callback slot table overflowed\n");
 		xprt_force_disconnect(xprt);
@@ -1297,6 +1306,8 @@ static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
 		list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
 		spin_unlock(&bc_serv->sv_cb_lock);
 		wake_up(&bc_serv->sv_cb_waitq);
+	} else {
+		xprt->req_first = req;
 	}
 
 	req->rq_private_buf.len = transport->tcp_copied;
-- 
1.7.4.2


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff
@ 2014-02-08 19:14     ` Sergei Shtylyov
  0 siblings, 0 replies; 206+ messages in thread
From: Sergei Shtylyov @ 2014-02-08 19:14 UTC (permalink / raw)
  To: shaobingqing, trond.myklebust, bfields, davem
  Cc: linux-nfs, netdev, linux-kernel

Hello.

On 08-02-2014 6:29, shaobingqing wrote:

> In current code, there only one struct rpc_rqst is prealloced. If one
> callback request is received from two sk_buff, the xprt_alloc_bc_request
> would be execute two times with the same transport->xid. The first time
> xprt_alloc_bc_request will alloc one struct rpc_rqst and the TCP_RCV_COPY_DATA
> bit of transport->tcp_flags will not be cleared. The second time
> xprt_alloc_bc_request could not alloc struct rpc_rqst any more and NULL
> pointer will be returned, then xprt_force_disconnect occur. I think one
> callback request can be allowed to be received from two sk_buff.

> Signed-off-by: shaobingqing <shaobingqing@bwstor.com.cn>
[...]

> diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
> index cec7b9b..82bfe01 100644
> --- a/include/linux/sunrpc/xprt.h
> +++ b/include/linux/sunrpc/xprt.h
> @@ -211,6 +211,7 @@ struct rpc_xprt {
>   						 * items */
>   	struct list_head	bc_pa_list;	/* List of preallocated
>   						 * backchannel rpc_rqst's */
> +	struct rpc_rqst	*req_first;

    Please align the variable name with the ones above and below.

>   #endif /* CONFIG_SUNRPC_BACKCHANNEL */
>   	struct list_head	recv;
>
[...]
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index ee03d35..c43dca4 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -1272,7 +1272,16 @@ static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
>   				container_of(xprt, struct sock_xprt, xprt);
>   	struct rpc_rqst *req;
>
> -	req = xprt_alloc_bc_request(xprt);
> +	if (xprt->req_first != NULL &&
> +			xprt->req_first->rq_xid == transport->tcp_xid) {

    The continuation line should be aligned right under 'xprt' on the broken 
up line, according to the networking coding style.

> +		req = xprt->req_first;
> +	} else if (xprt->req_first != NULL &&
> +			xprt->req_first->rq_xid != transport->tcp_xid) {

    Same here.

WBR, Sergei


^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff
@ 2014-02-08 19:14     ` Sergei Shtylyov
  0 siblings, 0 replies; 206+ messages in thread
From: Sergei Shtylyov @ 2014-02-08 19:14 UTC (permalink / raw)
  To: shaobingqing, trond.myklebust-7I+n7zu2hftEKMMhf/gKZA,
	bfields-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

Hello.

On 08-02-2014 6:29, shaobingqing wrote:

> In current code, there only one struct rpc_rqst is prealloced. If one
> callback request is received from two sk_buff, the xprt_alloc_bc_request
> would be execute two times with the same transport->xid. The first time
> xprt_alloc_bc_request will alloc one struct rpc_rqst and the TCP_RCV_COPY_DATA
> bit of transport->tcp_flags will not be cleared. The second time
> xprt_alloc_bc_request could not alloc struct rpc_rqst any more and NULL
> pointer will be returned, then xprt_force_disconnect occur. I think one
> callback request can be allowed to be received from two sk_buff.

> Signed-off-by: shaobingqing <shaobingqing-Gb3srWounXyPt1CcHtbs0g@public.gmane.org>
[...]

> diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
> index cec7b9b..82bfe01 100644
> --- a/include/linux/sunrpc/xprt.h
> +++ b/include/linux/sunrpc/xprt.h
> @@ -211,6 +211,7 @@ struct rpc_xprt {
>   						 * items */
>   	struct list_head	bc_pa_list;	/* List of preallocated
>   						 * backchannel rpc_rqst's */
> +	struct rpc_rqst	*req_first;

    Please align the variable name with the ones above and below.

>   #endif /* CONFIG_SUNRPC_BACKCHANNEL */
>   	struct list_head	recv;
>
[...]
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index ee03d35..c43dca4 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -1272,7 +1272,16 @@ static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
>   				container_of(xprt, struct sock_xprt, xprt);
>   	struct rpc_rqst *req;
>
> -	req = xprt_alloc_bc_request(xprt);
> +	if (xprt->req_first != NULL &&
> +			xprt->req_first->rq_xid == transport->tcp_xid) {

    The continuation line should be aligned right under 'xprt' on the broken 
up line, according to the networking coding style.

> +		req = xprt->req_first;
> +	} else if (xprt->req_first != NULL &&
> +			xprt->req_first->rq_xid != transport->tcp_xid) {

    Same here.

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff
@ 2014-02-10 17:46     ` Trond Myklebust
  0 siblings, 0 replies; 206+ messages in thread
From: Trond Myklebust @ 2014-02-10 17:46 UTC (permalink / raw)
  To: shaobingqing; +Cc: bfields, davem, linux-nfs, netdev, linux-kernel

On Sat, 2014-02-08 at 10:29 +0800, shaobingqing wrote:
> In current code, there only one struct rpc_rqst is prealloced. If one
> callback request is received from two sk_buff, the xprt_alloc_bc_request
> would be execute two times with the same transport->xid. The first time
> xprt_alloc_bc_request will alloc one struct rpc_rqst and the TCP_RCV_COPY_DATA
> bit of transport->tcp_flags will not be cleared. The second time
> xprt_alloc_bc_request could not alloc struct rpc_rqst any more and NULL
> pointer will be returned, then xprt_force_disconnect occur. I think one
> callback request can be allowed to be received from two sk_buff.
> 
> Signed-off-by: shaobingqing <shaobingqing@bwstor.com.cn>
> ---

There are still several problems with this patch.
For one thing, xprt->req_first is never cleared, which means that the
tests you add in xs_tcp_read_callback() could trigger even if the
request is in use by the callback server.
Furthermore, if the xprt is destroyed before the RPC callback has been
filled, then the request is leaked: it is no longer on the xprt
backchannel list, so nothing will clean it up there, and nothing ever
checks xprt->req_first, so it won't get cleaned up there either.

Instead of adding a new tracking mechanism, what say we just keep the
request on the xprt callback list until it has been completely filled.

IOW: something like the following patch:

8<-------------------------------------------------------------------
>From 2aa57b6c6c6025e17d7ca164bbda01767af662be Mon Sep 17 00:00:00 2001
From: Trond Myklebust <trond.myklebust@primarydata.com>
Date: Mon, 10 Feb 2014 11:18:39 -0500
Subject: [PATCH] SUNRPC: RPC callbacks may be split across several TCP
 segments

Since TCP is a stream protocol, our callback read code needs to take into
account the fact that RPC callbacks are not always confined to a single
TCP segment.
This patch adds support for multiple TCP segments by ensuring that we
only remove the rpc_rqst structure from the 'free backchannel requests'
list once the data has been completely received. We rely on the fact
that TCP data is ordered for the duration of the connection.

Reported-by: shaobingqing <shaobingqing@bwstor.com.cn>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 include/linux/sunrpc/bc_xprt.h |  3 +-
 net/sunrpc/backchannel_rqst.c  | 92 +++++++++++++++++++++++++++++-------------
 net/sunrpc/xprtsock.c          | 28 ++++---------
 3 files changed, 73 insertions(+), 50 deletions(-)

diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 969c0a671dbf..2ca67b55e0fe 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <linux/sunrpc/sched.h>
 
 #ifdef CONFIG_SUNRPC_BACKCHANNEL
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid);
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied);
 void xprt_free_bc_request(struct rpc_rqst *req);
 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
 void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs);
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 890a29912d5a..7cceeb06b939 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -210,39 +210,23 @@ out:
 }
 EXPORT_SYMBOL_GPL(xprt_destroy_backchannel);
 
-/*
- * One or more rpc_rqst structure have been preallocated during the
- * backchannel setup.  Buffer space for the send and private XDR buffers
- * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
- * to this request.  Use xprt_free_bc_request to return it.
- *
- * We know that we're called in soft interrupt context, grab the spin_lock
- * since there is no need to grab the bottom half spin_lock.
- *
- * Return an available rpc_rqst, otherwise NULL if non are available.
- */
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
+static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid)
 {
-	struct rpc_rqst *req;
+	struct rpc_rqst *req = NULL;
 
 	dprintk("RPC:       allocate a backchannel request\n");
-	spin_lock(&xprt->bc_pa_lock);
-	if (!list_empty(&xprt->bc_pa_list)) {
-		req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
-				rq_bc_pa_list);
-		list_del(&req->rq_bc_pa_list);
-	} else {
-		req = NULL;
-	}
-	spin_unlock(&xprt->bc_pa_lock);
+	if (list_empty(&xprt->bc_pa_list))
+		goto not_found;
 
-	if (req != NULL) {
-		set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
-		req->rq_reply_bytes_recvd = 0;
-		req->rq_bytes_sent = 0;
-		memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
+	req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
+				rq_bc_pa_list);
+	req->rq_reply_bytes_recvd = 0;
+	req->rq_bytes_sent = 0;
+	memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
 			sizeof(req->rq_private_buf));
-	}
+	req->rq_xid = xid;
+	req->rq_connect_cookie = xprt->connect_cookie;
+not_found:
 	dprintk("RPC:       backchannel req=%p\n", req);
 	return req;
 }
@@ -257,6 +241,7 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 
 	dprintk("RPC:       free backchannel req=%p\n", req);
 
+	req->rq_connect_cookie = xprt->connect_cookie - 1;
 	smp_mb__before_clear_bit();
 	WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
 	clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
@@ -279,7 +264,56 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 	 * may be reused by a new callback request.
 	 */
 	spin_lock_bh(&xprt->bc_pa_lock);
-	list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
+	list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list);
 	spin_unlock_bh(&xprt->bc_pa_lock);
 }
 
+/*
+ * One or more rpc_rqst structure have been preallocated during the
+ * backchannel setup.  Buffer space for the send and private XDR buffers
+ * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
+ * to this request.  Use xprt_free_bc_request to return it.
+ *
+ * We know that we're called in soft interrupt context, grab the spin_lock
+ * since there is no need to grab the bottom half spin_lock.
+ *
+ * Return an available rpc_rqst, otherwise NULL if non are available.
+ */
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid)
+{
+	struct rpc_rqst *req;
+
+	spin_lock(&xprt->bc_pa_lock);
+	list_for_each_entry(req, &xprt->bc_pa_list, rq_bc_pa_list) {
+		if (req->rq_connect_cookie != xprt->connect_cookie)
+			continue;
+		if (req->rq_xid == xid)
+			goto found;
+	}
+	req = xprt_alloc_bc_request(xprt, xid);
+found:
+	spin_unlock(&xprt->bc_pa_lock);
+	return req;
+}
+
+/*
+ * Add callback request to callback list.  The callback
+ * service sleeps on the sv_cb_waitq waiting for new
+ * requests.  Wake it up after adding enqueing the
+ * request.
+ */
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
+{
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct svc_serv *bc_serv = xprt->bc_serv;
+
+	req->rq_private_buf.len = copied;
+	set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+
+	dprintk("RPC:       add callback request to list\n");
+	spin_lock(&bc_serv->sv_cb_lock);
+	list_move(&req->rq_bc_list, &bc_serv->sv_cb_list);
+	wake_up(&bc_serv->sv_cb_waitq);
+	spin_unlock(&bc_serv->sv_cb_lock);
+}
+
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 817a1e523969..6497c221612c 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1302,41 +1302,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
  * If we're unable to obtain the rpc_rqst we schedule the closing of the
  * connection and return -1.
  */
-static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
+static int xs_tcp_read_callback(struct rpc_xprt *xprt,
 				       struct xdr_skb_reader *desc)
 {
 	struct sock_xprt *transport =
 				container_of(xprt, struct sock_xprt, xprt);
 	struct rpc_rqst *req;
 
-	req = xprt_alloc_bc_request(xprt);
+	/* Look up and lock the request corresponding to the given XID */
+	spin_lock(&xprt->transport_lock);
+	req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
 	if (req == NULL) {
+		spin_unlock(&xprt->transport_lock);
 		printk(KERN_WARNING "Callback slot table overflowed\n");
 		xprt_force_disconnect(xprt);
 		return -1;
 	}
 
-	req->rq_xid = transport->tcp_xid;
 	dprintk("RPC:       read callback  XID %08x\n", ntohl(req->rq_xid));
 	xs_tcp_read_common(xprt, desc, req);
 
-	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
-		struct svc_serv *bc_serv = xprt->bc_serv;
-
-		/*
-		 * Add callback request to callback list.  The callback
-		 * service sleeps on the sv_cb_waitq waiting for new
-		 * requests.  Wake it up after adding enqueing the
-		 * request.
-		 */
-		dprintk("RPC:       add callback request to list\n");
-		spin_lock(&bc_serv->sv_cb_lock);
-		list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
-		spin_unlock(&bc_serv->sv_cb_lock);
-		wake_up(&bc_serv->sv_cb_waitq);
-	}
-
-	req->rq_private_buf.len = transport->tcp_copied;
+	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
+		xprt_complete_bc_request(req, transport->tcp_copied);
+	spin_unlock(&xprt->transport_lock);
 
 	return 0;
 }
-- 
1.8.5.3


-- 
Trond Myklebust
Linux NFS client maintainer, PrimaryData
trond.myklebust@primarydata.com



^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff
@ 2014-02-10 17:46     ` Trond Myklebust
  0 siblings, 0 replies; 206+ messages in thread
From: Trond Myklebust @ 2014-02-10 17:46 UTC (permalink / raw)
  To: shaobingqing
  Cc: bfields-H+wXaHxf7aLQT0dZR+AlfA, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Sat, 2014-02-08 at 10:29 +0800, shaobingqing wrote:
> In current code, there only one struct rpc_rqst is prealloced. If one
> callback request is received from two sk_buff, the xprt_alloc_bc_request
> would be execute two times with the same transport->xid. The first time
> xprt_alloc_bc_request will alloc one struct rpc_rqst and the TCP_RCV_COPY_DATA
> bit of transport->tcp_flags will not be cleared. The second time
> xprt_alloc_bc_request could not alloc struct rpc_rqst any more and NULL
> pointer will be returned, then xprt_force_disconnect occur. I think one
> callback request can be allowed to be received from two sk_buff.
> 
> Signed-off-by: shaobingqing <shaobingqing-Gb3srWounXyPt1CcHtbs0g@public.gmane.org>
> ---

There are still several problems with this patch.
For one thing, xprt->req_first is never cleared, which means that the
tests you add in xs_tcp_read_callback() could trigger even if the
request is in use by the callback server.
Furthermore, if the xprt is destroyed before the RPC callback has been
filled, then the request is leaked: it is no longer on the xprt
backchannel list, so nothing will clean it up there, and nothing ever
checks xprt->req_first, so it won't get cleaned up there either.

Instead of adding a new tracking mechanism, what say we just keep the
request on the xprt callback list until it has been completely filled.

IOW: something like the following patch:

8<-------------------------------------------------------------------
>From 2aa57b6c6c6025e17d7ca164bbda01767af662be Mon Sep 17 00:00:00 2001
From: Trond Myklebust <trond.myklebust-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
Date: Mon, 10 Feb 2014 11:18:39 -0500
Subject: [PATCH] SUNRPC: RPC callbacks may be split across several TCP
 segments

Since TCP is a stream protocol, our callback read code needs to take into
account the fact that RPC callbacks are not always confined to a single
TCP segment.
This patch adds support for multiple TCP segments by ensuring that we
only remove the rpc_rqst structure from the 'free backchannel requests'
list once the data has been completely received. We rely on the fact
that TCP data is ordered for the duration of the connection.

Reported-by: shaobingqing <shaobingqing-Gb3srWounXyPt1CcHtbs0g@public.gmane.org>
Signed-off-by: Trond Myklebust <trond.myklebust-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org>
---
 include/linux/sunrpc/bc_xprt.h |  3 +-
 net/sunrpc/backchannel_rqst.c  | 92 +++++++++++++++++++++++++++++-------------
 net/sunrpc/xprtsock.c          | 28 ++++---------
 3 files changed, 73 insertions(+), 50 deletions(-)

diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 969c0a671dbf..2ca67b55e0fe 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <linux/sunrpc/sched.h>
 
 #ifdef CONFIG_SUNRPC_BACKCHANNEL
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid);
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied);
 void xprt_free_bc_request(struct rpc_rqst *req);
 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
 void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs);
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 890a29912d5a..7cceeb06b939 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -210,39 +210,23 @@ out:
 }
 EXPORT_SYMBOL_GPL(xprt_destroy_backchannel);
 
-/*
- * One or more rpc_rqst structure have been preallocated during the
- * backchannel setup.  Buffer space for the send and private XDR buffers
- * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
- * to this request.  Use xprt_free_bc_request to return it.
- *
- * We know that we're called in soft interrupt context, grab the spin_lock
- * since there is no need to grab the bottom half spin_lock.
- *
- * Return an available rpc_rqst, otherwise NULL if non are available.
- */
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
+static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid)
 {
-	struct rpc_rqst *req;
+	struct rpc_rqst *req = NULL;
 
 	dprintk("RPC:       allocate a backchannel request\n");
-	spin_lock(&xprt->bc_pa_lock);
-	if (!list_empty(&xprt->bc_pa_list)) {
-		req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
-				rq_bc_pa_list);
-		list_del(&req->rq_bc_pa_list);
-	} else {
-		req = NULL;
-	}
-	spin_unlock(&xprt->bc_pa_lock);
+	if (list_empty(&xprt->bc_pa_list))
+		goto not_found;
 
-	if (req != NULL) {
-		set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
-		req->rq_reply_bytes_recvd = 0;
-		req->rq_bytes_sent = 0;
-		memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
+	req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
+				rq_bc_pa_list);
+	req->rq_reply_bytes_recvd = 0;
+	req->rq_bytes_sent = 0;
+	memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
 			sizeof(req->rq_private_buf));
-	}
+	req->rq_xid = xid;
+	req->rq_connect_cookie = xprt->connect_cookie;
+not_found:
 	dprintk("RPC:       backchannel req=%p\n", req);
 	return req;
 }
@@ -257,6 +241,7 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 
 	dprintk("RPC:       free backchannel req=%p\n", req);
 
+	req->rq_connect_cookie = xprt->connect_cookie - 1;
 	smp_mb__before_clear_bit();
 	WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
 	clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
@@ -279,7 +264,56 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 	 * may be reused by a new callback request.
 	 */
 	spin_lock_bh(&xprt->bc_pa_lock);
-	list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
+	list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list);
 	spin_unlock_bh(&xprt->bc_pa_lock);
 }
 
+/*
+ * One or more rpc_rqst structure have been preallocated during the
+ * backchannel setup.  Buffer space for the send and private XDR buffers
+ * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
+ * to this request.  Use xprt_free_bc_request to return it.
+ *
+ * We know that we're called in soft interrupt context, grab the spin_lock
+ * since there is no need to grab the bottom half spin_lock.
+ *
+ * Return an available rpc_rqst, otherwise NULL if non are available.
+ */
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid)
+{
+	struct rpc_rqst *req;
+
+	spin_lock(&xprt->bc_pa_lock);
+	list_for_each_entry(req, &xprt->bc_pa_list, rq_bc_pa_list) {
+		if (req->rq_connect_cookie != xprt->connect_cookie)
+			continue;
+		if (req->rq_xid == xid)
+			goto found;
+	}
+	req = xprt_alloc_bc_request(xprt, xid);
+found:
+	spin_unlock(&xprt->bc_pa_lock);
+	return req;
+}
+
+/*
+ * Add callback request to callback list.  The callback
+ * service sleeps on the sv_cb_waitq waiting for new
+ * requests.  Wake it up after adding enqueing the
+ * request.
+ */
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
+{
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct svc_serv *bc_serv = xprt->bc_serv;
+
+	req->rq_private_buf.len = copied;
+	set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+
+	dprintk("RPC:       add callback request to list\n");
+	spin_lock(&bc_serv->sv_cb_lock);
+	list_move(&req->rq_bc_list, &bc_serv->sv_cb_list);
+	wake_up(&bc_serv->sv_cb_waitq);
+	spin_unlock(&bc_serv->sv_cb_lock);
+}
+
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 817a1e523969..6497c221612c 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1302,41 +1302,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
  * If we're unable to obtain the rpc_rqst we schedule the closing of the
  * connection and return -1.
  */
-static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
+static int xs_tcp_read_callback(struct rpc_xprt *xprt,
 				       struct xdr_skb_reader *desc)
 {
 	struct sock_xprt *transport =
 				container_of(xprt, struct sock_xprt, xprt);
 	struct rpc_rqst *req;
 
-	req = xprt_alloc_bc_request(xprt);
+	/* Look up and lock the request corresponding to the given XID */
+	spin_lock(&xprt->transport_lock);
+	req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
 	if (req == NULL) {
+		spin_unlock(&xprt->transport_lock);
 		printk(KERN_WARNING "Callback slot table overflowed\n");
 		xprt_force_disconnect(xprt);
 		return -1;
 	}
 
-	req->rq_xid = transport->tcp_xid;
 	dprintk("RPC:       read callback  XID %08x\n", ntohl(req->rq_xid));
 	xs_tcp_read_common(xprt, desc, req);
 
-	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
-		struct svc_serv *bc_serv = xprt->bc_serv;
-
-		/*
-		 * Add callback request to callback list.  The callback
-		 * service sleeps on the sv_cb_waitq waiting for new
-		 * requests.  Wake it up after adding enqueing the
-		 * request.
-		 */
-		dprintk("RPC:       add callback request to list\n");
-		spin_lock(&bc_serv->sv_cb_lock);
-		list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
-		spin_unlock(&bc_serv->sv_cb_lock);
-		wake_up(&bc_serv->sv_cb_waitq);
-	}
-
-	req->rq_private_buf.len = transport->tcp_copied;
+	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
+		xprt_complete_bc_request(req, transport->tcp_copied);
+	spin_unlock(&xprt->transport_lock);
 
 	return 0;
 }
-- 
1.8.5.3


-- 
Trond Myklebust
Linux NFS client maintainer, PrimaryData
trond.myklebust-7I+n7zu2hftEKMMhf/gKZA@public.gmane.org


--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH v2] SUNRPC: RPC callbacks may be split across several TCP segments
  2014-02-10 17:46     ` Trond Myklebust
  (?)
@ 2014-02-11 19:42     ` Trond Myklebust
  -1 siblings, 0 replies; 206+ messages in thread
From: Trond Myklebust @ 2014-02-11 19:42 UTC (permalink / raw)
  To: linux-nfs; +Cc: shaobingqing

Since TCP is a stream protocol, our callback read code needs to take into
account the fact that RPC callbacks are not always confined to a single
TCP segment.
This patch adds support for multiple TCP segments by ensuring that we
only remove the rpc_rqst structure from the 'free backchannel requests'
list once the data has been completely received. We rely on the fact
that TCP data is ordered for the duration of the connection.

Reported-by: shaobingqing <shaobingqing@bwstor.com.cn>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
v2: fix a list corruption issue

 include/linux/sunrpc/bc_xprt.h |  3 +-
 net/sunrpc/backchannel_rqst.c  | 93 +++++++++++++++++++++++++++++-------------
 net/sunrpc/xprtsock.c          | 28 ++++---------
 3 files changed, 74 insertions(+), 50 deletions(-)

diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 969c0a671dbf..2ca67b55e0fe 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -32,7 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <linux/sunrpc/sched.h>
 
 #ifdef CONFIG_SUNRPC_BACKCHANNEL
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid);
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied);
 void xprt_free_bc_request(struct rpc_rqst *req);
 int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
 void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs);
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index e860d4f7ed2a..3513d559bc45 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -212,39 +212,23 @@ out:
 }
 EXPORT_SYMBOL_GPL(xprt_destroy_backchannel);
 
-/*
- * One or more rpc_rqst structure have been preallocated during the
- * backchannel setup.  Buffer space for the send and private XDR buffers
- * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
- * to this request.  Use xprt_free_bc_request to return it.
- *
- * We know that we're called in soft interrupt context, grab the spin_lock
- * since there is no need to grab the bottom half spin_lock.
- *
- * Return an available rpc_rqst, otherwise NULL if non are available.
- */
-struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
+static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid)
 {
-	struct rpc_rqst *req;
+	struct rpc_rqst *req = NULL;
 
 	dprintk("RPC:       allocate a backchannel request\n");
-	spin_lock(&xprt->bc_pa_lock);
-	if (!list_empty(&xprt->bc_pa_list)) {
-		req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
-				rq_bc_pa_list);
-		list_del(&req->rq_bc_pa_list);
-	} else {
-		req = NULL;
-	}
-	spin_unlock(&xprt->bc_pa_lock);
+	if (list_empty(&xprt->bc_pa_list))
+		goto not_found;
 
-	if (req != NULL) {
-		set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
-		req->rq_reply_bytes_recvd = 0;
-		req->rq_bytes_sent = 0;
-		memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
+	req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
+				rq_bc_pa_list);
+	req->rq_reply_bytes_recvd = 0;
+	req->rq_bytes_sent = 0;
+	memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
 			sizeof(req->rq_private_buf));
-	}
+	req->rq_xid = xid;
+	req->rq_connect_cookie = xprt->connect_cookie;
+not_found:
 	dprintk("RPC:       backchannel req=%p\n", req);
 	return req;
 }
@@ -259,6 +243,7 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 
 	dprintk("RPC:       free backchannel req=%p\n", req);
 
+	req->rq_connect_cookie = xprt->connect_cookie - 1;
 	smp_mb__before_clear_bit();
 	WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
 	clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
@@ -281,7 +266,57 @@ void xprt_free_bc_request(struct rpc_rqst *req)
 	 * may be reused by a new callback request.
 	 */
 	spin_lock_bh(&xprt->bc_pa_lock);
-	list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
+	list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list);
 	spin_unlock_bh(&xprt->bc_pa_lock);
 }
 
+/*
+ * One or more rpc_rqst structure have been preallocated during the
+ * backchannel setup.  Buffer space for the send and private XDR buffers
+ * has been preallocated as well.  Use xprt_alloc_bc_request to allocate
+ * to this request.  Use xprt_free_bc_request to return it.
+ *
+ * We know that we're called in soft interrupt context, grab the spin_lock
+ * since there is no need to grab the bottom half spin_lock.
+ *
+ * Return an available rpc_rqst, otherwise NULL if non are available.
+ */
+struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid)
+{
+	struct rpc_rqst *req;
+
+	spin_lock(&xprt->bc_pa_lock);
+	list_for_each_entry(req, &xprt->bc_pa_list, rq_bc_pa_list) {
+		if (req->rq_connect_cookie != xprt->connect_cookie)
+			continue;
+		if (req->rq_xid == xid)
+			goto found;
+	}
+	req = xprt_alloc_bc_request(xprt, xid);
+found:
+	spin_unlock(&xprt->bc_pa_lock);
+	return req;
+}
+
+/*
+ * Add callback request to callback list.  The callback
+ * service sleeps on the sv_cb_waitq waiting for new
+ * requests.  Wake it up after adding enqueing the
+ * request.
+ */
+void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
+{
+	struct rpc_xprt *xprt = req->rq_xprt;
+	struct svc_serv *bc_serv = xprt->bc_serv;
+
+	req->rq_private_buf.len = copied;
+	set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+
+	dprintk("RPC:       add callback request to list\n");
+	spin_lock(&bc_serv->sv_cb_lock);
+	list_del(&req->rq_bc_pa_list);
+	list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
+	wake_up(&bc_serv->sv_cb_waitq);
+	spin_unlock(&bc_serv->sv_cb_lock);
+}
+
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 0addefca8e77..966763d735e9 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1306,41 +1306,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
  * If we're unable to obtain the rpc_rqst we schedule the closing of the
  * connection and return -1.
  */
-static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
+static int xs_tcp_read_callback(struct rpc_xprt *xprt,
 				       struct xdr_skb_reader *desc)
 {
 	struct sock_xprt *transport =
 				container_of(xprt, struct sock_xprt, xprt);
 	struct rpc_rqst *req;
 
-	req = xprt_alloc_bc_request(xprt);
+	/* Look up and lock the request corresponding to the given XID */
+	spin_lock(&xprt->transport_lock);
+	req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
 	if (req == NULL) {
+		spin_unlock(&xprt->transport_lock);
 		printk(KERN_WARNING "Callback slot table overflowed\n");
 		xprt_force_disconnect(xprt);
 		return -1;
 	}
 
-	req->rq_xid = transport->tcp_xid;
 	dprintk("RPC:       read callback  XID %08x\n", ntohl(req->rq_xid));
 	xs_tcp_read_common(xprt, desc, req);
 
-	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
-		struct svc_serv *bc_serv = xprt->bc_serv;
-
-		/*
-		 * Add callback request to callback list.  The callback
-		 * service sleeps on the sv_cb_waitq waiting for new
-		 * requests.  Wake it up after adding enqueing the
-		 * request.
-		 */
-		dprintk("RPC:       add callback request to list\n");
-		spin_lock(&bc_serv->sv_cb_lock);
-		list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
-		spin_unlock(&bc_serv->sv_cb_lock);
-		wake_up(&bc_serv->sv_cb_waitq);
-	}
-
-	req->rq_private_buf.len = transport->tcp_copied;
+	if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
+		xprt_complete_bc_request(req, transport->tcp_copied);
+	spin_unlock(&xprt->transport_lock);
 
 	return 0;
 }
-- 
1.8.5.3


^ permalink raw reply related	[flat|nested] 206+ messages in thread

* [PATCH] net/bonding: fix reset active slave
       [not found] <no>
                   ` (37 preceding siblings ...)
  2014-02-08  2:29 ` [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff shaobingqing
@ 2019-02-18 11:59 ` Hari Kumar Vemula
  2019-02-18 15:58   ` Radu Nicolau
  38 siblings, 1 reply; 206+ messages in thread
From: Hari Kumar Vemula @ 2019-02-18 11:59 UTC (permalink / raw)
  To: dev
  Cc: reshma.pattan, radu.nicolau, jananeex.m.parthasarathy,
	Hari Kumar Vemula, stable

test_alb_reply_from_client test fails due to incorrect active slave
array's index. This was due to invalid active slave count.

Count of internals->active_slave is not updated even when active slave
is deactivated.
Hence active slave count always keeps incrementing beyond the actual
active slaves.

Fix is to set the internals->active_slave to starting index 0 whenever
it exceeds the number of slaves in active slave list and also update
the active slave count during slave de-activation.

Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
Cc: stable@dpdk.org

Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
---
 drivers/net/bonding/rte_eth_bond_api.c | 6 ++++++
 drivers/net/bonding/rte_eth_bond_pmd.c | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bonding/rte_eth_bond_api.c b/drivers/net/bonding/rte_eth_bond_api.c
index e5e146540..ac084c4fd 100644
--- a/drivers/net/bonding/rte_eth_bond_api.c
+++ b/drivers/net/bonding/rte_eth_bond_api.c
@@ -129,6 +129,12 @@ deactivate_slave(struct rte_eth_dev *eth_dev, uint16_t port_id)
 	RTE_ASSERT(active_count < RTE_DIM(internals->active_slaves));
 	internals->active_slave_count = active_count;
 
+	/* Resetting active_slave when reaches to max
+	 * no of slaves in active list
+	 */
+	if (internals->active_slave >= active_count)
+		internals->active_slave = 0;
+
 	if (eth_dev->data->dev_started) {
 		if (internals->mode == BONDING_MODE_8023AD) {
 			bond_mode_8023ad_start(eth_dev);
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 23cec2549..319215c0b 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -84,7 +84,7 @@ bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			active_slave = 0;
 	}
 
-	if (++internals->active_slave == slave_count)
+	if (++internals->active_slave >= slave_count)
 		internals->active_slave = 0;
 	return num_rx_total;
 }
@@ -288,7 +288,7 @@ bond_ethdev_rx_burst_8023ad_fast_queue(void *queue, struct rte_mbuf **bufs,
 			active_slave = 0;
 	}
 
-	if (++internals->active_slave == slave_count)
+	if (++internals->active_slave >= slave_count)
 		internals->active_slave = 0;
 
 	return num_rx_total;
@@ -474,7 +474,7 @@ bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
 			idx = 0;
 	}
 
-	if (++internals->active_slave == slave_count)
+	if (++internals->active_slave >= slave_count)
 		internals->active_slave = 0;
 
 	return num_rx_total;
-- 
2.17.2

^ permalink raw reply related	[flat|nested] 206+ messages in thread

* Re: [PATCH] net/bonding: fix reset active slave
  2019-02-18 11:59 ` [PATCH] net/bonding: fix reset active slave Hari Kumar Vemula
@ 2019-02-18 15:58   ` Radu Nicolau
  2019-02-20 12:33     ` [dpdk-stable] " Ferruh Yigit
  0 siblings, 1 reply; 206+ messages in thread
From: Radu Nicolau @ 2019-02-18 15:58 UTC (permalink / raw)
  To: Hari Kumar Vemula, dev
  Cc: Pattan, Reshma, JananeeX M, Declan, jananeex.m.parthasarathy, stable



On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
> test_alb_reply_from_client test fails due to incorrect active slave
> array's index. This was due to invalid active slave count.
>
> Count of internals->active_slave is not updated even when active slave
> is deactivated.
> Hence active slave count always keeps incrementing beyond the actual
> active slaves.
>
> Fix is to set the internals->active_slave to starting index 0 whenever
> it exceeds the number of slaves in active slave list and also update
> the active slave count during slave de-activation.
>
> Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
> Cc: stable@dpdk.org
>
> Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
> ---
>
Acked-by: Radu Nicolau <radu.nicolau@intel.com 
<mailto:radu.nicolau@intel.com>>

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [dpdk-stable] [PATCH] net/bonding: fix reset active slave
  2019-02-18 15:58   ` Radu Nicolau
@ 2019-02-20 12:33     ` Ferruh Yigit
  2019-02-20 14:56       ` Radu Nicolau
  0 siblings, 1 reply; 206+ messages in thread
From: Ferruh Yigit @ 2019-02-20 12:33 UTC (permalink / raw)
  To: Radu Nicolau, Hari Kumar Vemula, dev
  Cc: Pattan, Reshma, JananeeX M, Declan, stable, Hyong Youb Kim

On 2/18/2019 3:58 PM, Radu Nicolau wrote:
> 
> 
> On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
>> test_alb_reply_from_client test fails due to incorrect active slave
>> array's index. This was due to invalid active slave count.
>>
>> Count of internals->active_slave is not updated even when active slave
>> is deactivated.
>> Hence active slave count always keeps incrementing beyond the actual
>> active slaves.
>>
>> Fix is to set the internals->active_slave to starting index 0 whenever
>> it exceeds the number of slaves in active slave list and also update
>> the active slave count during slave de-activation.
>>
>> Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
>> Cc: stable@dpdk.org
>>
>> Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
>> ---
>>
> Acked-by: Radu Nicolau <radu.nicolau@intel.com 
> <mailto:radu.nicolau@intel.com>>

Hi Radu, Hari,

There is another bonding patch, can you please check how related are they and if
are these fixing same root cause:

net/bonding: avoid the next active slave going out of bound
https://patches.dpdk.org/patch/49573/

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [dpdk-stable] [PATCH] net/bonding: fix reset active slave
  2019-02-20 12:33     ` [dpdk-stable] " Ferruh Yigit
@ 2019-02-20 14:56       ` Radu Nicolau
  2019-02-20 15:16         ` Hyong Youb Kim
  0 siblings, 1 reply; 206+ messages in thread
From: Radu Nicolau @ 2019-02-20 14:56 UTC (permalink / raw)
  To: Ferruh Yigit, Hari Kumar Vemula, dev
  Cc: Pattan, Reshma, JananeeX M, Declan, stable, Hyong Youb Kim



On 2/20/2019 12:33 PM, Ferruh Yigit wrote:
> On 2/18/2019 3:58 PM, Radu Nicolau wrote:
>>
>> On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
>>> test_alb_reply_from_client test fails due to incorrect active slave
>>> array's index. This was due to invalid active slave count.
>>>
>>> Count of internals->active_slave is not updated even when active slave
>>> is deactivated.
>>> Hence active slave count always keeps incrementing beyond the actual
>>> active slaves.
>>>
>>> Fix is to set the internals->active_slave to starting index 0 whenever
>>> it exceeds the number of slaves in active slave list and also update
>>> the active slave count during slave de-activation.
>>>
>>> Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
>>> Cc: stable@dpdk.org
>>>
>>> Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
>>> ---
>>>
>> Acked-by: Radu Nicolau <radu.nicolau@intel.com
>> <mailto:radu.nicolau@intel.com>>
> Hi Radu, Hari,
>
> There is another bonding patch, can you please check how related are they and if
> are these fixing same root cause:
>
> net/bonding: avoid the next active slave going out of bound
> https://patches.dpdk.org/patch/49573/
>
Hi, it's a similar fix for the same root cause, but this one covers more 
(or all) situations that can cause active_slave to go out of bounds.

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [dpdk-stable] [PATCH] net/bonding: fix reset active slave
  2019-02-20 14:56       ` Radu Nicolau
@ 2019-02-20 15:16         ` Hyong Youb Kim
  2019-02-22  1:52           ` Chas Williams
  0 siblings, 1 reply; 206+ messages in thread
From: Hyong Youb Kim @ 2019-02-20 15:16 UTC (permalink / raw)
  To: Radu Nicolau
  Cc: Ferruh Yigit, Hari Kumar Vemula, dev, Pattan, Reshma, JananeeX M,
	Declan, stable

On Wed, Feb 20, 2019 at 02:56:36PM +0000, Radu Nicolau wrote:
> 
> 
> On 2/20/2019 12:33 PM, Ferruh Yigit wrote:
> > On 2/18/2019 3:58 PM, Radu Nicolau wrote:
> > > 
> > > On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
> > > > test_alb_reply_from_client test fails due to incorrect active slave
> > > > array's index. This was due to invalid active slave count.
> > > > 
> > > > Count of internals->active_slave is not updated even when active slave
> > > > is deactivated.
> > > > Hence active slave count always keeps incrementing beyond the actual
> > > > active slaves.
> > > > 
> > > > Fix is to set the internals->active_slave to starting index 0 whenever
> > > > it exceeds the number of slaves in active slave list and also update
> > > > the active slave count during slave de-activation.
> > > > 
> > > > Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
> > > > Cc: stable@dpdk.org
> > > > 
> > > > Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
> > > > ---
> > > > 
> > > Acked-by: Radu Nicolau <radu.nicolau@intel.com
> > > <mailto:radu.nicolau@intel.com>>
> > Hi Radu, Hari,
> > 
> > There is another bonding patch, can you please check how related are they and if
> > are these fixing same root cause:
> > 
> > net/bonding: avoid the next active slave going out of bound
> > https://patches.dpdk.org/patch/49573/
> > 
> Hi, it's a similar fix for the same root cause, but this one covers more (or
> all) situations that can cause active_slave to go out of bounds.

If it covers more cases, please go with the new patch and drop mine. I
just want to see the issue fixed :-)

Thanks.
-Hyong

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [dpdk-stable] [PATCH] net/bonding: fix reset active slave
  2019-02-20 15:16         ` Hyong Youb Kim
@ 2019-02-22  1:52           ` Chas Williams
  2019-02-22 13:57             ` Ferruh Yigit
  0 siblings, 1 reply; 206+ messages in thread
From: Chas Williams @ 2019-02-22  1:52 UTC (permalink / raw)
  To: Hyong Youb Kim, Radu Nicolau
  Cc: Ferruh Yigit, Hari Kumar Vemula, dev, Pattan, Reshma, JananeeX M,
	Declan, stable



On 2/20/19 10:16 AM, Hyong Youb Kim wrote:
> On Wed, Feb 20, 2019 at 02:56:36PM +0000, Radu Nicolau wrote:
>>
>>
>> On 2/20/2019 12:33 PM, Ferruh Yigit wrote:
>>> On 2/18/2019 3:58 PM, Radu Nicolau wrote:
>>>>
>>>> On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
>>>>> test_alb_reply_from_client test fails due to incorrect active slave
>>>>> array's index. This was due to invalid active slave count.
>>>>>
>>>>> Count of internals->active_slave is not updated even when active slave
>>>>> is deactivated.
>>>>> Hence active slave count always keeps incrementing beyond the actual
>>>>> active slaves.
>>>>>
>>>>> Fix is to set the internals->active_slave to starting index 0 whenever
>>>>> it exceeds the number of slaves in active slave list and also update
>>>>> the active slave count during slave de-activation.
>>>>>
>>>>> Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
>>>>> Cc: stable@dpdk.org
>>>>>
>>>>> Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
>>>>> ---
>>>>>
>>>> Acked-by: Radu Nicolau <radu.nicolau@intel.com

Acked-by: Chas Williams <chas3@att.com>

>>>> <mailto:radu.nicolau@intel.com>>
>>> Hi Radu, Hari,
>>>
>>> There is another bonding patch, can you please check how related are they and if
>>> are these fixing same root cause:
>>>
>>> net/bonding: avoid the next active slave going out of bound
>>> https://patches.dpdk.org/patch/49573/
>>>
>> Hi, it's a similar fix for the same root cause, but this one covers more (or
>> all) situations that can cause active_slave to go out of bounds.
> 
> If it covers more cases, please go with the new patch and drop mine. I
> just want to see the issue fixed :-)

Yes, it does cover a few more cases. There really isn't any coordination
between slave activation/deactivation and the rx/tx burst routines. So
checking at the beginning or the end of the various routines is about
the same.

> Thanks.
> -Hyong
> 

^ permalink raw reply	[flat|nested] 206+ messages in thread

* Re: [dpdk-stable] [PATCH] net/bonding: fix reset active slave
  2019-02-22  1:52           ` Chas Williams
@ 2019-02-22 13:57             ` Ferruh Yigit
  0 siblings, 0 replies; 206+ messages in thread
From: Ferruh Yigit @ 2019-02-22 13:57 UTC (permalink / raw)
  To: Chas Williams, Hyong Youb Kim, Radu Nicolau
  Cc: Hari Kumar Vemula, dev, Pattan, Reshma, JananeeX M, Declan, stable

On 2/22/2019 1:52 AM, Chas Williams wrote:
> 
> 
> On 2/20/19 10:16 AM, Hyong Youb Kim wrote:
>> On Wed, Feb 20, 2019 at 02:56:36PM +0000, Radu Nicolau wrote:
>>>
>>>
>>> On 2/20/2019 12:33 PM, Ferruh Yigit wrote:
>>>> On 2/18/2019 3:58 PM, Radu Nicolau wrote:
>>>>>
>>>>> On 2/18/2019 11:59 AM, Hari Kumar Vemula wrote:
>>>>>> test_alb_reply_from_client test fails due to incorrect active slave
>>>>>> array's index. This was due to invalid active slave count.
>>>>>>
>>>>>> Count of internals->active_slave is not updated even when active slave
>>>>>> is deactivated.
>>>>>> Hence active slave count always keeps incrementing beyond the actual
>>>>>> active slaves.
>>>>>>
>>>>>> Fix is to set the internals->active_slave to starting index 0 whenever
>>>>>> it exceeds the number of slaves in active slave list and also update
>>>>>> the active slave count during slave de-activation.
>>>>>>
>>>>>> Fixes: e1110e977648 ("net/bonding: fix Rx slave fairness")
>>>>>> Cc: stable@dpdk.org
>>>>>>
>>>>>> Signed-off-by: Hari Kumar Vemula <hari.kumarx.vemula@intel.com>
>>>>>> ---
>>>>>>
>>>>> Acked-by: Radu Nicolau <radu.nicolau@intel.com
> 
> Acked-by: Chas Williams <chas3@att.com>

Applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 206+ messages in thread

end of thread, other threads:[~2019-02-22 13:57 UTC | newest]

Thread overview: 206+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <no>
2008-08-15  2:20 ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Yinghai Lu
2008-08-15  2:20   ` [PATCH 1/7] x86: some debug info for 32bit sparse_irq Yinghai Lu
2008-08-15  2:20     ` [PATCH 2/7] x86: remove union about dest for log/phy Yinghai Lu
2008-08-15  2:20       ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Yinghai Lu
2008-08-15  2:20         ` [PATCH 4/7] x86_64: rename irq_desc/irq_desc_with_new - fix Yinghai Lu
2008-08-15  2:20           ` [PATCH 5/7] x86: make 32bit support per_cpu vector fix #2 Yinghai Lu
2008-08-15  2:20             ` [PATCH 6/7] x86: ordering functions in io_apic_32.c Yinghai Lu
2008-08-15  2:20               ` [PATCH 7/7] x86: ordering functions in io_apic_64.c Yinghai Lu
2008-08-15  8:21         ` [PATCH 3/7] x86: make 32bit support per_cpu vector fix #1 Ingo Molnar
2008-08-15  8:29           ` Yinghai Lu
2008-08-15  8:51             ` Ingo Molnar
2008-08-15  8:27   ` [PATCH 00/07] dyn_array/nr_irqs/sparse_irq support v10 - fix Ingo Molnar
2008-08-15  8:34     ` Yinghai Lu
2008-08-15  8:51       ` Ingo Molnar
2008-08-15  9:35         ` Ingo Molnar
2008-08-15 10:00           ` Peter Zijlstra
2008-08-15 10:19             ` Ingo Molnar
2008-08-15 10:28               ` Peter Zijlstra
2008-08-15 17:07                 ` Yinghai Lu
2008-08-15 23:42 ` [PATCH 0/7] merge io_apic_xx.c Yinghai Lu
2008-08-15 23:42   ` [PATCH 1/7] x86: ordering functions in io_apic_32.c - fix Yinghai Lu
2008-08-15 23:42     ` [PATCH 2/7] x86: make headers files the smae in io_apic_xx.c Yinghai Lu
2008-08-15 23:42       ` [PATCH 3/7] x86: make 64 handle sis_apic_bug like the 32 bit Yinghai Lu
2008-08-15 23:42         ` [PATCH 4/7] x86: remve ioapic_force Yinghai Lu
2008-08-15 23:42           ` [PATCH 5/7] x86: make io_apic_64.c and io_apic_32.c the same Yinghai Lu
2008-08-15 23:42             ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Yinghai Lu
2008-08-15 23:42               ` [PATCH 7/7] make 32 bit have io_apic resource in /proc/iomem Yinghai Lu
2008-08-16  8:02               ` [PATCH 6/7] rename io_apic_64.c to io_apic.c Ingo Molnar
2008-08-16  8:22                 ` [PATCH] x86: io_apic.c, build fix Ingo Molnar
2008-08-16  8:26                   ` Yinghai Lu
2008-08-18  4:12 ` [PATCH] x86: apic - unify lapic_resume - fix Yinghai Lu
2008-08-18  4:12   ` [PATCH 1/2] x86: make HAVE_SPARSE_IRQ support selectable Yinghai Lu
2008-08-18  4:12     ` [PATCH 2/2] irq: rename irq_desc() to to_irq_desc() Yinghai Lu
2008-08-18  7:37       ` Ingo Molnar
2008-08-18 18:14         ` Yinghai Lu
2008-08-18  7:25   ` [PATCH] x86: apic - unify lapic_resume - fix Ingo Molnar
2008-08-18 20:44 ` [PATCH] irq: rename irq_desc() to to_irq_desc() " Yinghai Lu
2008-08-18 20:44   ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #2 Yinghai Lu
2008-08-18 20:44     ` [PATCH] irq: rename irq_desc() to to_irq_desc() - fix #3 Yinghai Lu
2008-08-19  0:11       ` Ingo Molnar
2008-08-19  0:38         ` Ingo Molnar
2008-08-19  0:48           ` Yinghai Lu
2008-08-19  1:16             ` Ingo Molnar
2010-04-15  9:02 ` [U-Boot] [PATCH] OpenRD: Bring PCIe endpoint out of reset Tanmay Upadhyay
2010-04-20  5:51 ` Tanmay Upadhyay
2010-04-30  6:49   ` Prafulla Wadaskar
2010-04-22 13:16 ` [PATCH] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
2010-05-04 12:48 ` [U-Boot] [PATCH] OpenRD: Reset PCIe endpoint while boot-up through PERST# Tanmay Upadhyay
2010-06-10  9:12 ` [U-Boot] [PATCH] ARM: Kirkwood: Add support for OpenRD-Client & OpenRD-Ultimate Tanmay Upadhyay
2010-06-10  9:16   ` Simon Kagstrom
2010-06-10  9:38     ` Tanmay Upadhyay
2010-06-10 10:25       ` Simon Kagstrom
2010-06-10 19:03         ` Prafulla Wadaskar
2010-06-14 11:02           ` Tanmay Upadhyay
2010-06-13 11:53   ` Albert ARIBAUD
2010-06-13 12:41     ` Wolfgang Denk
2010-06-13 12:51     ` Wolfgang Denk
2010-06-13 13:39       ` Albert ARIBAUD
2010-08-10  8:29 ` [PATCH v2] OpenRD: Enable SD/UART selection for serial port 1 Tanmay Upadhyay
2010-08-10  8:56   ` Alexander Clouter
2010-08-10  8:58     ` Alexander Clouter
2010-08-10 10:27       ` Tanmay Upadhyay
2010-08-10 10:28         ` Alexander Clouter
2010-08-10 10:49           ` Tanmay Upadhyay
2010-08-10 11:53             ` Alexander Clouter
2010-08-11  5:21               ` Tanmay Upadhyay
2010-08-10  8:40 ` [PATCH] ARM: Fix broken Kconfig in arch/arm Tanmay Upadhyay
2011-03-02  8:38 ` [RFC PATCH 1/5] x86/Kconfig: Add Page Cache Accounting entry Liu Yuan
2011-03-02  8:38   ` Liu Yuan
2011-03-02 16:24   ` Randy Dunlap
2011-03-02 16:24     ` Randy Dunlap
2011-03-03  3:11     ` Liu Yuan
2011-03-02  8:38 ` [RFC PATCH 2/5] block: Add functions and data types for Page Cache Accounting Liu Yuan
2011-03-02  8:38   ` Liu Yuan
2011-03-02  8:38 ` [RFC PATCH 3/5] block: Make Page Cache counters work with sysfs Liu Yuan
2011-03-02  8:38   ` Liu Yuan
2011-03-02  8:38 ` [RFC PATCH 4/5] mm: Add hit/miss accounting for Page Cache Liu Yuan
2011-03-02  8:38   ` Liu Yuan
2011-03-02  8:45   ` Ingo Molnar
2011-03-02  8:45     ` Ingo Molnar
2011-03-02 17:02     ` Dave Hansen
2011-03-02 17:02       ` Dave Hansen
2011-03-02 18:49       ` Ingo Molnar
2011-03-02 18:49         ` Ingo Molnar
2011-03-03  0:33         ` Wu Fengguang
2011-03-03  0:33           ` Wu Fengguang
2011-03-03  2:01     ` KOSAKI Motohiro
2011-03-03  2:01       ` KOSAKI Motohiro
2011-03-03  3:14     ` Tao Ma
2011-03-03  3:14       ` Tao Ma
2011-03-03  9:34       ` Ingo Molnar
2011-03-03  9:34         ` Ingo Molnar
2011-03-03 15:08         ` Tao Ma
2011-03-03 15:08           ` Tao Ma
2011-03-02  8:38 ` [RFC PATCH 5/5] mm: Add readpages accounting Liu Yuan
2011-03-02  8:38   ` Liu Yuan
2011-04-18 15:06 ` [v2 0/7] OMAP: GPIO: Use PM runtime framework Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-19  6:26   ` Tony Lindgren
2011-04-19  6:26     ` Tony Lindgren
2011-04-20 23:59     ` Kevin Hilman
2011-04-20 23:59       ` Kevin Hilman
2011-04-21  5:42       ` Tony Lindgren
2011-04-21  5:42         ` Tony Lindgren
2011-04-21 15:15         ` Kevin Hilman
2011-04-21 15:15           ` Kevin Hilman
2011-04-22  6:11           ` Tony Lindgren
2011-04-22  6:11             ` Tony Lindgren
2011-04-23  8:35         ` Linus Walleij
2011-04-23  8:35           ` Linus Walleij
2011-04-26  7:29           ` Tony Lindgren
2011-04-26  7:29             ` Tony Lindgren
2011-04-27 13:18             ` Linus Walleij
2011-04-27 13:18               ` Linus Walleij
2011-05-03 16:22               ` Kevin Hilman
2011-05-03 16:22                 ` Kevin Hilman
2011-05-03 21:41                 ` Linus Walleij
2011-05-03 21:41                   ` Linus Walleij
2011-05-04  6:19                   ` Tony Lindgren
2011-05-04  6:19                     ` Tony Lindgren
2011-05-12  0:57                     ` Linus Walleij
2011-05-12  0:57                       ` Linus Walleij
2011-05-12  9:42                       ` Kevin Hilman
2011-05-12  9:42                         ` Kevin Hilman
2011-05-19 19:08                         ` Grant Likely
2011-05-19 19:08                           ` Grant Likely
2011-05-20  3:34                           ` Shawn Guo
2011-05-20  3:34                             ` Shawn Guo
2011-05-19 19:05                       ` Grant Likely
2011-05-19 19:05                         ` Grant Likely
2011-04-18 15:06 ` [PATCH 1/7] OMAP: GPIO: Make gpio_context part of gpio_bank structure Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-18 15:06 ` [PATCH 2/7] OMAP: GPIO: Use flag to identify wkup dmn GPIO Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-18 15:06 ` [PATCH 3/7] OMAP4: GPIO: Save/restore context Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-21  0:26   ` Kevin Hilman
2011-04-21  0:26     ` Kevin Hilman
2011-04-18 15:06 ` [PATCH 4/7] OMAP: GPIO: handle save/restore ctx in GPIO driver Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-18 15:06 ` [PATCH 5/7] OMAP2+: GPIO: make workaround_enabled bank specific Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-18 15:06 ` [PATCH 6/7] OMAP: GPIO: Cleanup prepare_for_idle/resume Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-04-18 15:06 ` [PATCH 7/7] OMAP: GPIO: use PM runtime framework Varadarajan, Charulatha
2011-04-18 15:06   ` Varadarajan, Charulatha
2011-07-05  7:17 ` [U-Boot] [PATCH v2] Armada100: Add Board Support for Marvell GuruPlug-Display Ajay Bhargav
2011-07-06  5:49   ` Prafulla Wadaskar
2011-07-14  9:37 ` [PATCH 1/2] ARM: pxa168: gplugD: Get rid of mfp-gplugd.h Tanmay Upadhyay
2011-07-18  6:00   ` Eric Miao
2011-07-14  9:37 ` [PATCH 2/2] ARM: pxa168: gplugD: bug-fix: Free correct GPIO Tanmay Upadhyay
2011-07-18  5:59   ` Eric Miao
2011-09-14  5:59 ` [PATCH] mmc: sdhci-pxa: Check pdata before using its members Tanmay Upadhyay
2011-09-14  6:15   ` zhangfei gao
2011-09-21 18:12   ` Chris Ball
2011-11-14  9:43 ` [U-Boot] [Patch V2] mmc: mv_sdhci: Fix host version read for Armada100 Ajay Bhargav
2011-11-25 23:44   ` Andy Fleming
2011-12-06 11:07 ` [PATCH] USB: pxa168: Fix compilation error Tanmay Upadhyay
2011-12-06 11:25   ` Sergei Shtylyov
2011-12-08  4:33     ` [PATCH v2] " Tanmay Upadhyay
2011-12-07 19:57   ` [PATCH] " Alan Stern
2012-02-07 22:58 ` [PATCH v2] add support for AR6003 2048 byte board file Prasanna Kumar
2012-02-08  9:41   ` Kalle Valo
2012-07-10 13:46 ` [Qemu-devel] [PATCH] pseries iommu: h_put_tce split to support more IOMMUs Alexey Kardashevskiy
2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: removed cached qemu_irq from PCI host bus Alexey Kardashevskiy
2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries: added allocator for a block of IRQs Alexey Kardashevskiy
2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries pci: enable debugging with disabled emulated PCI bus Alexey Kardashevskiy
2012-07-10 13:46   ` [Qemu-devel] [PATCH] xics: added end-of-interrupt (EOI) handlers Alexey Kardashevskiy
2012-07-13  8:04     ` Alexey Kardashevskiy
2012-07-10 13:46   ` [Qemu-devel] [PATCH] pseries dma: DMA window params added to PHB and DT population changed Alexey Kardashevskiy
2012-07-25  5:20 ` [PATCH] fixed a macro coding style issue Baodong Chen
2012-07-25  5:27   ` Venu Byravarasu
2012-07-25  5:37   ` Dmitry Torokhov
2012-07-25  6:09     ` Baodong Chen
2012-07-25  6:15     ` Al Viro
2012-07-25  6:36       ` Dmitry Torokhov
2012-07-31  7:27         ` Dmitry Torokhov
2012-09-27 12:51 ` [PATCH 1/8] fs/namespace.c: introduce helper function path_unmounted() Yan Hong
2012-09-27 12:51   ` [PATCH 2/8] fs/namespace.c: remove unused macro MNT_WRITER_UNDERFLOW_LIMIT Yan Hong
2012-09-27 12:51   ` [PATCH 3/8] fs/namespace.c: trivial code clean Yan Hong
2012-09-27 12:51   ` [PATCH 4/8] fs/namespace.c: check permission early in sys_[u]mount Yan Hong
2012-09-27 12:51   ` [PATCH 5/8] fs/namei.c: introduce macro AT_FDINV Yan Hong
2012-09-27 12:51   ` [PATCH 6/8] fs/inode.c: call alloc_inode() in new_inode() directly Yan Hong
2012-09-27 12:51   ` [PATCH 7/8] fs/inode.c: remove outstanding spin lock prefetch Yan Hong
2012-09-27 12:51   ` [PATCH 8/8] vfs: misc comment clean Yan Hong
2013-01-07 18:11 ` [PATCH] Staging: android: fixed const coding style issue in binder.c Patrik Karlin
2013-01-07 23:01   ` Greg KH
2013-11-11  9:27 ` [PATCH 1/2] mklibs: add dependency on dpkg-native Lei Liu
2013-11-11  9:27 ` [PATCH 2/2] Fix grep pattern when mklibs collects executables in rootfs Lei Liu
2013-11-12 10:23   ` Richard Purdie
2013-11-13  3:05     ` Lei Liu
2013-11-22 22:33       ` Nicolas Dechesne
     [not found]         ` <52955AAB.6000801@gmail.com>
2013-11-27 13:00           ` Nicolas Dechesne
2014-02-08  2:29 ` [PATCH v2] SUNRPC: Allow one callback request to be received from two sk_buff shaobingqing
2014-02-08 19:14   ` Sergei Shtylyov
2014-02-08 19:14     ` Sergei Shtylyov
2014-02-10 17:46   ` Trond Myklebust
2014-02-10 17:46     ` Trond Myklebust
2014-02-11 19:42     ` [PATCH v2] SUNRPC: RPC callbacks may be split across several TCP segments Trond Myklebust
2019-02-18 11:59 ` [PATCH] net/bonding: fix reset active slave Hari Kumar Vemula
2019-02-18 15:58   ` Radu Nicolau
2019-02-20 12:33     ` [dpdk-stable] " Ferruh Yigit
2019-02-20 14:56       ` Radu Nicolau
2019-02-20 15:16         ` Hyong Youb Kim
2019-02-22  1:52           ` Chas Williams
2019-02-22 13:57             ` Ferruh Yigit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.