Messages in this thread Patch in this message | | | From | BlaisorBlade <> | Subject | [PATCH] Oops and panic while unloading holder of pm_idle | Date | Thu, 19 Aug 2004 18:31:22 +0200 |
| |
(CC me on replies as I'm not subscribed).
A short description, with my hypothesis about how the panic() happened:
My 2.6.7 preemptible kernel oopsed because when I unloaded the "processor" module (driver/acpi/processor.c), the pm_idle(see arch/i386/kernel/process.c) function he provided was called after the module being unloaded (notice that the "processor" module is not listed below).
I.e., cpu_idle did "idle = pm_idle", it was probably preempted (I run with CONFIG_PREEMPT=y), the processor module was unloaded, and then it called "(*idle)();". In fact it does not happen always (I just got again this panic by unloading the same module, and checked that the address was from the "processor", but I cannot get it again; don't ask me why it can be obtained only the first time it is unloaded, but not after reloading and re-unloading it).
This could happen as well on SMP, so we need a spinlock for accessing pm_idle. We could maybe as well use a semaphore (since we will always be in process context), but IMHO there is too much overhead. And it does not make sense for the idle thread to sleep while holding a semaphore (I don't know if it's a bug). So I attach spinlock-protect-pm_idle.patch (which corrects some more things on some archs). With this patch applied, I cannot reproduce the problem any more.
But that does not suffice: saying
static void (*pm_idle_save)(void); pm_idle_save = pm_idle; pm_idle = my_own_pm_idle;
does not work if you stack more modules onto it. Say, if module1 and module2 both install their pm_idle and then I unload module1 and after I unload module2: module2 will restore module1_pm_idle, so we get Oopses. I.e. we need a stack of pm_idle functions + some register_pm_idle() APIs. Do you agree?
This may be a bit overkill given that only APM and ACPI, and, on SPARC, arch/sparc/kernel/{apc,pmc}.c, define their pm_idle function. So, as an alternative, see this code (which assumes pm_idle is renamed to _pm_idle and unexported, to force changes in all drivers):
int install_pm_idle(void (*idle)(void)) { if (_pm_idle == NULL) { _pm_idle = idle; return 1; } else return 0; } EXPORT_SYMBOL(install_pm_idle);
Also, in my case, I don't think we have this kind of panic, because pm_idle is just defined by APM and ACPI (CONFIG_APM=y, and APM is not supported by my laptop). I also checked, when getting again the same panic, that the faulty EIP was actually inside the processor module (from /proc/modules).
And also, it PANICKED, but CONTINUED TO RUN: notice the last 3 lines: <0>Kernel panic: Attempted to kill the idle task! In idle task - not syncing <6>ACPI: Processor [CPU0] (supports C1 C2) The third one comes from reloading the "processor" module.
For reference, I attach the Oops output and the cpu_idle disassemble, so that you can check the EIP value. However I checked that it was actually calling pm_idle.
Unable to handle kernel paging request at virtual address e0e8a238 printing eip: e0e8a238 *pde = 1e1e1067 *pte = 00000000 Oops: 0000 [#1] PREEMPT Modules linked in: fan button battery non_fatal ac binfmt_misc snd_seq_oss snd_seq_midi_event snd_seq snd_pcm_oss snd_mixer_oss snd_intel8x0 snd_ac97_codec snd_pcm snd_timer snd_page_alloc gameport snd_mpu401_uart snd_rawmidi snd_seq_device snd soundcore af_packet ipv6 ds yenta_socket pcmcia_core eth1394 tg3 ohci1394 ieee1394 nls_iso8859_15 nls_cp850 vfat fat psmouse amd64_agp agpgart ide_cd cdrom sd_mod usb_storage scsi_mod tsdev evdev dm_mod usbhid usbmouse ehci_hcd ohci_hcd usbcore rtc CPU: 0 EIP: 0060:[<e0e8a238>] Not tainted EFLAGS: 00010212 (2.6.7) EIP is at 0xe0e8a238 eax: 00f6b2a4 ebx: 00008008 ecx: 00f6a78f edx: 00008008 esi: c15666b0 edi: c03d41c0 ebp: c1566600 esp: c03adfc8 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, threadinfo=c03ac000 task=c0330a40) Stack: 00099100 00099100 c03ac000 00099100 c03d41c0 00426007 c01020cd c03ac000 c03ae61d 00000012 c03ae370 c03d3fc0 00000800 c010019f Call Trace: [<c01020cd>] cpu_idle+0x2d/0x40 [<c03ae61d>] start_kernel+0x14d/0x170 [<c03ae370>] unknown_bootoption+0x0/0x120
Code: Bad EIP value. <0>Kernel panic: Attempted to kill the idle task! In idle task - not syncing <6>ACPI: Processor [CPU0] (supports C1 C2)
(gdb) disassemble cpu_idle Dump of assembler code for function cpu_idle: 0xc01020a0 <cpu_idle+0>: push %ebx 0xc01020a1 <cpu_idle+1>: mov $0xffffe000,%ebx 0xc01020a6 <cpu_idle+6>: and %esp,%ebx 0xc01020a8 <cpu_idle+8>: jmp 0xc01020cd <cpu_idle+45> 0xc01020aa <cpu_idle+10>: lea 0x0(%esi),%esi 0xc01020b0 <cpu_idle+16>: mov 0xc03d3504,%eax 0xc01020b5 <cpu_idle+21>: mov $0xc0102030,%edx 0xc01020ba <cpu_idle+26>: test %eax,%eax 0xc01020bc <cpu_idle+28>: cmove %edx,%eax 0xc01020bf <cpu_idle+31>: mov 0xc0331e40,%edx 0xc01020c5 <cpu_idle+37>: mov %edx,0xc03e8e84 0xc01020cb <cpu_idle+43>: call *%eax 0xc01020cd <cpu_idle+45>: mov 0x8(%ebx),%eax 0xc01020d0 <cpu_idle+48>: test $0x8,%al 0xc01020d2 <cpu_idle+50>: je 0xc01020b0 <cpu_idle+16> 0xc01020d4 <cpu_idle+52>: call 0xc02d9200 <schedule> 0xc01020d9 <cpu_idle+57>: jmp 0xc01020cd <cpu_idle+45> 0xc01020db <cpu_idle+59>: nop 0xc01020dc <cpu_idle+60>: lea 0x0(%esi,1),%esi
-- Paolo Giarrusso, aka Blaisorblade Linux registered user n. 292729
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it> ---
vanilla-linux-2.6.7-SKAS-paolo/arch/arm/kernel/process.c | 9 +++++- vanilla-linux-2.6.7-SKAS-paolo/arch/arm26/kernel/armksyms.c | 1 vanilla-linux-2.6.7-SKAS-paolo/arch/arm26/kernel/process.c | 7 ++++- vanilla-linux-2.6.7-SKAS-paolo/arch/cris/kernel/crisksyms.c | 2 + vanilla-linux-2.6.7-SKAS-paolo/arch/cris/kernel/process.c | 7 ++++- vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/apm.c | 4 ++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/i386_ksyms.c | 1 vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/process.c | 7 ++++- vanilla-linux-2.6.7-SKAS-paolo/arch/ia64/kernel/acpi.c | 2 + vanilla-linux-2.6.7-SKAS-paolo/arch/ia64/kernel/process.c | 5 ++- vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/apc.c | 5 ++- vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/pmc.c | 2 + vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/process.c | 9 +++++- vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/sparc_ksyms.c | 1 vanilla-linux-2.6.7-SKAS-paolo/arch/x86_64/kernel/process.c | 13 ++++++--- vanilla-linux-2.6.7-SKAS-paolo/arch/x86_64/kernel/x8664_ksyms.c | 1 vanilla-linux-2.6.7-SKAS-paolo/drivers/acpi/processor.c | 7 ++++- vanilla-linux-2.6.7-SKAS-paolo/include/linux/pm.h | 14 ++++++++++ 18 files changed, 84 insertions(+), 13 deletions(-)
diff -puN arch/arm/kernel/process.c~spinlock-protect-pm_idle arch/arm/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/arm/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/arm/kernel/process.c 2004-08-18 21:12:23.113797464 +0200 @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/kallsyms.h> #include <linux/init.h> +#include <linux/pm.h> #include <asm/system.h> #include <asm/io.h> @@ -78,6 +79,9 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL(pm_idle_lock); + /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. @@ -99,7 +103,9 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; preempt_disable(); @@ -108,6 +114,7 @@ void cpu_idle(void) idle(); leds_event(led_idle_end); preempt_enable(); + unlock_pm_idle(); schedule(); } } diff -puN arch/i386/kernel/process.c~spinlock-protect-pm_idle arch/i386/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/process.c 2004-08-17 21:04:06.000000000 +0200 @@ -36,6 +36,7 @@ #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/ptrace.h> +#include <linux/pm.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -69,6 +70,7 @@ unsigned long thread_saved_pc(struct tas * Powermanagement idle function, if any.. */ void (*pm_idle)(void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; void disable_hlt(void) { @@ -142,13 +144,16 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; irq_stat[smp_processor_id()].idle_timestamp = jiffies; idle(); + unlock_pm_idle(); } schedule(); } diff -puN arch/cris/kernel/process.c~spinlock-protect-pm_idle arch/cris/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/cris/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/cris/kernel/process.c 2004-08-17 21:06:28.000000000 +0200 @@ -112,6 +112,7 @@ #include <linux/fs.h> #include <linux/user.h> #include <linux/elfcore.h> +#include <linux/pm.h> //#define DEBUG @@ -179,6 +180,7 @@ EXPORT_SYMBOL(enable_hlt); * The following aren't currently used. */ void (*pm_idle)(void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; extern void default_idle(void); @@ -193,12 +195,15 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; idle(); + unlock_pm_idle(); } schedule(); } diff -puN arch/ia64/kernel/process.c~spinlock-protect-pm_idle arch/ia64/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/ia64/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/ia64/kernel/process.c 2004-08-17 20:57:07.000000000 +0200 @@ -228,7 +228,9 @@ cpu_idle (void *unused) /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; @@ -241,6 +243,7 @@ cpu_idle (void *unused) (*mark_idle)(1); (*idle)(); } + unlock_pm_idle(); if (mark_idle) (*mark_idle)(0); diff -puN arch/arm26/kernel/process.c~spinlock-protect-pm_idle arch/arm26/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/arm26/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/arm26/kernel/process.c 2004-08-17 21:04:06.000000000 +0200 @@ -26,6 +26,7 @@ #include <linux/reboot.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/pm.h> #include <asm/system.h> #include <asm/io.h> @@ -72,6 +73,7 @@ __setup("hlt", hlt_setup); */ void (*pm_idle)(void); void (*pm_power_off)(void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; /* * This is our default idle handler. We need to disable @@ -94,12 +96,15 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ preempt_disable(); while (1) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; leds_event(led_idle_start); while (!need_resched()) idle(); + unlock_pm_idle(); leds_event(led_idle_end); schedule(); } diff -puN arch/sparc/kernel/process.c~spinlock-protect-pm_idle arch/sparc/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/sparc/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/process.c 2004-08-17 21:04:06.000000000 +0200 @@ -48,6 +48,7 @@ * Set in pm platform drivers */ void (*pm_idle)(void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; /* * Power-off handler instantiation for pm.h compliance @@ -90,6 +91,7 @@ int cpu_idle(void) /* endless idle loop with no priority at all */ for (;;) { + void (*idle)(void); if (ARCH_SUN4C_SUN4) { static int count = HZ; static unsigned long last_jiffies; @@ -121,9 +123,12 @@ int cpu_idle(void) local_irq_restore(flags); } - while((!need_resched()) && pm_idle) { - (*pm_idle)(); /* XXX Huh? On sparc?! */ + lock_pm_idle(); + idle = pm_idle; + while((!need_resched()) && idle) { + (*idle)(); /* XXX Huh? On sparc?! */ } + unlock_pm_idle(); schedule(); check_pgt_cache(); diff -puN arch/x86_64/kernel/process.c~spinlock-protect-pm_idle arch/x86_64/kernel/process.c --- vanilla-linux-2.6.7-SKAS/arch/x86_64/kernel/process.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/x86_64/kernel/process.c 2004-08-17 21:04:06.000000000 +0200 @@ -33,6 +33,7 @@ #include <linux/irq.h> #include <linux/ptrace.h> #include <linux/version.h> +#include <linux/pm.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -58,6 +59,7 @@ atomic_t hlt_counter = ATOMIC_INIT(0); * Powermanagement idle function, if any.. */ void (*pm_idle)(void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; void disable_hlt(void) { @@ -130,11 +132,14 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; + void (*idle)(void); + lock_pm_idle(); + idle = pm_idle; if (!idle) idle = default_idle; while (!need_resched()) idle(); + unlock_pm_idle(); schedule(); } } @@ -170,8 +175,9 @@ void __init select_idle_routine(const st * Skip, if setup has overridden idle. * Also, take care of system with asymmetric CPUs. * Use, mwait_idle only if all cpus support it. - * If not, we fallback to default_idle() + * If not, we fallback to default_idle() in cpu_idle(). */ + lock_pm_idle(); if (!pm_idle) { if (!printed) { printk("using mwait in idle threads.\n"); @@ -179,10 +185,9 @@ void __init select_idle_routine(const st } pm_idle = mwait_idle; } + unlock_pm_idle(); return; } - pm_idle = default_idle; - return; } static int __init idle_setup (char *str) diff -puN arch/ia64/kernel/acpi.c~spinlock-protect-pm_idle arch/ia64/kernel/acpi.c --- vanilla-linux-2.6.7-SKAS/arch/ia64/kernel/acpi.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/ia64/kernel/acpi.c 2004-08-17 20:35:54.000000000 +0200 @@ -61,6 +61,8 @@ void (*pm_idle) (void); EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); +spinlock_t pm_idle_lock = SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL(pm_idle_lock); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; diff -puN arch/i386/kernel/apm.c~spinlock-protect-pm_idle arch/i386/kernel/apm.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/apm.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/apm.c 2004-08-17 20:57:07.000000000 +0200 @@ -2032,8 +2032,10 @@ static int __init apm_init(void) if (HZ != 100) idle_period = (idle_period * HZ) / 100; if (idle_threshold < 100) { + lock_pm_idle(); original_pm_idle = pm_idle; pm_idle = apm_cpu_idle; + unlock_pm_idle(); set_pm_idle = 1; } @@ -2044,8 +2046,10 @@ static void __exit apm_exit(void) { int error; + lock_pm_idle(); if (set_pm_idle) pm_idle = original_pm_idle; + unlock_pm_idle(); if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) && (apm_info.connection_version > 0x0100)) { error = apm_engage_power_management(APM_DEVICE_ALL, 0); diff -puN drivers/acpi/processor.c~spinlock-protect-pm_idle drivers/acpi/processor.c --- vanilla-linux-2.6.7-SKAS/drivers/acpi/processor.c~spinlock-protect-pm_idle 2004-08-17 20:21:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/drivers/acpi/processor.c 2004-08-17 20:57:07.000000000 +0200 @@ -2334,8 +2334,10 @@ acpi_processor_add ( * platforms that only support C1. */ if ((pr->id == 0) && (pr->flags.power)) { + lock_pm_idle(); pm_idle_save = pm_idle; pm_idle = acpi_processor_idle; + unlock_pm_idle(); } printk(KERN_INFO PREFIX "%s [%s] (supports", @@ -2373,8 +2375,11 @@ acpi_processor_remove ( pr = (struct acpi_processor *) acpi_driver_data(device); /* Unregister the idle handler when processor #0 is removed. */ - if (pr->id == 0) + if (pr->id == 0) { + lock_pm_idle(); pm_idle = pm_idle_save; + unlock_pm_idle(); + } status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, acpi_processor_notify); diff -puN include/linux/pm.h~spinlock-protect-pm_idle include/linux/pm.h --- vanilla-linux-2.6.7-SKAS/include/linux/pm.h~spinlock-protect-pm_idle 2004-08-17 20:22:20.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/linux/pm.h 2004-08-17 20:28:42.000000000 +0200 @@ -25,6 +25,7 @@ #include <linux/config.h> #include <linux/list.h> +#include <linux/spinlock.h> #include <asm/atomic.h> /* @@ -193,6 +194,19 @@ static inline void pm_dev_idle(struct pm extern void (*pm_idle)(void); extern void (*pm_power_off)(void); +extern spinlock_t pm_idle_lock; + +/*Not sure if this should be a semaphore...*/ +static inline int lock_pm_idle(void) +{ + spin_lock(&pm_idle_lock); + return 0; +} +static inline void unlock_pm_idle(void) +{ + spin_unlock(&pm_idle_lock); +} + enum { PM_SUSPEND_ON, PM_SUSPEND_STANDBY, diff -puN arch/i386/kernel/i386_ksyms.c~spinlock-protect-pm_idle arch/i386/kernel/i386_ksyms.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/i386_ksyms.c~spinlock-protect-pm_idle 2004-08-17 21:00:33.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/i386_ksyms.c 2004-08-17 21:04:06.000000000 +0200 @@ -84,6 +84,7 @@ EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); +EXPORT_SYMBOL(pm_idle_lock); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(cpu_khz); EXPORT_SYMBOL(apm_info); diff -puN arch/arm26/kernel/armksyms.c~spinlock-protect-pm_idle arch/arm26/kernel/armksyms.c --- vanilla-linux-2.6.7-SKAS/arch/arm26/kernel/armksyms.c~spinlock-protect-pm_idle 2004-08-17 21:00:33.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/arm26/kernel/armksyms.c 2004-08-17 21:04:06.000000000 +0200 @@ -115,6 +115,7 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(set_irq_type); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); +EXPORT_SYMBOL(pm_idle_lock); /* processor dependencies */ EXPORT_SYMBOL(__machine_arch_type); diff -puN arch/sparc/kernel/sparc_ksyms.c~spinlock-protect-pm_idle arch/sparc/kernel/sparc_ksyms.c --- vanilla-linux-2.6.7-SKAS/arch/sparc/kernel/sparc_ksyms.c~spinlock-protect-pm_idle 2004-08-17 21:00:34.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/sparc_ksyms.c 2004-08-17 21:04:06.000000000 +0200 @@ -323,3 +323,4 @@ EXPORT_SYMBOL(do_BUG); /* Sun Power Management Idle Handler */ EXPORT_SYMBOL(pm_idle); +EXPORT_SYMBOL(pm_idle_lock); diff -puN arch/x86_64/kernel/x8664_ksyms.c~spinlock-protect-pm_idle arch/x86_64/kernel/x8664_ksyms.c --- vanilla-linux-2.6.7-SKAS/arch/x86_64/kernel/x8664_ksyms.c~spinlock-protect-pm_idle 2004-08-17 21:00:34.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/x86_64/kernel/x8664_ksyms.c 2004-08-17 21:04:06.000000000 +0200 @@ -61,6 +61,7 @@ EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); +EXPORT_SYMBOL(pm_idle_lock); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL_NOVERS(__down_failed); diff -puN arch/sparc/kernel/pmc.c~spinlock-protect-pm_idle arch/sparc/kernel/pmc.c --- vanilla-linux-2.6.7-SKAS/arch/sparc/kernel/pmc.c~spinlock-protect-pm_idle 2004-08-17 21:00:34.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/pmc.c 2004-08-17 21:04:06.000000000 +0200 @@ -85,7 +85,9 @@ sbus_done: #ifndef PMC_NO_IDLE /* Assign power management IDLE handler */ + lock_pm_idle(); pm_idle = pmc_swift_idle; + unlock_pm_idle(); #endif printk(KERN_INFO "%s: power management initialized\n", PMC_DEVNAME); diff -puN arch/sparc/kernel/apc.c~spinlock-protect-pm_idle arch/sparc/kernel/apc.c --- vanilla-linux-2.6.7-SKAS/arch/sparc/kernel/apc.c~spinlock-protect-pm_idle 2004-08-17 21:00:34.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/sparc/kernel/apc.c 2004-08-17 21:04:06.000000000 +0200 @@ -170,8 +170,11 @@ sbus_done: } /* Assign power management IDLE handler */ - if(!apc_no_idle) + if(!apc_no_idle) { + lock_pm_idle(); pm_idle = apc_swift_idle; + unlock_pm_idle(); + } printk(KERN_INFO "%s: power management initialized%s\n", APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); diff -puN arch/cris/kernel/crisksyms.c~spinlock-protect-pm_idle arch/cris/kernel/crisksyms.c --- vanilla-linux-2.6.7-SKAS/arch/cris/kernel/crisksyms.c~spinlock-protect-pm_idle 2004-08-17 21:05:13.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/cris/kernel/crisksyms.c 2004-08-17 21:06:28.000000000 +0200 @@ -38,6 +38,8 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(loops_per_usec); +EXPORT_SYMBOL(pm_idle); +EXPORT_SYMBOL(pm_idle_lock); /* String functions */ EXPORT_SYMBOL(memcmp); _ | |