I write a driver for i2c rtc chip for learning purpose. The driver can detect interrupts on GPIO pin from rtc chip. I want to schedule a tasklet into interrupt context and do some usefull work into the tasklet later.
GPIO irq handler:
static irqreturn_t alarm_irq_handler(int irq, void *dev)
{
struct ds3231_state *driver_data;
driver_data = i2c_get_clientdata(to_i2c_client(dev));
if (!driver_data)
return IRQ_NONE;
tasklet_schedule(&driver_data->tasklet);
return IRQ_HANDLED;
}
Tasklet function:
Into the tasklet function I want to do some communucation with i2c-chip, because I need to clear interrupt flags into the chip.
static void bottom_half_ds3231_handler(unsigned long data)
{
struct device *dev = (struct device *)data;
struct i2c_client *client = to_i2c_client(dev);
printk(KERN_INFO "ds3231 gpio alarm interrupt detect\n");
ds3231_disable_onchip_alarm_detect(client); // <--- this functions use I2C
ds3231_clear_onchip_alarm_flags(client);
}
When I try to use i2c, my kernel fails. I know about i2c layer from non-process context. I2C functions are so slow, that's why i have wanted to do slow work into bottom half. But i can't use i2c into bottom half. Why?
How can i reset some flags into the chip after interrupts have been detected?
UPD 1: show stack trace after the kernel was failed
# [ 3160.248272] my-ds3231-rtc 1-0068: ds3231 gpio alarm interrupt detect
[ 3160.254792] BUG: scheduling while atomic: swapper/0/0/0x00000100
[ 3160.260827] Modules linked in: rtc_ds3231(O)
[ 3160.265127] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G O 5.5.0 #1
[ 3160.272376] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 3160.278536] [<c0312994>] (unwind_backtrace) from [<c030cc4c>] (show_stack+0x10/0x14)
[ 3160.286325] [<c030cc4c>] (show_stack) from [<c0ef7270>] (dump_stack+0xc0/0xd4)
[ 3160.293589] [<c0ef7270>] (dump_stack) from [<c0370324>] (__schedule_bug+0x68/0x88)
[ 3160.301204] [<c0370324>] (__schedule_bug) from [<c0f10f90>] (__schedule+0x450/0x618)
[ 3160.308983] [<c0f10f90>] (__schedule) from [<c0f111c0>] (schedule+0x68/0xf4)
[ 3160.316066] [<c0f111c0>] (schedule) from [<c0f15110>] (schedule_timeout+0x188/0x30c)
[ 3160.323846] [<c0f15110>] (schedule_timeout) from [<c0f1214c>] (wait_for_completion_timeout+0xd8/0x16c)
[ 3160.333205] [<c0f1214c>] (wait_for_completion_timeout) from [<c0c6f174>] (omap_i2c_xfer_common+0x3e4/0x5a8)
[ 3160.342998] [<c0c6f174>] (omap_i2c_xfer_common) from [<c0c5bfec>] (__i2c_transfer+0x1d8/0x650)
[ 3160.351650] [<c0c5bfec>] (__i2c_transfer) from [<c0c5c4c0>] (i2c_transfer+0x5c/0x104)
[ 3160.359528] [<c0c5c4c0>] (i2c_transfer) from [<bf000244>] (read_reg+0x68/0xb4 [rtc_ds3231])
[ 3160.367924] [<bf000244>] (read_reg [rtc_ds3231]) from [<bf000ec4>] (ds3231_disable_onchip_alarm_detect+0x28/0xb0 [rtc_ds3231])
[ 3160.379371] [<bf000ec4>] (ds3231_disable_onchip_alarm_detect [rtc_ds3231]) from [<bf001220>] (bottom_half_ds3231_handler+0x38/0xcc [rtc_ds3231])
[ 3160.392389] [<bf001220>] (bottom_half_ds3231_handler [rtc_ds3231]) from [<c034dfdc>] (tasklet_action_common.constprop.3+0x70/0x174)
[ 3160.404272] [<c034dfdc>] (tasklet_action_common.constprop.3) from [<c03022d8>] (__do_softirq+0x130/0x3b4)
[ 3160.413881] [<c03022d8>] (__do_softirq) from [<c034e72c>] (irq_exit+0xcc/0xd8)
[ 3160.421141] [<c034e72c>] (irq_exit) from [<c039df38>] (__handle_domain_irq+0x60/0xb4)
[ 3160.429007] [<c039df38>] (__handle_domain_irq) from [<c0301acc>] (__irq_svc+0x6c/0x90)
[ 3160.436956] Exception stack(0xc1801f10 to 0xc1801f58)
[ 3160.442030] 1f00: 00000000 0002077c df9a7d70 c031dcc0
[ 3160.450243] 1f20: ffffe000 c1804e6c c1804eb0 00000001 00000000 c1804e48 c1760628 00000000
[ 3160.458455] 1f40: 00000001 c1801f60 c0309194 c0309198 60000013 ffffffff
[ 3160.465107] [<c0301acc>] (__irq_svc) from [<c0309198>] (arch_cpu_idle+0x38/0x3c)
[ 3160.472540] [<c0309198>] (arch_cpu_idle) from [<c03783f4>] (do_idle+0x1bc/0x2ac)
[ 3160.479970] [<c03783f4>] (do_idle) from [<c03787a4>] (cpu_startup_entry+0x18/0x1c)
[ 3160.487576] [<c03787a4>] (cpu_startup_entry) from [<c1600dac>] (start_kernel+0x480/0x4b0)
[ 3160.495786] bad: scheduling from the idle thread!