开发者

Kernel Function Failing on interrupt but not on ioctl

开发者 https://www.devze.com 2023-02-26 18:59 出处:网络
Im writing a kernel driver interfacing over i2c and I do a read from the bus interface chip in multiple places. Some are done from the user space via an ioctl and others occur on an interrupt. The rea

Im writing a kernel driver interfacing over i2c and I do a read from the bus interface chip in multiple places. Some are done from the user space via an ioctl and others occur on an interrupt. The reads done from the ioctl work fine, but the reads done from the interrupt cause a core dump(See Below).

Here are the relevant code parts:

static struct i2c_client *pcf8575_client; //global i2c client handle

static void
pcf8575_init_client(struct i2c_client *client) {
   .
   .
   .
    pcf8575_client = client;
   .
   . 
   .
}

static int
pcf8575_ioctl(struct inode *inode,struct file *file,unsigned int request,unsigned long argument)
{
  .
  .
  .
  pcf8575_read_char(pcf8575_client, &key); //works fine here, gets back appropriate value
  .
  .
  .
}

static irqreturn_t i2c_keys_isr (int irq, void *data)
{
   int result;
   static char last_key, key;
   static struct i2c_client *pcf8575_client;
   pcf8575_client = (struct i2c_client*) data;
   .
   .
   .
   result = pcf8575_read_char (pcf8575_client, &key); //this is where it fails from the   irq routine
}

//Here is the functions definition
static inline int
pcf8575_read(struct i2c_client *client, u8 reg, u8 *value) {
    s32 data;

    data = i2c_smbus_read_byte_data(client, reg); //fails on this call only when called from the interrupt

    if (data < 0)
    return -EIO;

    *value = data;

    return 0;
}

We have validated that pcf8575_client is a valid non-null pointer, we were able to print out the pointer's value and verify that it matched the global as well as dereference individual values in the struct pointed to by the pointer from within the interrupt routine.

Here is the core dump we are receiving:

