谢谢,第一次碰到,我有个i2c的设备驱动,在中断里进行读写,就碰到以下情况,不知道是不是使用mutex_lock引起的.
出错的地方在i2c转串口(SC16IS740)的驱动程序里,该模块申请了一个IRQ中断,
中断处理函数是serial_sc16is7_interrupt(),在这个函数里
要调用i2c-core模块里的i2c_smbus_read_byte_data()函数读I2C总线,
但这时系统就panic掉了。
内核版本是2.6.21,下面是出错信息。
---------------------------------------------------------
<3>BUG: scheduling while atomic: swapper/0x00010000/0
<3>bad: scheduling from the idle thread!
<1>Unable to handle kernel NULL pointer dereference at virtual address 00000000
<1>pgd = c0004000
<1>[00000000] *pgd=00000000
Internal error: Oops: 17 [#1]
Modules linked in: nmeapipe gtspmdev
CPU: 0
PC is at dequeue_task+0xc/0x84
LR is at deactivate_task+0x34/0x40
pc : [<bf06633c>] lr : [<bf0666c0>] Not tainted
sp : c0009cec ip : c0009d00 fp : c0009cfc
r10: 00000005 r9 : b9a0f85d r8 : c00129b8
r7 : 00000002 r6 : c00129b8 r5 : c0008000 r4 : c00129b8
r3 : 00000080 r2 : 00000080 r1 : 00000000 r0 : c00129b8
Flags: nZCv IRQs off FIQs on Mode SVC_32 Segment kernel
Control: 317F
Table: 103C8000 DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0008250)
Stack: (0xc0009cec to 0xc000a000)
9fe0: 9fe0: c002f364 c002f364 c00137a4 c00137a4 00000000 00000000 c0009ff8 c0009ff8 00040070 00040070 bf0408ac bf0408ac 00000000 00000000 00000000 00000000
Backtrace:
[<bf066330>] (dequeue_task+0x0/0x84) from [<bf0666c0>] (deactivate_task+0x34/0x40)
r4 = C00129B8
[<bf06668c>] (deactivate_task+0x0/0x40) from [<bf1f2410>] (schedule+0x1b0/0x744)
r4 = 00000005
[<bf1f2260>] (schedule+0x0/0x744) from [<bf1f375c>] (__mutex_lock_slowpath+0x5c/0x88)
[<bf1f3700>] (__mutex_lock_slowpath+0x0/0x88) from [<bf1f36d4>] (mutex_lock+0x20/0x28)
r7 = C0074054 r6 = C0009DB8 r5 = 00000002 r4 = C0074034
[<bf1f36b4>] (mutex_lock+0x0/0x28) from [<bf165098>](i2c_transfer+0x38/0x64)
[<bf165060>] (i2c_transfer+0x0/0x64) from [<bf165674>] (i2c_smbus_xfer+0x350/0x464)
r7 = 00000002 r6 = 00000000 r5 = C0009DB8 r4 = 00000000
[<bf165324>] (i2c_smbus_xfer+0x0/0x464) from [<bf165a1c>] (i2c_smbus_read_byte_data+0x44/0x58)
[<bf1659d8>] (i2c_smbus_read_byte_data+0x0/0x58) from [<bf167fb0>] (Sc16is7xx_Read_Register+0x38/0x44)
[<bf167f78>] (Sc16is7xx_Read_Register+0x0/0x44) (from [<bf150480>] (serial_in+0x20/0x28)
r4 = 00000000
[<bf150460>] (serial_in+0x0/0x28) from [<bf1506a4>] (serial_sc16is7_interrupt+0x34/0xcc)
[<bf150670>] (serial_sc16is7_interrupt+0x0/0xcc) from [<bf08ae30>](handle_IRQ_event+0x44/0x80)
[<bf08adec>](handle_IRQ_event+0x0/0x80) from [<bf08bffc>] (handle_simple_irq+0x80/0xb4)
r7 = C001D96C r6 = 000000AE r5 = 000000AE r4 = C000EB80
[<bf08bf7c>] (handle_simple_irq+0x0/0xb4) from [<bf064a70>] (gpio_irq_handler+0x1ac/0x234)
r5 = 00000001 r4 = C000EB80
[<bf0648c4>] (gpio_irq_handler+0x0/0x234) from [<bf05813c>] (asm_do_IRQ+0x44/0x5c)
[<bf0580f8>] (asm_do_IRQ+0x0/0x5c) from [<bf057424>](__irq_svc+0x24/0x80)
r7 = C0048E04 r6 = FFFFFFFF r5 = FEFECB00 r4 = FFFFFFFF
[<bf058340>] (cpu_idle+0x0/0x7c) from [<bf056c24>] (rest_init+0x24/0x2c)
r6 = C000AF28 r5 = C002EEA8 r4 = C0037C00
[<bf056c00>] (rest_init+0x0/0x2c) from [<bf040b18>] (start_kernel+0x27c/0x2e4)
[<bf04089c>] (start_kernel+0x0/0x2e4) from [<00040070>] (0x40070)
r6 = C00137A4 r5 = C002F364 r4 = 0000317D
Code:c0030148 e1a0c00d e92dd810 e24cb004 (e5913000)
<0>Kernel panic - not syncing: Aiee, killing interrupt handler!
---------------------------------------------------------
/*kernel/drivers/i2c/i2c-core.c*/
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
{
int ret;
if (adap->algo->master_xfer) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
mutex_lock_nested(&adap->bus_lock, adap->level);
ret = adap->algo->master_xfer(adap,msgs,num);
mutex_unlock(&adap->bus_lock);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -ENOSYS;
}
}
---------------
这里的mutex_lock_nested 与mutex_lock有什么区别啊,跟中断有没有关系呢?
从 Backtrace 来看,应该是 i2c_transfer 中调用 mutex_lock 导致 schedule 调用
而产生 进程调度,导致死机. 而在中断上下文,这种情况是绝对不允许发生的.换句话说是不允许
睡眠的,不允许进程调度.
你可以 把 mutex_lock 注释掉再试试 .
另外你的内核是什么版本?