diff options
author | Ingo Molnar <mingo@elte.hu> | 2007-10-16 08:42:30 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 10:51:26 -0400 |
commit | c2cbdbb1583830b77f169a717407f035d6627793 (patch) | |
tree | f459d8c032609574b6a11971735cd1277dc6fc1b /sound/isa/gus/gus_irq.c | |
parent | c9b58006be7e471a5f55d171cbaa08f4aa8078ea (diff) |
[ALSA] fix bootup crash in snd_gus_interrupt()
when simulating a storm of fake GUS interrupts (without actually owning
this venerable piece of ISA hardware) the driver falls over (crashes) in
two ways:
1) spinlocks being initialized too late:
INFO: trying to register non-static key.
the code is fine but needs lockdep annotation.
turning off the locking correctness validator.
[<401058ca>] show_trace_log_lvl+0x1a/0x30
[<401064b2>] show_trace+0x12/0x20
[<401064d6>] dump_stack+0x16/0x20
[<4014a72b>] __lock_acquire+0xcfb/0x1030
[<4014aac0>] lock_acquire+0x60/0x80
[<40721a68>] _spin_lock_irqsave+0x38/0x50
[<4058fc12>] snd_gf1_i_look8+0x22/0x60
[<405906fe>] snd_gus_interrupt+0x13e/0x270
[<401548e8>] handle_IRQ_event+0x28/0x60
[<40155cc1>] handle_fasteoi_irq+0x71/0xe0
[<40107238>] do_IRQ+0x48/0xa0
[<401051fe>] common_interrupt+0x2e/0x40
[<40156822>] register_handler_proc+0x92/0xf0
[<401550c2>] setup_irq+0xe2/0x190
[<40155224>] request_irq+0xb4/0xd0
[<4058f524>] snd_gus_create+0x124/0x3c0
[<40aa4087>] snd_gusclassic_probe+0x2a7/0x4b0
[<403f5eff>] isa_bus_probe+0x1f/0x30
[<403f1944>] driver_probe_device+0x84/0x190
[<403f1a58>] __device_attach+0x8/0x10
[<403f0e63>] bus_for_each_drv+0x53/0x80
[<403f1b1b>] device_attach+0x8b/0x90
[<403f0dd8>] bus_attach_device+0x48/0x80
[<403efdbd>] device_add+0x45d/0x5a0
[<403eff12>] device_register+0x12/0x20
[<403f60c3>] isa_register_driver+0xb3/0x140
[<40aa3dd2>] alsa_card_gusclassic_init+0x12/0x20
[<40a665c3>] kernel_init+0x133/0x310
[<401054a7>] kernel_thread_helper+0x7/0x10
=======================
2) callback functions not being filled in yet:
BUG: unable to handle kernel NULL pointer dereference at virtual address 00000000
printing eip:
00000000
*pde = 00000000
Oops: 0000 [#1]
SMP DEBUG_PAGEALLOC
CPU: 0
EIP: 0060:[<00000000>] Not tainted VLI
EFLAGS: 00010002 (2.6.23 #37)
EIP is at 0x0
eax: 7fe94000 ebx: 7fe94000 ecx: 00000000 edx: 00000226
esi: 00000000 edi: 00000005 ebp: 7ff87c28 esp: 7ff87bf4
ds: 007b es: 007b fs: 00d8 gs: 0000 ss: 0068
Process swapper (pid: 1, ti=7ff86000 task=7ff84000 task.ti=7ff86000)
Stack: 40590683 408424a9 408db87c 00000029 40787406 00000064 00000046 ff000000
000000ff 00000001 7faefaf0 00000000 00000005 7ff87c40 401548e8 00000000
40a52000 7faefaf0 00000005 7ff87c58 40155cc1 40a52030 00000005 00000000
Call Trace:
[<401058ca>] show_trace_log_lvl+0x1a/0x30
[<4010598b>] show_stack_log_lvl+0xab/0xd0
[<40105b7c>] show_registers+0x1cc/0x2d0
[<40105d96>] die+0x116/0x240
[<4011d7bb>] do_page_fault+0x18b/0x670
[<40721d22>] error_code+0x72/0x80
[<401548e8>] handle_IRQ_event+0x28/0x60
[<40155cc1>] handle_fasteoi_irq+0x71/0xe0
[<40107238>] do_IRQ+0x48/0xa0
[<401051fe>] common_interrupt+0x2e/0x40
[<401a344e>] proc_create+0x3e/0x120
[<401a3733>] proc_mkdir_mode+0x23/0x50
[<401a376f>] proc_mkdir+0xf/0x20
[<40156864>] register_handler_proc+0xd4/0xf0
[<401550c2>] setup_irq+0xe2/0x190
[<40155224>] request_irq+0xb4/0xd0
[<4058f524>] snd_gus_create+0x124/0x3c0
[<40aa4087>] snd_gusclassic_probe+0x2a7/0x4b0
[<403f5eff>] isa_bus_probe+0x1f/0x30
[<403f1944>] driver_probe_device+0x84/0x190
[<403f1a58>] __device_attach+0x8/0x10
[<403f0e63>] bus_for_each_drv+0x53/0x80
[<403f1b1b>] device_attach+0x8b/0x90
[<403f0dd8>] bus_attach_device+0x48/0x80
[<403efdbd>] device_add+0x45d/0x5a0
[<403eff12>] device_register+0x12/0x20
[<403f60c3>] isa_register_driver+0xb3/0x140
[<40aa3dd2>] alsa_card_gusclassic_init+0x12/0x20
[<40a665c3>] kernel_init+0x133/0x310
[<401054a7>] kernel_thread_helper+0x7/0x10
=======================
Code: Bad EIP value.
EIP: [<00000000>] 0x0 SS:ESP 0068:7ff87bf4
Kernel panic - not syncing: Fatal exception in interrupt
with these things fixed, i get the expected 'no such hardware' result
from the driver initialization:
Calling initcall 0x40aa3dc0: alsa_card_gusclassic_init+0x0/0x20()
ALSA sound/isa/gus/gusclassic.c:136: [0x220] check 1 failed - 0xff
initcall 0x40aa3dc0: alsa_card_gusclassic_init+0x0/0x20() returned 0.
initcall 0x40aa3dc0 ran for 133 msecs:
alsa_card_gusclassic_init+0x0/0x20()
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/isa/gus/gus_irq.c')
-rw-r--r-- | sound/isa/gus/gus_irq.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index a0430b338d67..cd9a6f1c99e6 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c | |||
@@ -45,11 +45,13 @@ __again: | |||
45 | // snd_printk("IRQ: status = 0x%x\n", status); | 45 | // snd_printk("IRQ: status = 0x%x\n", status); |
46 | if (status & 0x02) { | 46 | if (status & 0x02) { |
47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); | 47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); |
48 | gus->gf1.interrupt_handler_midi_in(gus); | 48 | if (gus->gf1.interrupt_handler_midi_in) |
49 | gus->gf1.interrupt_handler_midi_in(gus); | ||
49 | } | 50 | } |
50 | if (status & 0x01) { | 51 | if (status & 0x01) { |
51 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); | 52 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); |
52 | gus->gf1.interrupt_handler_midi_out(gus); | 53 | if (gus->gf1.interrupt_handler_midi_out) |
54 | gus->gf1.interrupt_handler_midi_out(gus); | ||
53 | } | 55 | } |
54 | if (status & (0x20 | 0x40)) { | 56 | if (status & (0x20 | 0x40)) { |
55 | unsigned int already, _current_; | 57 | unsigned int already, _current_; |
@@ -85,20 +87,24 @@ __again: | |||
85 | } | 87 | } |
86 | if (status & 0x04) { | 88 | if (status & 0x04) { |
87 | STAT_ADD(gus->gf1.interrupt_stat_timer1); | 89 | STAT_ADD(gus->gf1.interrupt_stat_timer1); |
88 | gus->gf1.interrupt_handler_timer1(gus); | 90 | if (gus->gf1.interrupt_handler_timer1) |
91 | gus->gf1.interrupt_handler_timer1(gus); | ||
89 | } | 92 | } |
90 | if (status & 0x08) { | 93 | if (status & 0x08) { |
91 | STAT_ADD(gus->gf1.interrupt_stat_timer2); | 94 | STAT_ADD(gus->gf1.interrupt_stat_timer2); |
92 | gus->gf1.interrupt_handler_timer2(gus); | 95 | if (gus->gf1.interrupt_handler_timer2) |
96 | gus->gf1.interrupt_handler_timer2(gus); | ||
93 | } | 97 | } |
94 | if (status & 0x80) { | 98 | if (status & 0x80) { |
95 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { | 99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { |
96 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); | 100 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); |
97 | gus->gf1.interrupt_handler_dma_write(gus); | 101 | if (gus->gf1.interrupt_handler_dma_write) |
102 | gus->gf1.interrupt_handler_dma_write(gus); | ||
98 | } | 103 | } |
99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { | 104 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { |
100 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); | 105 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); |
101 | gus->gf1.interrupt_handler_dma_read(gus); | 106 | if (gus->gf1.interrupt_handler_dma_read) |
107 | gus->gf1.interrupt_handler_dma_read(gus); | ||
102 | } | 108 | } |
103 | } | 109 | } |
104 | if (--loop > 0) | 110 | if (--loop > 0) |