BUG: scheduling while atomic: swapper/0/0x00010000
Modules linked in: i2c_keys<7>s3c2410-i2c s3c2410-i2c: READ: Send Stop
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 0 [#1]
Modules linked in: i2c_keys i2cts(P) gpio
CPU: 0    Tainted: P            (2.6.28.10 #143)
PC is at 0x0
LR is at activate_task+0x48/0x60
pc : [<00000000>]    lr : [<c0080560>]    psr: 40000093
sp : c0347b80  ip : c0347b98  fp : c0347b94
r10: 00000000  r9 : 00000003  r8 : c035e7b8
r7 : 00000000  r6 : 20000093  r5 : c0364f60  r4 : c0348fe4
r3 : c0299098  r2 : 00000001  r1 : c0348fe4  r0 : c0364f60
Flags: nZcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: c000717f  Table: 3fbb0000  DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0346260)
Stack: (0xc0347b80 to 0xc0348000)
7b80: c0348fe4 c035e7ac c0347bb4 c0347b98 c00819e4 c0080528 c0347e24 c035e7ac 
7ba0: 00000000 00000001 c0347bc4 c0347bb8 c0081a5c c0081994 c0347bd8 c0347bc8 
7bc0: c00994fc c0081a58 c0347e24 c0347c04 c0347bdc c0080a74 c00994f8 60000093 
7be0: c035e7b8 00000000 0000002b 00000009 00000000 c0346000 c0347c1c c0347c08 
7c00: c0080ae4 c0080a4c 00000000 00000091 c0347c40 c0347c20 c020fde4 c0080ac8 
7c20: cfaaffc0 00000000 00000000 0000002b 00000009 c0347c60 c0347c44 c00a888c 
7c40: c020fc70 c03518e0 0000002b cfaaffc0 c037832c c0347c80 c0347c64 c00a9d40 
7c60: c00a8858 0000002b c0347f4c 08000000 c0347d70 c0347c98 c0347c84 c0072064 
7c80: c00a9c40 ffffffff f4000000 c0347d58 c0347c9c c0072a44 c0072010 c034f50c 
7ca0: 80000013 c034f4cc c034f4cc c0375864 00000000 c037586d c0347d70 00000009 
7cc0: 00000000 c0346000 c0347d58 c0347cb8 c0347ce4 c0085b48 c0086158 60000013 
7ce0: ffffffff c034f52c c034f52c c0347d7c c0347cdc 00000004 80000013 c0086158 
7d00: 60000013 ffffffff c034e430 c0347d28 c0347d1c c007d440 00000003 60000013 
7d20: c0347d58 c0347d30 c0085b48 c009ce50 bf00b420 c0350dd4 c0347d7c 000003e8 
7d40: c0364f60 00000000 c0346000 c0347d68 c0347d5c c02962fc c0085eb4 c0347d9c 
7d60: c0347d7c c00a43e0 c02962f4 c030252e bf00b42c c0347d7c 00000000 c0085e00 
7d80: c0347db0 c0347f4c c0348fe4 c034913c c0347db0 c0347da0 c0082e7c c00a43a4 
7da0: ffff4a0b c0347ddc c0347db4 c0296740 c0082e58 ffff4a0b c0347de0 c0350238 
7dc0: 000003e8 c0346000 c0347e30 c0347e24 c0347e14 c0347de0 c0296ba0 c0296704 
7de0: c0376678 c0376678 ffff4a0b c008ecd4 c0348fe4 c0375e20 000003e8 c035e7b8 
7e00: 00000000 00000000 c0347e60 c0347e18 c020fb7c c0296b18 00000001 c0347eac 
7e20: c035e7f4 00000000 c0348fe4 c00994e8 c035e7b8 c035e7b8 00000052 c02fbb1d 
7e40: 00000002 c035e7f4 c0347eb8 c035e834 00000001 c0347ea8 c0347e64 c020c290 
7e60: c020fa20 00000052 00000021 00000002 c02fbb1d c035e8c0 00000001 c0347eac 
7e80: c035e7f4 00000021 c0347eda 00000002 30020fdc 41129200 30020f40 c0347ed4 
7ea0: c0347eac c020d018 c020c198 00010021 c0290002 c0347eda cfba5e00 00000000 
7ec0: 00000000 00000010 c0347ef0 c0347ed8 bf00a2b4 c020cfd0 ffff7f10 cfbbe300 
7ee0: 00000000 c0347f10 c0347ef4 c00a888c bf00a25c c035128c 00000010 cfbbe300 
7f00: c037832c c0347f30 c0347f14 c00a9d40 c00a8858 00000010 00000000 00000001 
7f20: c03644e8 c0347f48 c0347f34 c0072064 c00a9c40 ffffffff f4000000 c0347fa0 
7f40: c0347f4c c0072a44 c0072010 f4100000 00000032 f4100000 60000013 c00738f8 
7f60: c0346000 c00738f8 c03644e8 30020fdc 41129200 30020f40 c0347fa0 c0347fa4 
7f80: c0347f94 c0073f08 c0073998 60000013 ffffffff c0347fc0 c0347fa4 c0073f08 
7fa0: c0073908 c03786d8 c0364088 c0022f00 c0349c34 c0347fd0 c0347fc4 c0295258 
7fc0: c0073ed8 c0347ff4 c0347fd4 c000896c c0295214 c0008458 c0022f00 c0007175 
7fe0: c036454c c0023304 00000000 c0347ff8 30008034 c0008704 00000000 00000000 
Backtrace: 
[<c0080518>] (activate_task+0x0/0x60) from [<c00819e4>] (try_to_wake_up+0x60/0xc4)
 r5:c035e7ac r4:c0348fe4
[<c0081984>] (try_to_wake_up+0x0/0xc4) from [<c0081a5c>] (default_wake_function+0x14/0x18)
 r7:00000001 r6:00000000 r5:c035e7ac r4:c0347e24
[<c0081a48>] (default_wake_function+0x0/0x18) from [<c00994fc>] (autoremove_wake_function+0x14/0x3c)
[<c00994e8>] (autoremove_wake_function+0x0/0x3c) from [<c0080a74>] (__wake_up_common+0x38/0x7c)
 r4:c0347e24
[<c0080a3c>] (__wake_up_common+0x0/0x7c) from [<c0080ae4>] (__wake_up+0x2c/0x44)
[<c0080ab8>] (__wake_up+0x0/0x44) from [<c020fde4>] (s3c24xx_i2c_irq+0x184/0x5c4)
 r4:00000091
[<c020fc60>] (s3c24xx_i2c_irq+0x0/0x5c4) from [<c00a888c>] (handle_IRQ_event+0x44/0x80)
 r8:00000009 r7:0000002b r6:00000000 r5:00000000 r4:cfaaffc0
[<c00a8848>] (handle_IRQ_event+0x0/0x80) from [<c00a9d40>] (handle_edge_irq+0x110/0x14c)
 r7:c037832c r6:cfaaffc0 r5:0000002b r4:c03518e0
[<c00a9c30>] (handle_edge_irq+0x0/0x14c) from [<c0072064>] (__exception_text_start+0x64/0x84)
 r7:c0347d70 r6:08000000 r5:c0347f4c r4:0000002b
[<c0072000>] (__exception_text_start+0x0/0x84) from [<c007开发者_StackOverflow2a44>] (__irq_svc+0x24/0xa0)
Exception stack(0xc0347c9c to 0xc0347ce4)
7c80:                                                                c034f50c 
7ca0: 80000013 c034f4cc c034f4cc c0375864 00000000 c037586d c0347d70 00000009 
7cc0: 00000000 c0346000 c0347d58 c0347cb8 c0347ce4 c0085b48 c0086158 60000013 
7ce0: ffffffff                                                                
 r5:f4000000 r4:ffffffff
[<c0085ea4>] (vprintk+0x0/0x2fc) from [<c02962fc>] (printk+0x1c/0x24)
[<c02962e0>] (printk+0x0/0x24) from [<c00a43e0>] (print_modules+0x4c/0x9c)
 r3:00000000 r2:c0347d7c r1:bf00b42c r0:c030252e
[<c00a4394>] (print_modules+0x0/0x9c) from [<c0082e7c>] (__schedule_bug+0x34/0x5c)
 r6:c034913c r5:c0348fe4 r4:c0347f4c
[<c0082e48>] (__schedule_bug+0x0/0x5c) from [<c0296740>] (schedule+0x4c/0x2b8)
 r4:ffff4a0b
[<c02966f4>] (schedule+0x0/0x2b8) from [<c0296ba0>] (schedule_timeout+0x98/0xc4)
[<c0296b08>] (schedule_timeout+0x0/0xc4) from [<c020fb7c>] (s3c24xx_i2c_xfer+0x16c/0x250)
 r7:00000000 r6:00000000 r5:c035e7b8 r4:000003e8
[<c020fa10>] (s3c24xx_i2c_xfer+0x0/0x250) from [<c020c290>] (i2c_transfer+0x108/0x168)
[<c020c188>] (i2c_transfer+0x0/0x168) from [<c020d018>] (i2c_master_recv+0x58/0x80)
[<c020cfc0>] (i2c_master_recv+0x0/0x80) from [<bf00a2b4>] (i2c_keys_isr+0x68/0x1b4 [i2c_keys])
 r7:00000010 r6:00000000 r5:00000000 r4:cfba5e00
[<bf00a24c>] (i2c_keys_isr+0x0/0x1b4 [i2c_keys]) from [<c00a888c>] (handle_IRQ_event+0x44/0x80)
 r5:00000000 r4:cfbbe300
[<c00a8848>] (handle_IRQ_event+0x0/0x80) from [<c00a9d40>] (handle_edge_irq+0x110/0x14c)
 r7:c037832c r6:cfbbe300 r5:00000010 r4:c035128c
[<c00a9c30>] (handle_edge_irq+0x0/0x14c) from [<c0072064>] (__exception_text_start+0x64/0x84)
 r7:c03644e8 r6:00000001 r5:00000000 r4:00000010
[<c0072000>] (__exception_text_start+0x0/0x84) from [<c0072a44>] (__irq_svc+0x24/0xa0)
Exception stack(0xc0347f4c to 0xc0347f94)
7f40:                            f4100000 00000032 f4100000 60000013 c00738f8 
7f60: c0346000 c00738f8 c03644e8 30020fdc 41129200 30020f40 c0347fa0 c0347fa4 
7f80: c0347f94 c0073f08 c0073998 60000013 ffffffff                            
 r5:f4000000 r4:ffffffff
[<c00738f8>] (default_idle+0x0/0xb0) from [<c0073f08>] (cpu_idle+0x40/0x5c)
[<c0073ec8>] (cpu_idle+0x0/0x5c) from [<c0295258>] (rest_init+0x54/0x68)
 r7:c0349c34 r6:c0022f00 r5:c0364088 r4:c03786d8
[<c0295204>] (rest_init+0x0/0x68) from [<c000896c>] (start_kernel+0x278/0x2e0)
[<c00086f4>] (start_kernel+0x0/0x2e0) from [<30008034>] (0x30008034)
 r6:c0023304 r5:c036454c r4:c0007175
Code: bad PC value.
Kernel panic - not syncing: Fatal exception in interrupt


Here's your problem: i2c_smbus_read_byte_data() calls i2c_smbus_xfer(), which calls i2c_lock_adapter(), which calls rt_mutex_lock().

rt_mutex_lock() can sleep. Functions that can sleep may only be called from a process context.

Therefore it's illegal for you to call i2c_smbus_read_byte_data() from an interrupt handler.

If you're in an interrupt handler or tasklet or holding a spinlock, you must not sleep (or call functions that may sleep) or you may deadlock the system. That's what the message "BUG: scheduling while atomic" is trying to tell you.

If you need to use that function you'll need to reorganize your code so you can call it from a process context. You might consider having your interrupt handler wake up a task or submit a work_struct to a workqueue, which then does the necessary work.

0

精彩评论

暂无评论...
验证码 换一张
取 消