From 7727ac725d1a6a96c5d87180377f8c68b4a1ee37 Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Thu, 1 Feb 2024 14:02:42 +0100 Subject: [PATCH] Use spinlocks in ec_mini.ko examples down() must not be used in softirq context: ``` [ 613.686994] BUG: sleeping function called from invalid context at ../kernel/locking/semaphore.c:58 [ 613.687003] in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 29, name: ktimers/1 [ 613.687007] preempt_count: 0, expected: 0 [ 613.687009] RCU nest depth: 3, expected: 0 [ 613.687013] CPU: 1 PID: 29 Comm: ktimers/1 Tainted: G W OE 6.1.38-lp154.12-0601rt #1 1ef8e7f7e45a6388beff51e7b17265074b1375d6 [ 613.687020] Hardware name: ICP / iEi IMBA-9454ISA/IMBA-9454ISA(E168), BIOS 080014 02/20/2009 [ 613.687023] Call Trace: [ 613.687029] [ 613.687034] dump_stack_lvl+0x44/0x5c [ 613.687046] __might_resched+0x171/0x1c0 [ 613.687055] ? check_slave_config_states+0x100/0x100 [ec_mini 7f93b9d1541d0037eab9400e73ee29f252250780] [ 613.687070] down+0x1e/0x70 [ 613.687076] cyclic_task+0x11/0xdc [ec_mini 7f93b9d1541d0037eab9400e73ee29f252250780] [ 613.687088] call_timer_fn+0x29/0x190 [ 613.687096] run_timer_softirq+0x4d5/0x570 [ 613.687104] ? __schedule+0x32b/0x1330 [ 613.687110] __do_softirq+0xd5/0x2ec [ 613.687117] ? smpboot_thread_fn+0x23/0x300 [ 613.687127] run_timersd+0x60/0xb0 [ 613.687130] smpboot_thread_fn+0x24c/0x300 [ 613.687133] ? smpboot_unregister_percpu_thread+0x70/0x70 [ 613.687135] kthread+0x129/0x140 [ 613.687138] ? kthread_complete_and_exit+0x20/0x20 [ 613.687141] ret_from_fork+0x22/0x30 [ 613.687146] ``` --- examples/mini/mini.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/mini/mini.c b/examples/mini/mini.c index a41504eb..51a3efb1 100644 --- a/examples/mini/mini.c +++ b/examples/mini/mini.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "../../include/ecrt.h" // EtherCAT realtime interface @@ -50,7 +50,7 @@ // EtherCAT static ec_master_t *master = NULL; static ec_master_state_t master_state = {}; -struct semaphore master_sem; +static spinlock_t master_spinlock; static ec_domain_t *domain1 = NULL; static ec_domain_state_t domain1_state = {}; @@ -188,9 +188,9 @@ void check_domain1_state(void) { ec_domain_state_t ds; - down(&master_sem); + spin_lock(&master_spinlock); ecrt_domain_state(domain1, &ds); - up(&master_sem); + spin_unlock(&master_spinlock); if (ds.working_counter != domain1_state.working_counter) printk(KERN_INFO PFX "Domain1: WC %u.\n", ds.working_counter); @@ -206,9 +206,9 @@ void check_master_state(void) { ec_master_state_t ms; - down(&master_sem); + spin_lock(&master_spinlock); ecrt_master_state(master, &ms); - up(&master_sem); + spin_unlock(&master_spinlock); if (ms.slaves_responding != master_state.slaves_responding) printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding); @@ -226,9 +226,9 @@ void check_slave_config_states(void) { ec_slave_config_state_t s; - down(&master_sem); + spin_lock(&master_spinlock); ecrt_slave_config_state(sc_ana_in, &s); - up(&master_sem); + spin_unlock(&master_spinlock); if (s.al_state != sc_ana_in_state.al_state) printk(KERN_INFO PFX "AnaIn: State 0x%02X.\n", s.al_state); @@ -300,10 +300,10 @@ void cyclic_task(unsigned long data) #endif { // receive process data - down(&master_sem); + spin_lock(&master_spinlock); ecrt_master_receive(master); ecrt_domain_process(domain1); - up(&master_sem); + spin_unlock(&master_spinlock); // check process data state (optional) check_domain1_state(); @@ -336,10 +336,10 @@ void cyclic_task(unsigned long data) EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09); // send process data - down(&master_sem); + spin_lock(&master_spinlock); ecrt_domain_queue(domain1); ecrt_master_send(master); - up(&master_sem); + spin_unlock(&master_spinlock); // restart timer timer.expires += HZ / FREQUENCY; @@ -351,9 +351,9 @@ void cyclic_task(unsigned long data) void send_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; - down(&master_sem); + spin_lock_bh(&master_spinlock); ecrt_master_send_ext(m); - up(&master_sem); + spin_unlock_bh(&master_spinlock); } /*****************************************************************************/ @@ -361,9 +361,9 @@ void send_callback(void *cb_data) void receive_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; - down(&master_sem); + spin_lock_bh(&master_spinlock); ecrt_master_receive(m); - up(&master_sem); + spin_unlock_bh(&master_spinlock); } /*****************************************************************************/ @@ -387,7 +387,7 @@ int __init init_mini_module(void) goto out_return; } - sema_init(&master_sem, 1); + spin_lock_init(&master_spinlock); ecrt_master_callbacks(master, send_callback, receive_callback, master); printk(KERN_INFO PFX "Registering domain...\n");