diff --git a/master/cdev.c b/master/cdev.c index 0557af5496ef1d27886a2b6462712f10c8796063..8d509501feb92e56e83447b160652a73b475fca4 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -808,12 +808,12 @@ int ec_cdev_ioctl_slave_sdo_upload( if (master->debug_level) EC_DBG("Schedule SDO upload request for slave %u\n",request.slave->ring_position); // schedule request. - list_add_tail(&request.list, &master->slave_sdo_requests); + list_add_tail(&request.list, &request.slave->slave_sdo_requests); up(&master->master_sem); // wait for processing through FSM - if (wait_event_interruptible(master->sdo_queue, + if (wait_event_interruptible(request.slave->sdo_queue, request.req.state != EC_INT_REQUEST_QUEUED)) { // interrupted by signal down(&master->master_sem); @@ -828,7 +828,7 @@ int ec_cdev_ioctl_slave_sdo_upload( } // wait until master FSM has finished processing - wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY); + wait_event(request.slave->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY); if (master->debug_level) EC_DBG("Scheduled SDO upload request for slave %u done\n",request.slave->ring_position); @@ -914,12 +914,12 @@ int ec_cdev_ioctl_slave_sdo_download( if (master->debug_level) EC_DBG("Schedule SDO download request for slave %u\n",request.slave->ring_position); // schedule request. - list_add_tail(&request.list, &master->slave_sdo_requests); + list_add_tail(&request.list, &request.slave->slave_sdo_requests); up(&master->master_sem); // wait for processing through FSM - if (wait_event_interruptible(master->sdo_queue, + if (wait_event_interruptible(request.slave->sdo_queue, request.req.state != EC_INT_REQUEST_QUEUED)) { // interrupted by signal down(&master->master_sem); @@ -934,7 +934,7 @@ int ec_cdev_ioctl_slave_sdo_download( } // wait until master FSM has finished processing - wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY); + wait_event(request.slave->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY); if (master->debug_level) EC_DBG("Scheduled SDO download request for slave %u done\n",request.slave->ring_position); diff --git a/master/fsm_master.c b/master/fsm_master.c index 0d27545f538e0bde0d6703c3fde7cb558758bd47..5533f0c21a7261e70f6d6d80dd132d918540865c 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -1017,14 +1017,14 @@ void ec_fsm_master_state_sdo_request( EC_DBG("Failed to process internal SDO request for slave %u.\n", fsm->slave->ring_position); request->state = EC_INT_REQUEST_FAILURE; - wake_up(&master->sdo_queue); + wake_up(&fsm->slave->sdo_queue); ec_fsm_master_restart(fsm); return; } // SDO request finished request->state = EC_INT_REQUEST_SUCCESS; - wake_up(&master->sdo_queue); + wake_up(&fsm->slave->sdo_queue); if (master->debug_level) EC_DBG("Finished internal SDO request for slave %u.\n", diff --git a/master/fsm_slave.c b/master/fsm_slave.c index 0d2a067c51c44233cd1c4db3c44a182a6a201862..33ce879f33eef300c27c7b65b1a6a4c293c3102d 100644 --- a/master/fsm_slave.c +++ b/master/fsm_slave.c @@ -115,9 +115,7 @@ void ec_fsm_slave_state_idle( ec_master_sdo_request_t *request, *next; // search the first matching external request to be processed - list_for_each_entry_safe(request, next, &master->slave_sdo_requests, list) { - if (request->slave != slave) - continue; + list_for_each_entry_safe(request, next, &slave->slave_sdo_requests, list) { list_del_init(&request->list); // dequeue request->req.state = EC_INT_REQUEST_BUSY; @@ -125,7 +123,7 @@ void ec_fsm_slave_state_idle( EC_ERR("Discarding SDO request, slave %u is in INIT.\n", slave->ring_position); request->req.state = EC_INT_REQUEST_FAILURE; - wake_up(&master->sdo_queue); + wake_up(&slave->sdo_queue); continue; } @@ -165,7 +163,7 @@ void ec_fsm_slave_state_sdo_request( EC_DBG("Failed to process SDO request for slave %u.\n", fsm->slave->ring_position); request->state = EC_INT_REQUEST_FAILURE; - wake_up(&master->sdo_queue); + wake_up(&slave->sdo_queue); fsm->sdo_request = NULL; fsm->state = ec_fsm_slave_state_idle; return; @@ -173,7 +171,7 @@ void ec_fsm_slave_state_sdo_request( // SDO request finished request->state = EC_INT_REQUEST_SUCCESS; - wake_up(&master->sdo_queue); + wake_up(&slave->sdo_queue); if (master->debug_level) EC_DBG("Finished SDO request for slave %u.\n", diff --git a/master/master.c b/master/master.c index d1546580659caa530a0d627d3b4aaedd79970271..dfc049ba3f70dc3c60e825a03e2ea7d96955cad4 100644 --- a/master/master.c +++ b/master/master.c @@ -184,9 +184,6 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ INIT_LIST_HEAD(&master->sii_requests); init_waitqueue_head(&master->sii_queue); - INIT_LIST_HEAD(&master->slave_sdo_requests); - init_waitqueue_head(&master->sdo_queue); - INIT_LIST_HEAD(&master->reg_requests); init_waitqueue_head(&master->reg_queue); @@ -405,21 +402,6 @@ void ec_master_clear_slaves(ec_master_t *master) wake_up(&master->reg_queue); } - // SDO requests - while (1) { - ec_master_sdo_request_t *request; - if (list_empty(&master->slave_sdo_requests)) - break; - // get first request - request = list_entry(master->slave_sdo_requests.next, - ec_master_sdo_request_t, list); - list_del_init(&request->list); // dequeue - EC_INFO("Discarding SDO request, slave %u does not exist anymore.\n", - request->slave->ring_position); - request->req.state = EC_INT_REQUEST_FAILURE; - wake_up(&master->sdo_queue); - } - // FoE requests while (1) { ec_master_foe_request_t *request; @@ -438,6 +420,20 @@ void ec_master_clear_slaves(ec_master_t *master) for (slave = master->slaves; slave < master->slaves + master->slave_count; slave++) { + // SDO requests + while (1) { + ec_master_sdo_request_t *request; + if (list_empty(&slave->slave_sdo_requests)) + break; + // get first request + request = list_entry(slave->slave_sdo_requests.next, + ec_master_sdo_request_t, list); + list_del_init(&request->list); // dequeue + EC_INFO("Discarding SDO request, slave %u does not exist anymore.\n", + request->slave->ring_position); + request->req.state = EC_INT_REQUEST_FAILURE; + wake_up(&slave->sdo_queue); + } ec_slave_clear(slave); } @@ -770,6 +766,8 @@ void ec_master_queue_sdo_datagram( #endif datagram->jiffies_sent = jiffies; + master->fsm.idle = 0; + down(&master->io_sem); list_add_tail(&datagram->queue, &master->sdo_datagram_queue); up(&master->io_sem); diff --git a/master/master.h b/master/master.h index 00771b2b067ed643caa634426c43aa0415bad00d..baa3d10df2804a22d8dd61791c12fe4ba3921033 100644 --- a/master/master.h +++ b/master/master.h @@ -185,10 +185,6 @@ struct ec_master { wait_queue_head_t sii_queue; /**< Wait queue for SII write requests from user space. */ - struct list_head slave_sdo_requests; /**< SDO access requests. */ - wait_queue_head_t sdo_queue; /**< Wait queue for SDO access requests - from user space. */ - struct list_head reg_requests; /**< Register requests. */ wait_queue_head_t reg_queue; /**< Wait queue for register requests. */ diff --git a/master/slave.c b/master/slave.c index c6b0c6097a737750b99d9f8fec758f46552d8bbb..0175d3c4ff299b701d8adfd854761919e4b64cbc 100644 --- a/master/slave.c +++ b/master/slave.c @@ -149,6 +149,9 @@ void ec_slave_init( slave->sdo_dictionary_fetched = 0; slave->jiffies_preop = 0; + INIT_LIST_HEAD(&slave->slave_sdo_requests); + init_waitqueue_head(&slave->sdo_queue); + // init state machine datagram ec_datagram_init(&slave->fsm_datagram); snprintf(slave->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "slave%u-fsm",slave->ring_position); diff --git a/master/slave.h b/master/slave.h index 8c6cadaee4ce4aeb605757162118cd85b3d270be..4f5d4fcb9a4077a986c1a395d02ae2567e22dac3 100644 --- a/master/slave.h +++ b/master/slave.h @@ -159,6 +159,9 @@ struct ec_slave uint8_t sdo_dictionary_fetched; /**< Dictionary has been fetched. */ unsigned long jiffies_preop; /**< Time, the slave went to PREOP. */ + struct list_head slave_sdo_requests; /**< SDO access requests. */ + wait_queue_head_t sdo_queue; /**< Wait queue for SDO access requests + from user space. */ ec_fsm_slave_t fsm; /**< Slave state machine. */ ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */ };