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
--
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
--- ...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 ...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" ...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 --
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, ...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 ...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 = ...unrelated sidenote - shouldnt the scheduler define cpu_online_map to cpumask_of_cpu(0) on UP, to avoid such ugly #ifdefs? Ingo --
copy that from mach_default... should double check if cpu_online_map is cpu_mask_of_cpu(0) if !CONFIG_SMP YH --
yeah. Separate clean-up patch i think. Ingo --
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 --
current arch code use irq_desc directly..., if need to irq_desc to them, need to provide set_irq(..., ...) YH --
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
--
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 ...
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
--
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 --
/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
--
