From 4295244fabc703759f54cf1dbc6b4ad38d4ee3b5 Mon Sep 17 00:00:00 2001
From: Martin Troxler <martin.troxler@komaxgroup.com>
Date: Tue, 1 Dec 2009 14:24:57 +0100
Subject: [PATCH] Moved sdo request queue to slaves

---
 master/cdev.c       | 12 ++++++------
 master/fsm_master.c |  4 ++--
 master/fsm_slave.c  | 10 ++++------
 master/master.c     | 34 ++++++++++++++++------------------
 master/master.h     |  4 ----
 master/slave.c      |  3 +++
 master/slave.h      |  3 +++
 7 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/master/cdev.c b/master/cdev.c
index 0557af54..8d509501 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 0d27545f..5533f0c2 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 0d2a067c..33ce879f 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 d1546580..dfc049ba 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 00771b2b..baa3d10d 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 c6b0c609..0175d3c4 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 8c6cadae..4f5d4fcb 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. */
 };
-- 
GitLab