Messages in this thread Patch in this message | | | From | OGAWA Hirofumi <> | Subject | Oops in clockevents_notify()'s BUG_ON | Date | Sat, 26 Dec 2009 03:08:09 +0900 |
| |
Hi,
In poweroff process, I've got Oops in clockevents_notify()'s BUG_ON. After some investigation, "hpet" clockevent hits BUG_ON().
On x86_64, hpet_legacy_clockevent_register() registers clockevent as
hpet_legacy_clockevent_register() [...] /* * Start hpet with the boot cpu mask and make it * global after the IO_APIC has been initialized. */ hpet_clockevent.cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(&hpet_clockevent);
The comment says "boot cpu". But it's not true on x86_64, and one of my machine is "second cpu" actually. [This might be one of problems]
And on that machine, hpet is used as oneshot_broadcast.
Then, in poweroff process, it calls cpu_down() for the nonboot cpus if CONFIG_HOTPLUG_CPU is y. And clockevents_notify() checks clockevent in clockevent_devices
So, the following code see hpet for broadcast on clockevent_devices. And like mentioned above, hpet has cpumask like percpu clockevent, but it is using as broadcast. So, this hits BUG_ON().
clockevents_notify() [...] list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { if (cpumask_test_cpu(cpu, dev->cpumask) && cpumask_weight(dev->cpumask) == 1) { BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); list_del(&dev->list); } }
Well, so, attached patch fixes the problem on my machine. But I'm not sure if it's right thing. Can you check it?
Thanks. -- OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> ---
kernel/time/clockevents.c | 3 +++ 1 file changed, 3 insertions(+)
diff -puN kernel/time/clockevents.c~hpet-shutdown-fix kernel/time/clockevents.c --- linux-2.6/kernel/time/clockevents.c~hpet-shutdown-fix 2009-12-26 02:47:07.000000000 +0900 +++ linux-2.6-hirofumi/kernel/time/clockevents.c 2009-12-26 02:47:07.000000000 +0900 @@ -258,6 +258,9 @@ void clockevents_notify(unsigned long re */ cpu = *((int *)arg); list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) { + if (tick_is_broadcast_device(dev)) + continue; + if (cpumask_test_cpu(cpu, dev->cpumask) && cpumask_weight(dev->cpumask) == 1) { BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); _
| |