今天客户反应我们的驱动在运行中还是会Oops,奇怪了。因为这个驱动我们之前是在我们自己的一个板子上做的,稳定性之类的已经验证过了,虽然现在的运行环境不是我们自己的版本,既然驱动正常加载,怎么还会出问题呢。
下面的是Oops信息:
BUG: scheduling while atomic: swapper/0/0x40010100
Modules linked in: drvPid: 0, comm: swapper
CPU: 0 Not tainted (2.6.33.5 #19)
PC is at __rcu_process_callbacks+0x68/0x3a0
LR is at __rcu_process_callbacks+0x68/0x3a0
pc : [<c0065820>] lr : [<c0065820>] psr: a0000013
sp : c02c3eb0 ip : c02c3eb0 fp : c02c3ed8
r10: c02e2660 r9 : 0000000a r8 : c02cd5c8
r7 : 00000001 r6 : 00000024 r5 : c02cd708 r4 : c02cd5c8
r3 : 00000002 r2 : c02c2000 r1 : a0000013 r0 : c02cd5c8
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 0005317f Table: 21edc000 DAC: 00000017
[<c0027de4>] (show_regs+0x0/0x4c) from [<c0038678>] (__schedule_bug+0x48/0x5c)
r4:c02c3e68
[<c0038630>] (__schedule_bug+0x0/0x5c) from [<c022b964>] (schedule+0x4c/0x2bc)
r4:c02c2000
[<c022b918>] (schedule+0x0/0x2bc) from [<c00386b0>] (__cond_resched+0x24/0x34)
[<c003868c>] (__cond_resched+0x0/0x34) from [<c022bc68>] (_cond_resched+0x30/0x40)
r4:c1d8e180
[<c022bc38>] (_cond_resched+0x0/0x40) from [<c0086890>] (__kmalloc+0x5c/0xe0)
[<c0086834>] (__kmalloc+0x0/0xe0) from [<bf000130>] (init_rx_dma+0x1c/0x98 [drv])
r7:00000000 r6:00000012 r5:c1d8e180 r4:c1d8e180
[<c0062684>] (handle_IRQ_event+0x0/0x114) from [<c00649c8>] (handle_level_irq+0xf0/0x10c)
r8:c02cd5c8 r7:00000001 r6:00000017 r5:00000017 r4:c02ca028
[<c00648d8>] (handle_level_irq+0x0/0x10c) from [<c0026074>] (asm_do_IRQ+0x74/0xa0)
r5:c02c3f50 r4:00000017
[<c0026000>] (asm_do_IRQ+0x0/0xa0) from [<c0026a68>] (__irq_svc+0x28/0x60)
先google下吧,关键字"BUG: scheduling while atomic",在这里找到的答案。原来malloc内存时,参数GFP_KERNEL是可能会阻塞的,所以不能在中断上下文使用GFP_KERNEL申请内存,而只能使用GFP_ATOMIC。
详见LDD CH8 Allocating Memory
The most commonly used flag, GFP_KERNEL, means that the allocation (internally performed by calling, eventually, __get_free_pages, which is the source of the GFP_ prefix) is performed on behalf of a process running in kernel space. In other words, this means that the calling function is executing a system call on behalf of a process. Using GFP_KERNEL means that kmalloc can put the current process to sleep waiting for a page when called in low-memory situations. A function that allocates memory using GFP_KERNEL must, therefore, be reentrant and cannot be running in atomic context. While the current process sleeps, the kernel takes proper action to locate some free memory, either by flushing buffers to disk or by swapping out memory from a user process.
- GFP_ATOMIC
Used to allocate memory from interrupt handlers and other code outside of a process context. Never sleeps.- GFP_KERNEL
Normal allocation of kernel memory. May sleep.- GFP_USER
Used to allocate memory for user-space pages; it may sleep.- GFP_HIGHUSER
Like GFP_USER, but allocates from high memory, if any. High memory is described in the next subsection.- GFP_NOIO
- GFP_NOFS
These flags function like GFP_KERNEL, but they add restrictions on what the kernel can do to satisfy the request. A GFP_NOFS allocation is not allowed to perform any filesystem calls, while GFP_NOIO disallows the initiation of any I/O at all.
They are used primarily in the filesystem and virtual memory code where an allocation may be allowed to sleep, but recursive filesystem calls would be a bad idea.