This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi
I am getting kernel oops because of i2c_master_send function when i call tsc2007_wq_function function with schedule_work(&work), but when i directly call same function in timer function, it is working but in this case "BUG: scheduling while atomic: swapper" warning occurs and linux is crashing.
if "&normal_i2c" causes this problem which is in "static DECLARE_WORK(work, (void (*)(void *))tsc2007_wq_function, &normal_i2c)" has anybody got any idea what to write instead of it.
static unsigned int short normal_i2c[] = { 0x48, I2C_CLIENT_END };I2C_CLIENT_INSMOD_1 (tsc2007);static void tsc2007_wq_function(void *);static DECLARE_WORK(work, (void (*)(void *))tsc2007_wq_function, &normal_i2c);static void tsc2007_wq_function(void *arg){ struct tsc2007_data *data = (struct tsc2007_data *)arg; struct i2c_client *client = &data->client; u16 x_value = 0; u16 y_value = 0; u8 measure_y = TSC2007_CMD (MEAS_YPOS, data->pd, data->m); u8 measure_x = TSC2007_CMD (MEAS_XPOS, data->pd, data->m); data->kernel_x = 0; data->kernel_y = 0; i2c_master_send (client,&measure_y, BYTES_TO_TX); i2c_master_recv (client,(u8 *)&y_value, BYTES_TO_RX); i2c_master_send (client,&measure_x, BYTES_TO_TX); i2c_master_recv (client,(u8 *)&x_value, BYTES_TO_RX); if (data->m == M_12BIT){ data->kernel_y = (((be16_to_cpu (y_value)) >> 4) & VALUE_MASK); data->kernel_x = (((be16_to_cpu (x_value)) >> 4) & VALUE_MASK); } else if (data->m == M_8BIT){ data->kernel_y = y_value; data->kernel_x = x_value; }}
////////kernel oops message/////////
# ts_test [ 26.710000] Unable to handle kernel paging request at virtual address 00bbe59f[ 26.710000] pgd = c49d0000[ 26.720000] [00bbe59f] *pgd=00000000[ 26.720000] Internal error: Oops: 1 [#1][ 26.720000] Modules linked in:[ 26.720000] CPU: 0[ 26.720000] PC is at i2c_transfer+0x18/0xe8[ 26.720000] LR is at i2c_master_send+0x44/0x54[ 26.720000] pc : [<c024aa5c>] lr : [<c024b630>] Not tainted[ 26.720000] sp : c0581eb8 ip : c0581ee8 fp : c0581ee4[ 26.720000] r10: c03e5f9c r9 : c028e108 r8 : 00000000[ 26.720000] r7 : c03e5e00 r6 : 000001b6 r5 : 000001b4 r4 : fffefffe[ 26.720000] r3 : 00bbe59f r2 : 00000001 r1 : c0581eec r0 : fffefffe[ 26.720000] Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment kernel[ 26.720000] Control: 5317F[ 26.720000] Table: 849D0000 DAC: 00000017[ 26.720000] Process events/0 (pid: 12, stack limit = 0xc0580258)[ 26.720000] Stack: (0xc0581eb8 to 0xc0582000)[ 26.720000] 1ea0: c053eeb0 00000001 [ 26.720000] 1ec0: 000001b4 000001b6 c03e5e00 00000000 c028e108 c03e5f9c c0581f0c c0581ee8 [ 26.720000] 1ee0: c024b630 c024aa54 c055d040 0000fffe c0580001 c0581f17 c005f9d0 c03e5f9c [ 26.720000] 1f00: c0581f34 c0581f10 c028e174 c024b5fc 00009dc8 d0c00000 00000000 80000013 [ 26.720000] 1f20: c05366a0 c0580000 c0581f6c c0581f38 c00625a4 c028e118 c05366b8 c05366a8 [ 26.720000] 1f40: 00000002 00000000 c05366a8 c0580000 c05366a0 c05366b0 00000002 c0581f84 [ 26.720000] 1f60: c0581fcc c0581f70 c0062dac c00624d4 00000001 00000000 c0049c08 00010000 [ 26.720000] 1f80: 00000000 00000000 c055d040 c004b200 00100100 00200200 ffffffff ffffffff [ 26.720000] 1fa0: 00000000 c05366a0 c0580000 c0062ca4 c0551ee0 00000000 00000000 00000000 [ 26.720000] 1fc0: c0581ff4 c0581fd0 c0065d10 c0062cb4 ffffffff ffffffff 00000000 00000000 [ 26.720000] 1fe0: 00000000 00000000 00000000 c0581ff8 c0052a74 c0065c38 00000000 4800133a [ 26.720000] Backtrace: [ 26.720000] [<c024aa44>] (i2c_transfer+0x0/0xe8) from [<c024b630>] (i2c_master_send+0x44/0x54)[ 26.720000] [<c024b5ec>] (i2c_master_send+0x0/0x54) from [<c028e174>] (tsc2007_wq_function+0x6c/0x104)[ 26.720000] r4 = C03E5F9C [ 26.720000] [<c028e108>] (tsc2007_wq_function+0x0/0x104) from [<c00625a4>] (run_workqueue+0xe0/0x170)[ 26.720000] r6 = C0580000 r5 = C05366A0 r4 = 80000013 [ 26.720000] [<c00624c4>] (run_workqueue+0x0/0x170) from [<c0062dac>] (worker_thread+0x108/0x144)[ 26.720000] [<c0062ca4>] (worker_thread+0x0/0x144) from [<c0065d10>] (kthread+0xe8/0x128)[ 26.720000] [<c0065c28>] (kthread+0x0/0x128) from [<c0052a74>] (do_exit+0x0/0x9cc)[ 26.720000] r7 = 00000000 r6 = 00000000 r5 = 00000000 r4 = 00000000[ 26.720000] Code: e24cb004 e24dd004 e590300c e1a04000 (e5933000) [ 26.720000] <7>evbug.c: Event. Dev: <NULL>, Type: 1, Code: 330, Value: 0[ 27.930000] evbug.c: Event. Dev: <NULL>, Type: 3, Code: 24, Value: 0[ 27.940000] evbug.c: Event. Dev: <NULL>, Type: 0, Code: 0, Value: 0946684823.822249: 269 -19110 7500946684825.041995: 269 -19110 0
Hi Ali,
I forwarded your problem to an export on Linux, and asked for help. The following is his analysis:
"
I am looking at my kernel that I use for OMAP development (2.6.33) ... In a cursory check, the panic trace suggests that the i2c_transfer function is 232 bytes long, where mine is 240 bytes long, a discrepancy of 4 bytes. Right now I am trying 2.6.32 to see if it might match. Right now I am working out a build on that version... so while I do this, I'll critique what I see here...First, withstatic unsigned int short normal_i2c[] = { 0x48, I2C_CLIENT_END };...static DECLARE_WORK(work, (void (*)(void *))tsc2007_wq_function, &normal_i2c);static void tsc2007_wq_function(void *arg)What I see here is that this person is creating a task to deal with the data (&normal_i2c) which is then being passed to the work queue function, and then being cast...static void tsc2007_wq_function(void *arg){ struct tsc2007_data *data = (struct tsc2007_data *)arg;... to a tsc2007_data. It's an array of unsigned short ints. I have no idea (I searched for it, didn't find it) what type the tsc2007_data is; or more to the point, what this structure contains. I am convinced that it is not as small as the array being passed to the function, observing that within that structure there is an i2c_client structure which we take the address of here: struct i2c_client *client = &data->client;This is declared in include/linux/i2c.h... 188 struct i2c_client { 189 unsigned short flags; /* div., see below */ 190 unsigned short addr; /* chip address - NOTE: 7bit */ 191 /* addresses are stored in the */ 192 /* _LOWER_ 7 bits */ 193 char name[I2C_NAME_SIZE]; 194 struct i2c_adapter *adapter; /* the adapter we sit on */ 195 struct i2c_driver *driver; /* and our access routines */ 196 struct device dev; /* the device structure */ 197 int irq; /* irq issued by device */ 198 struct list_head detected; 199 };So, supposing that the client structure is the first element in the tsc2007_data structure, immediately the address that we're going to use is I2C_CLIENT_END (assuming we don't have any padding between elements) which is not right.Now that the build is complete, I've found that the i2c_transfer function blew up on line 1084 (assuming that I am using the right kernel version, which I'm not... this one's i2c_transfer function is 220 bytes long). This does look correct to me, considering the type of oops/panic that we're seeing and the code, even though the kernel that I've built is different in this function:In drivers/i2c/i2c-core.c: 1062 int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 1063 { 1064 unsigned long orig_jiffies; 1065 int ret, try; 1066 1067 /* REVISIT the fault reporting model here is weak:... 1082 */ 1083*1084 if (adap->algo->master_xfer) {What we see going on here in 1084 is a check to see whether adap->algo->master_xfer is zero. The field adap is taken straight out of i2c_client, deeper into the structure than the pointer to (two unsigned short ints) normal_i2c will support.I'd like to see the way this function is being called in the timer function... it's possible that it's being called correctly there, but I can guarantee you it's not being called correctly in this instance. The data that needs to be passed to DECLARE_WORK should be a pointer to a properly-populated tsc2007_data structure, but right now, it's a pointer to an unsigned int array of two elements.
In reply to Wendy Fang:
Hi,
I wonder if this problem has been resolved. I experience something similar on beagleboard clone board with tsc2007 on i2c bus 2 using Linux2.6.29-omap1. The driver works fine except for reading tsc2007 data via i2c WHILE inside timer function. I reads tsc2007 OK inside probe() but not when inside timer function where it causes kernel dump. Timer function looks like
static void tsc2007_timer( unsigned long data ){
unsigned long flags;
struct tsc2007 *ts = (struct tsc2007 *)data;
if (unlikely(!ts->get_pendown_state() && ts->pendown))
{
struct input_dev *input = ts->input;
dev_dbg(&ts->client->dev, "UP\n");
input_report_key(input, BTN_TOUCH, 0);
input_report_abs(input, ABS_PRESSURE, 0);
input_sync(input);
ts->pendown = 0;
enable_irq( ts->irq );
ts->irq_disabled = 0;
} else {
// pen is still down, continue with the measurement
dev_dbg(&ts->client->dev, "DOWN\n");
tsc2007_read_values( ts ); // this makes kernel crash
tsc2007_send_event(ts);
}
Here is the kernel dump caused by tsc2007_read_values( ts ) call
[ 2750.183441] ------------[ cut here ]------------
[ 2750.188110] WARNING: at kernel/mutex.c:351 mutex_trylock+0x68/0x13c()
[ 2750.194580] Modules linked in: tsc2007 g_zero [last unloaded: tsc2007]
[ 2750.201171] [<c035da80>] (dump_stack+0x0/0x14) from [<c005bfa8>] (warn_slowpath+0x68/0x9c)
[ 2750.209533] [<c005bf40>] (warn_slowpath+0x0/0x9c) from [<c035ed74>] (mutex_trylock+0x68/0x13c)
[ 2750.218231] r3:c04e636c r2:00000000
[ 2750.221862] r7:00000001 r6:cfb2ee38 r5:00000049 r4:cfb2ee58
[ 2750.227600] [<c035ed0c>] (mutex_trylock+0x0/0x13c) from [<c022a7a0>] (i2c_transfer+0xec/0x164)
[ 2750.236297] r6:cfb2ee38 r5:00000049 r4:00000001
[ 2750.240966] [<c022a6b4>] (i2c_transfer+0x0/0x164) from [<c022b540>] (i2c_master_send+0x44/0x54 )
[ 2750.249755] [<c022b4fc>] (i2c_master_send+0x0/0x54) from [<bf011078>] (tsc2007_read_values+0x2 c/0x418 [tsc2007])
[ 2750.260040] r4:cfbb31c0
[ 2750.262573] [<bf01104c>] (tsc2007_read_values+0x0/0x418 [tsc2007]) from [<bf011880>] (tsc2007_ timer+0xe0/0x2a4 [tsc2007])
[ 2750.273651] r5:cfbb31c0 r4:00000103
[ 2750.277282] [<bf0117a0>] (tsc2007_timer+0x0/0x2a4 [tsc2007]) from [<c00660dc>] (run_timer_soft irq+0x1ac/0x250)
[ 2750.287384] [<c0065f30>] (run_timer_softirq+0x0/0x250) from [<c0061ac0>] (__do_softirq+0x6c/0x 10c)
[ 2750.296417] [<c0061a54>] (__do_softirq+0x0/0x10c) from [<c0061ba8>] (irq_exit+0x48/0x94)
[ 2750.304595] [<c0061b60>] (irq_exit+0x0/0x94) from [<c003705c>] (__exception_text_start+0x5c/0x 70)
[ 2750.313568] [<c0037000>] (__exception_text_start+0x0/0x70) from [<c0037a84>] (__irq_svc+0x44/0 xa4)
[ 2750.322631] Exception stack(0xc0473f20 to 0xc0473f68)
[ 2750.327697] 3f20: 2b4e76c4 a0000013 0051f4c5 00000000 c0043ad0 c0472000 c047603c c0038f1c
[ 2750.336120] 3f40: c04a9bc8 411fc082 0000001f c0473f8c c0473f90 c0473f68 c0038edc c0043adc
[ 2750.344512] 3f60: 60000013 ffffffff
[ 2750.352905] r5:d8200000 r4:ffffffff
[ 2750.356506] [<c0043ad0>] (omap3_pm_idle+0x0/0x130) from [<c0038edc>] (cpu_idle+0x50/0x90)
[ 2750.364776] [<c0038e8c>] (cpu_idle+0x0/0x90) from [<c0359924>] (rest_init+0x6c/0x80)
[ 2750.372619] r8:8002a3c4 r7:c0475ed0 r6:c002bea4 r5:c04a9764 r4:c04e34d4
[ 2750.379394] [<c03598b8>] (rest_init+0x0/0x80) from [<c0008968>] (start_kernel+0x25c/0x2b8)
[ 2750.387756] [<c000870c>] (start_kernel+0x0/0x2b8) from [<80008034>] (0x80008034)
[ 2750.395233] ---[ end trace 91dd314bb23dd928 ]---