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] <TASK> [ 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] </TASK> ```
This commit is contained in:
parent
2fdea4dd53
commit
7727ac725d
|
|
@ -27,7 +27,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue