# HG changeset patch # User Florian Pose # Date 1147261865 0 # Node ID 07247920a7ba402eb87a8153088b266de207a1af # Parent 9e8150db6fc8a3faad32925d8cf3e1afc1f59140 EoE with workqueue; bugfix in ec_master_init() diff -r 9e8150db6fc8 -r 07247920a7ba examples/mini/mini.c --- a/examples/mini/mini.c Wed May 10 11:33:10 2006 +0000 +++ b/examples/mini/mini.c Wed May 10 11:51:05 2006 +0000 @@ -108,21 +108,15 @@ int request_lock(void *data) { - unsigned int tries = 0; - while (1) { - if (spin_trylock(&master_lock)) { - if (tries) printk(KERN_INFO "lock: %i tries needed.\n", tries); - return 1; - } - tries++; - } + spin_lock_bh(&master_lock); + return 0; // access allowed } /*****************************************************************************/ void release_lock(void *data) { - spin_unlock(&master_lock); + spin_unlock_bh(&master_lock); } /*****************************************************************************/ diff -r 9e8150db6fc8 -r 07247920a7ba master/master.c --- a/master/master.c Wed May 10 11:33:10 2006 +0000 +++ b/master/master.c Wed May 10 11:51:05 2006 +0000 @@ -46,7 +46,11 @@ /*****************************************************************************/ void ec_master_freerun(unsigned long); +#ifdef EOE_TIMER void ec_master_run_eoe(unsigned long); +#else +void ec_master_run_eoe(void *); +#endif ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); void ec_master_process_watch_command(ec_master_t *); @@ -98,31 +102,45 @@ INIT_LIST_HEAD(&master->domains); INIT_LIST_HEAD(&master->eoe_slaves); + ec_command_init(&master->simple_command); + ec_command_init(&master->watch_command); + + // init freerun timer + init_timer(&master->freerun_timer); + master->freerun_timer.function = ec_master_freerun; + master->freerun_timer.data = (unsigned long) master; + + // init eoe timer +#ifdef EOE_TIMER + init_timer(&master->eoe_timer); + master->eoe_timer.function = ec_master_run_eoe; + master->eoe_timer.data = (unsigned long) master; +#else + if (!(master->eoe_workqueue = create_singlethread_workqueue("EoE"))) { + EC_ERR("Failed to create EoE workqueue.\n"); + goto out_return; + } + INIT_WORK(&master->eoe_work, ec_master_run_eoe, (void *) master); +#endif + // init kobject and add it to the hierarchy memset(&master->kobj, 0x00, sizeof(struct kobject)); kobject_init(&master->kobj); master->kobj.ktype = &ktype_ec_master; if (kobject_set_name(&master->kobj, "ethercat%i", index)) { EC_ERR("Failed to set kobj name.\n"); - kobject_put(&master->kobj); - return -1; - } - - // init freerun timer - init_timer(&master->freerun_timer); - master->freerun_timer.function = ec_master_freerun; - master->freerun_timer.data = (unsigned long) master; - - // init eoe timer - init_timer(&master->eoe_timer); - master->eoe_timer.function = ec_master_run_eoe; - master->eoe_timer.data = (unsigned long) master; - - ec_command_init(&master->simple_command); - ec_command_init(&master->watch_command); + goto out_kobj_put; + } ec_master_reset(master); return 0; + + out_kobj_put: + kobject_put(&master->kobj); +#ifndef EOE_TIMER + out_return: +#endif + return -1; } /*****************************************************************************/ @@ -139,9 +157,6 @@ EC_INFO("Clearing master %i...\n", master->index); - del_timer_sync(&master->eoe_timer); - del_timer_sync(&master->freerun_timer); - ec_master_reset(master); if (master->device) { @@ -152,6 +167,10 @@ ec_command_clear(&master->simple_command); ec_command_clear(&master->watch_command); +#ifndef EOE_TIMER + if (master->eoe_workqueue) destroy_workqueue(master->eoe_workqueue); +#endif + EC_INFO("Master %i cleared.\n", master->index); } @@ -171,7 +190,15 @@ ec_eoe_t *eoe, *next_eoe; // stop EoE processing +#ifdef EOE_TIMER del_timer_sync(&master->eoe_timer); +#else + if (master->eoe_workqueue) { + if (!cancel_delayed_work(&master->eoe_work)) { + flush_workqueue(master->eoe_workqueue); + } + } +#endif // stop free-run mode ec_master_freerun_stop(master); @@ -839,12 +866,17 @@ Does the Ethernet-over-EtherCAT processing. */ +#ifdef EOE_TIMER void ec_master_run_eoe(unsigned long data /**< master pointer */) +#else +void ec_master_run_eoe(void *data /**< master pointer */) +#endif { ec_master_t *master = (ec_master_t *) data; ec_eoe_t *eoe; - if (!master->request_cb(master->cb_data)) goto restart_timer; + // request_cb must return 0, if the lock has been aquired! + if (master->request_cb(master->cb_data)) goto queue; ecrt_master_async_receive(master); list_for_each_entry(eoe, &master->eoe_slaves, list) { @@ -854,9 +886,13 @@ master->release_cb(master->cb_data); - restart_timer: + queue: +#ifdef EOE_TIMER master->eoe_timer.expires += HZ / 1000; add_timer(&master->eoe_timer); +#else + queue_delayed_work(master->eoe_workqueue, &master->eoe_work, HZ / 1000); +#endif } /****************************************************************************** @@ -1420,6 +1456,9 @@ /** Sets the locking callbacks. + The request_cb function must return zero, to allow another instance + (the EoE process for example) to access the master. Non-zero means, + that access is forbidden at this time. \ingroup RealtimeInterface */ @@ -1472,8 +1511,12 @@ } // start EoE processing +#ifdef EOE_TIMER master->eoe_timer.expires = jiffies + 10; add_timer(&master->eoe_timer); +#else + queue_work(master->eoe_workqueue, &master->eoe_work); +#endif return 0; } diff -r 9e8150db6fc8 -r 07247920a7ba master/master.h --- a/master/master.h Wed May 10 11:33:10 2006 +0000 +++ b/master/master.h Wed May 10 11:51:05 2006 +0000 @@ -40,6 +40,14 @@ /*****************************************************************************/ +// Uncomment this to do EoE within a kernel timer. Otherwise, it will be +// done in a working queue. + +//#define EOE_TIMER + + +/*****************************************************************************/ + /** EtherCAT master mode. */ @@ -100,7 +108,12 @@ int (*request_cb)(void *); /**< lock request callback */ void (*release_cb)(void *); /**< lock release callback */ void *cb_data; /**< data parameter of locking callbacks */ +#ifdef EOE_TIMER struct timer_list eoe_timer; /** EoE timer object */ +#else + struct workqueue_struct *eoe_workqueue; /**< EoE workqueue */ + struct work_struct eoe_work; /**< work structure for EoE workqueue */ +#endif }; /*****************************************************************************/