diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-28 18:16:45 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-28 18:19:55 -0500 |
commit | b2e2fe99628c4f944c3075258e536197b5a4f3f8 (patch) | |
tree | ad56d4853efc86c2c86e897b843a6438550d039c /kernel/irq | |
parent | 12026ea16a618b289fcf457661aed24f57323a20 (diff) |
sparseirq: work around __weak alias bug
Impact: fix boot crash if the kernel is built with certain GCC versions
GCC has a bug with __weak alias functions: if the functions are in
the same compilation unit as their call site, GCC can decide to
inline them - and thus rob the linker of the opportunity to override
the weak alias with the real thing.
This can lead to the boot crash reported by Kamalesh Babulal:
ACPI: Core revision 20080926
Setting APIC routing to flat
BUG: unable to handle kernel NULL pointer dereference at
0000000000000000
IP: [<ffffffff8021f9a8>] add_pin_to_irq_cpu+0x14/0x74
PGD 0
Oops: 0000 [#1] SMP
[...]
So move the arch_init_chip_data() function from handle.c to manage.c.
Reported-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/handle.c | 5 | ||||
-rw-r--r-- | kernel/irq/manage.c | 9 |
2 files changed, 9 insertions, 5 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 157c04c3b158..c20db0be9173 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -86,11 +86,6 @@ void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) | |||
86 | desc->kstat_irqs = (unsigned int *)ptr; | 86 | desc->kstat_irqs = (unsigned int *)ptr; |
87 | } | 87 | } |
88 | 88 | ||
89 | int __weak arch_init_chip_data(struct irq_desc *desc, int cpu) | ||
90 | { | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) | 89 | static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu) |
95 | { | 90 | { |
96 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); | 91 | memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 46953a06f4a8..c2741b02ad38 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -261,6 +261,15 @@ void enable_irq(unsigned int irq) | |||
261 | } | 261 | } |
262 | EXPORT_SYMBOL(enable_irq); | 262 | EXPORT_SYMBOL(enable_irq); |
263 | 263 | ||
264 | /* | ||
265 | * [ Not in kernel/irq/handle.c, so that GCC does not | ||
266 | * inline the __weak alias: ] | ||
267 | */ | ||
268 | int __weak arch_init_chip_data(struct irq_desc *desc, int cpu) | ||
269 | { | ||
270 | return 0; | ||
271 | } | ||
272 | |||
264 | static int set_irq_wake_real(unsigned int irq, unsigned int on) | 273 | static int set_irq_wake_real(unsigned int irq, unsigned int on) |
265 | { | 274 | { |
266 | struct irq_desc *desc = irq_to_desc(irq); | 275 | struct irq_desc *desc = irq_to_desc(irq); |