Using common waitqueue for requests. stable-1.5
authorFlorian Pose <fp@igh-essen.com>
Tue, 04 Dec 2012 16:05:23 +0100
branchstable-1.5
changeset 2467 74ede087bc85
parent 2466 a0b686241178
child 2468 3134b7255f3d
Using common waitqueue for requests.
master/fsm_master.c
master/fsm_slave.c
master/ioctl.c
master/master.c
master/master.h
master/slave.c
master/slave.h
--- a/master/fsm_master.c	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/fsm_master.c	Tue Dec 04 16:05:23 2012 +0100
@@ -1136,7 +1136,7 @@
     if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
         EC_SLAVE_ERR(slave, "Failed to write SII data.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&master->sii_queue);
+        wake_up(&master->request_queue);
         ec_fsm_master_restart(fsm);
         return;
     }
@@ -1164,7 +1164,7 @@
     // TODO: Evaluate other SII contents!
 
     request->state = EC_INT_REQUEST_SUCCESS;
-    wake_up(&master->sii_queue);
+    wake_up(&master->request_queue);
 
     // check for another SII write request
     if (ec_fsm_master_action_process_sii(fsm))
@@ -1232,14 +1232,14 @@
         EC_SLAVE_DBG(fsm->slave, 1,
                 "Failed to process internal SDO request.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&fsm->slave->sdo_queue);
+        wake_up(&fsm->master->request_queue);
         ec_fsm_master_restart(fsm);
         return;
     }
 
     // SDO request finished
     request->state = EC_INT_REQUEST_SUCCESS;
-    wake_up(&fsm->slave->sdo_queue);
+    wake_up(&fsm->master->request_queue);
 
     EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n");
 
--- a/master/fsm_slave.c	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/fsm_slave.c	Tue Dec 04 16:05:23 2012 +0100
@@ -180,45 +180,45 @@
         )
 {
     ec_slave_t *slave = fsm->slave;
-    ec_sdo_request_t *request, *next;
-
-    // search the first external request to be processed
-    list_for_each_entry_safe(request, next, &slave->sdo_requests, list) {
-
-        list_del_init(&request->list); // dequeue
-        if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
-            EC_SLAVE_WARN(slave, "Aborting SDO request,"
-                    " slave has error flag set.\n");
-            request->state = EC_INT_REQUEST_FAILURE;
-            wake_up(&slave->sdo_queue);
-            fsm->sdo_request = NULL;
-            fsm->state = ec_fsm_slave_state_idle;
-            return 0;
-        }
-
-        if (slave->current_state == EC_SLAVE_STATE_INIT) {
-            EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
-            request->state = EC_INT_REQUEST_FAILURE;
-            wake_up(&slave->sdo_queue);
-            fsm->sdo_request = NULL;
-            fsm->state = ec_fsm_slave_state_idle;
-            return 0;
-        }
-
-        request->state = EC_INT_REQUEST_BUSY;
-
-        // Found pending SDO request. Execute it!
-        EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
-
-        // Start SDO transfer
-        fsm->sdo_request = request;
-        fsm->state = ec_fsm_slave_state_sdo_request;
-        ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
-        ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
-        ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
+    ec_sdo_request_t *request;
+
+    if (list_empty(&slave->sdo_requests)) {
+        return 0;
+    }
+
+    // take the first request to be processed
+    request = list_entry(slave->sdo_requests.next, ec_sdo_request_t, list);
+    list_del_init(&request->list); // dequeue
+
+    if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) {
+        EC_SLAVE_WARN(slave, "Aborting SDO request,"
+                " slave has error flag set.\n");
+        request->state = EC_INT_REQUEST_FAILURE;
+        wake_up(&slave->master->request_queue);
+        fsm->state = ec_fsm_slave_state_idle;
         return 1;
     }
-    return 0;
+
+    if (slave->current_state == EC_SLAVE_STATE_INIT) {
+        EC_SLAVE_WARN(slave, "Aborting SDO request, slave is in INIT.\n");
+        request->state = EC_INT_REQUEST_FAILURE;
+        wake_up(&slave->master->request_queue);
+        fsm->state = ec_fsm_slave_state_idle;
+        return 1;
+    }
+
+    request->state = EC_INT_REQUEST_BUSY;
+
+    // Found pending SDO request. Execute it!
+    EC_SLAVE_DBG(slave, 1, "Processing SDO request...\n");
+
+    // Start SDO transfer
+    fsm->sdo_request = request;
+    fsm->state = ec_fsm_slave_state_sdo_request;
+    ec_fsm_coe_transfer(&fsm->fsm_coe, slave, request);
+    ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
+    ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram);
+    return 1;
 }
 
 /*****************************************************************************/
@@ -240,7 +240,7 @@
     if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
         EC_SLAVE_ERR(slave, "Failed to process SDO request.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->sdo_queue);
+        wake_up(&slave->master->request_queue);
         fsm->sdo_request = NULL;
         fsm->state = ec_fsm_slave_state_ready;
         return;
@@ -250,8 +250,7 @@
 
     // SDO request finished
     request->state = EC_INT_REQUEST_SUCCESS;
-    wake_up(&slave->sdo_queue);
-
+    wake_up(&slave->master->request_queue);
     fsm->sdo_request = NULL;
     fsm->state = ec_fsm_slave_state_ready;
 }
@@ -296,7 +295,8 @@
         EC_SLAVE_WARN(slave, "Aborting register request,"
                 " slave has error flag set.\n");
         fsm->reg_request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->reg_queue);
+        wake_up(&slave->master->request_queue);
+        fsm->reg_request = NULL;
         fsm->state = ec_fsm_slave_state_idle;
         return 1;
     }
@@ -345,7 +345,8 @@
                 " request datagram: ");
         ec_datagram_print_state(fsm->datagram);
         reg->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->reg_queue);
+        wake_up(&slave->master->request_queue);
+        fsm->reg_request = NULL;
         fsm->state = ec_fsm_slave_state_ready;
         return;
     }
@@ -365,7 +366,8 @@
                 fsm->datagram->working_counter);
     }
 
-    wake_up(&slave->reg_queue);
+    wake_up(&slave->master->request_queue);
+    fsm->reg_request = NULL;
     fsm->state = ec_fsm_slave_state_ready;
 }
 
@@ -394,8 +396,9 @@
         EC_SLAVE_WARN(slave, "Aborting FoE request,"
                 " slave has error flag set.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->sdo_queue);
-        return 0;
+        wake_up(&slave->master->request_queue);
+        fsm->state = ec_fsm_slave_state_idle;
+        return 1;
     }
 
     request->state = EC_INT_REQUEST_BUSY;
@@ -429,7 +432,7 @@
     if (!ec_fsm_foe_success(&fsm->fsm_foe)) {
         EC_SLAVE_ERR(slave, "Failed to handle FoE request.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->foe_queue);
+        wake_up(&slave->master->request_queue);
         fsm->foe_request = NULL;
         fsm->state = ec_fsm_slave_state_ready;
         return;
@@ -440,8 +443,7 @@
             " data.\n", request->data_size);
 
     request->state = EC_INT_REQUEST_SUCCESS;
-    wake_up(&slave->foe_queue);
-
+    wake_up(&slave->master->request_queue);
     fsm->foe_request = NULL;
     fsm->state = ec_fsm_slave_state_ready;
 }
@@ -471,14 +473,16 @@
         EC_SLAVE_WARN(slave, "Aborting SoE request,"
                 " slave has error flag set.\n");
         req->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->soe_queue);
-        return 0;
+        wake_up(&slave->master->request_queue);
+        fsm->state = ec_fsm_slave_state_idle;
+        return 1;
     }
 
     if (slave->current_state == EC_SLAVE_STATE_INIT) {
         EC_SLAVE_WARN(slave, "Aborting SoE request, slave is in INIT.\n");
         req->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->soe_queue);
+        wake_up(&slave->master->request_queue);
+        fsm->state = ec_fsm_slave_state_idle;
         return 0;
     }
 
@@ -515,7 +519,7 @@
     if (!ec_fsm_soe_success(&fsm->fsm_soe)) {
         EC_SLAVE_ERR(slave, "Failed to process SoE request.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->soe_queue);
+        wake_up(&slave->master->request_queue);
         fsm->soe_request = NULL;
         fsm->state = ec_fsm_slave_state_ready;
         return;
@@ -525,8 +529,7 @@
 
     // SoE request finished
     request->state = EC_INT_REQUEST_SUCCESS;
-    wake_up(&slave->soe_queue);
-
+    wake_up(&slave->master->request_queue);
     fsm->soe_request = NULL;
     fsm->state = ec_fsm_slave_state_ready;
 }
--- a/master/ioctl.c	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/ioctl.c	Tue Dec 04 16:05:23 2012 +0100
@@ -911,8 +911,9 @@
         return -EFAULT;
     }
 
-    if (!data.nwords)
+    if (!data.nwords) {
         return 0;
+    }
 
     byte_size = sizeof(uint16_t) * data.nwords;
     if (!(words = kmalloc(byte_size, GFP_KERNEL))) {
@@ -927,8 +928,10 @@
         return -EFAULT;
     }
 
-    if (down_interruptible(&master->master_sem))
+    if (down_interruptible(&master->master_sem)) {
+        kfree(words);
         return -EINTR;
+    }
 
     if (!(slave = ec_master_find_slave(
                     master, 0, data.slave_position))) {
@@ -953,7 +956,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(master->sii_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -968,7 +971,7 @@
     }
 
     // wait until master FSM has finished processing
-    wait_event(master->sii_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     kfree(words);
 
@@ -1025,7 +1028,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->reg_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -1040,7 +1043,7 @@
     }
 
     // wait until master FSM has finished processing
-    wait_event(slave->reg_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     if (request.state == EC_INT_REQUEST_SUCCESS) {
         if (copy_to_user((void __user *) io.data, request.data, io.size)) {
@@ -1092,8 +1095,7 @@
         return -EINTR;
     }
 
-    if (!(slave = ec_master_find_slave(
-                    master, 0, io.slave_position))) {
+    if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
         up(&master->master_sem);
         ec_reg_request_clear(&request);
         EC_MASTER_ERR(master, "Slave %u does not exist!\n",
@@ -1107,7 +1109,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->reg_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -1122,7 +1124,7 @@
     }
 
     // wait until master FSM has finished processing
-    wait_event(slave->reg_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     ec_reg_request_clear(&request);
 
@@ -3597,15 +3599,15 @@
         return -EINVAL;
     }
 
+    EC_SLAVE_DBG(slave, 1, "Scheduling FoE read request.\n");
+
     // schedule request.
     list_add_tail(&request.list, &slave->foe_requests);
 
     up(&master->master_sem);
 
-    EC_SLAVE_DBG(slave, 1, "Scheduled FoE read request.\n");
-
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->foe_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -3619,17 +3621,12 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid
-
     // wait until master FSM has finished processing
-    wait_event(slave->foe_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     io.result = request.result;
     io.error_code = request.error_code;
 
-    EC_SLAVE_DBG(slave, 1, "Read %zd bytes via FoE (result = 0x%x).\n",
-            request.data_size, request.result);
-
     if (request.state != EC_INT_REQUEST_SUCCESS) {
         io.data_size = 0;
         ret = -EIO;
@@ -3652,10 +3649,7 @@
         ret = -EFAULT;
     }
 
-    EC_SLAVE_DBG(slave, 1, "Finished FoE read request.\n");
-
     ec_foe_request_clear(&request);
-
     return ret;
 }
 
@@ -3715,7 +3709,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->foe_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -3729,10 +3723,8 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid
-
     // wait until master FSM has finished processing
-    wait_event(slave->foe_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     io.result = request.result;
     io.error_code = request.error_code;
@@ -3744,9 +3736,6 @@
     }
 
     ec_foe_request_clear(&request);
-
-    EC_SLAVE_DBG(slave, 1, "Finished FoE write request.\n");
-
     return ret;
 }
 
--- a/master/master.c	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/master.c	Tue Dec 04 16:05:23 2012 +0100
@@ -220,7 +220,8 @@
     master->app_cb_data = NULL;
 
     INIT_LIST_HEAD(&master->sii_requests);
-    init_waitqueue_head(&master->sii_queue);
+
+    init_waitqueue_head(&master->request_queue);
 
     // init devices
     for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
@@ -434,8 +435,8 @@
 
     master->dc_ref_clock = NULL;
 
-    // external requests are obsolete, so we wake pending waiters and remove
-    // them from the list
+    // External requests are obsolete, so we wake pending waiters and remove
+    // them from the list.
 
     while (!list_empty(&master->sii_requests)) {
         ec_sii_write_request_t *request =
@@ -445,7 +446,7 @@
         EC_MASTER_WARN(master, "Discarding SII request, slave %u about"
                 " to be deleted.\n", request->slave->ring_position);
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&master->sii_queue);
+        wake_up(&master->request_queue);
     }
 
     for (slave = master->slaves;
@@ -2667,6 +2668,7 @@
 {
     ec_sdo_request_t request;
     ec_slave_t *slave;
+    int ret;
 
     EC_MASTER_DBG(master, 1, "%s(master = 0x%p,"
             " slave_position = %u, index = 0x%04X, subindex = 0x%02X,"
@@ -2681,9 +2683,10 @@
 
     ec_sdo_request_init(&request);
     ecrt_sdo_request_index(&request, index, subindex);
-    if (ec_sdo_request_alloc(&request, data_size)) {
+    ret = ec_sdo_request_alloc(&request, data_size);
+    if (ret) {
         ec_sdo_request_clear(&request);
-        return -ENOMEM;
+        return ret;
     }
 
     memcpy(request.data, data, data_size);
@@ -2702,7 +2705,7 @@
         return -EINVAL;
     }
 
-    EC_SLAVE_DBG(slave, 1, "Schedule SDO download request.\n");
+    EC_SLAVE_DBG(slave, 1, "Scheduling SDO download request.\n");
 
     // schedule request.
     list_add_tail(&request.list, &slave->sdo_requests);
@@ -2710,7 +2713,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->sdo_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -2724,22 +2727,21 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid!
-
     // wait until master FSM has finished processing
-    wait_event(slave->sdo_queue, request.state != EC_INT_REQUEST_BUSY);
-
-    EC_SLAVE_DBG(slave, 1, "Finished SDO download request.\n");
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     *abort_code = request.abort_code;
 
     if (request.state == EC_INT_REQUEST_SUCCESS) {
-        return 0;
+        ret = 0;
     } else if (request.errno) {
-        return -request.errno;
+        ret = -request.errno;
     } else {
-        return -EIO;
-    }
+        ret = -EIO;
+    }
+
+    ec_sdo_request_clear(&request);
+    return ret;
 }
 
 /*****************************************************************************/
@@ -2750,6 +2752,7 @@
 {
     ec_sdo_request_t request;
     ec_slave_t *slave;
+    int ret;
 
     EC_MASTER_DBG(master, 1, "%s(master = 0x%p,"
             " slave_position = %u, index = 0x%04X,"
@@ -2764,9 +2767,10 @@
 
     ec_sdo_request_init(&request);
     ecrt_sdo_request_index(&request, index, 0);
-    if (ec_sdo_request_alloc(&request, data_size)) {
+    ret = ec_sdo_request_alloc(&request, data_size);
+    if (ret) {
         ec_sdo_request_clear(&request);
-        return -ENOMEM;
+        return ret;
     }
 
     request.complete_access = 1;
@@ -2786,7 +2790,7 @@
         return -EINVAL;
     }
 
-    EC_SLAVE_DBG(slave, 1, "Schedule SDO download request"
+    EC_SLAVE_DBG(slave, 1, "Scheduling SDO download request"
             " (complete access).\n");
 
     // schedule request.
@@ -2795,7 +2799,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->sdo_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -2809,23 +2813,21 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid!
-
     // wait until master FSM has finished processing
-    wait_event(slave->sdo_queue, request.state != EC_INT_REQUEST_BUSY);
-
-    EC_SLAVE_DBG(slave, 1, "Finished SDO download request"
-            " (complete access).\n");
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     *abort_code = request.abort_code;
 
     if (request.state == EC_INT_REQUEST_SUCCESS) {
-        return 0;
+        ret = 0;
     } else if (request.errno) {
-        return -request.errno;
+        ret = -request.errno;
     } else {
-        return -EIO;
-    }
+        ret = -EIO;
+    }
+
+    ec_sdo_request_clear(&request);
+    return ret;
 }
 
 /*****************************************************************************/
@@ -2836,7 +2838,7 @@
 {
     ec_sdo_request_t request;
     ec_slave_t *slave;
-    int retval = 0;
+    int ret = 0;
 
     EC_MASTER_DBG(master, 1, "%s(master = 0x%p,"
             " slave_position = %u, index = 0x%04X, subindex = 0x%02X,"
@@ -2861,7 +2863,7 @@
         return -EINVAL;
     }
 
-    EC_SLAVE_DBG(slave, 1, "Schedule SDO upload request.\n");
+    EC_SLAVE_DBG(slave, 1, "Scheduling SDO upload request.\n");
 
     // schedule request.
     list_add_tail(&request.list, &slave->sdo_requests);
@@ -2869,7 +2871,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->sdo_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -2883,34 +2885,32 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid!
-
     // wait until master FSM has finished processing
-    wait_event(slave->sdo_queue, request.state != EC_INT_REQUEST_BUSY);
-
-    EC_SLAVE_DBG(slave, 1, "Finished SDO upload request.\n");
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     *abort_code = request.abort_code;
 
     if (request.state != EC_INT_REQUEST_SUCCESS) {
         *result_size = 0;
         if (request.errno) {
-            retval = -request.errno;
+            ret = -request.errno;
         } else {
-            retval = -EIO;
+            ret = -EIO;
         }
     } else {
         if (request.data_size > target_size) {
             EC_MASTER_ERR(master, "Buffer too small.\n");
-            ec_sdo_request_clear(&request);
-            return -EOVERFLOW;
-        }
-        memcpy(target, request.data, request.data_size);
-        *result_size = request.data_size;
+            ret = -EOVERFLOW;
+        }
+        else {
+            memcpy(target, request.data, request.data_size);
+            *result_size = request.data_size;
+            ret = 0;
+        }
     }
 
     ec_sdo_request_clear(&request);
-    return retval;
+    return ret;
 }
 
 /*****************************************************************************/
@@ -2963,7 +2963,7 @@
     up(&master->master_sem);
 
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->soe_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -2977,10 +2977,8 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid
-
     // wait until master FSM has finished processing
-    wait_event(slave->soe_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     if (error_code) {
         *error_code = request.error_code;
@@ -3023,15 +3021,15 @@
         return -EINVAL;
     }
 
+    EC_SLAVE_DBG(slave, 1, "Scheduling SoE read request.\n");
+
     // schedule request.
     list_add_tail(&request.list, &slave->soe_requests);
 
     up(&master->master_sem);
 
-    EC_SLAVE_DBG(slave, 1, "Scheduled SoE read request.\n");
-
     // wait for processing through FSM
-    if (wait_event_interruptible(slave->soe_queue,
+    if (wait_event_interruptible(master->request_queue,
                 request.state != EC_INT_REQUEST_QUEUED)) {
         // interrupted by signal
         down(&master->master_sem);
@@ -3045,17 +3043,13 @@
         up(&master->master_sem);
     }
 
-    // FIXME slave may become invalid
-
     // wait until master FSM has finished processing
-    wait_event(slave->soe_queue, request.state != EC_INT_REQUEST_BUSY);
+    wait_event(master->request_queue, request.state != EC_INT_REQUEST_BUSY);
 
     if (error_code) {
         *error_code = request.error_code;
     }
 
-    EC_SLAVE_DBG(slave, 1, "Read %zd bytes via SoE.\n", request.data_size);
-
     if (request.state != EC_INT_REQUEST_SUCCESS) {
         if (result_size) {
             *result_size = 0;
--- a/master/master.h	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/master.h	Tue Dec 04 16:05:23 2012 +0100
@@ -287,8 +287,9 @@
     void *app_cb_data; /**< Application callback data. */
 
     struct list_head sii_requests; /**< SII write requests. */
-    wait_queue_head_t sii_queue; /**< Wait queue for SII
-                                      write requests from user space. */
+
+    wait_queue_head_t request_queue; /**< Wait queue for external requests
+                                       from user space. */
 };
 
 /*****************************************************************************/
--- a/master/slave.c	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/slave.c	Tue Dec 04 16:05:23 2012 +0100
@@ -153,16 +153,9 @@
     slave->jiffies_preop = 0;
 
     INIT_LIST_HEAD(&slave->sdo_requests);
-    init_waitqueue_head(&slave->sdo_queue);
-
     INIT_LIST_HEAD(&slave->reg_requests);
-    init_waitqueue_head(&slave->reg_queue);
-
     INIT_LIST_HEAD(&slave->foe_requests);
-    init_waitqueue_head(&slave->foe_queue);
-
     INIT_LIST_HEAD(&slave->soe_requests);
-    init_waitqueue_head(&slave->soe_queue);
 
     // init state machine datagram
     ec_datagram_init(&slave->fsm_datagram);
@@ -201,7 +194,7 @@
         EC_SLAVE_WARN(slave, "Discarding SDO request,"
                 " slave about to be deleted.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->sdo_queue);
+        wake_up(&slave->master->request_queue);
     }
 
     while (!list_empty(&slave->reg_requests)) {
@@ -211,7 +204,7 @@
         EC_SLAVE_WARN(slave, "Discarding register request,"
                 " slave about to be deleted.\n");
         reg->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->reg_queue);
+        wake_up(&slave->master->request_queue);
     }
 
     while (!list_empty(&slave->foe_requests)) {
@@ -221,7 +214,7 @@
         EC_SLAVE_WARN(slave, "Discarding FoE request,"
                 " slave about to be deleted.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->foe_queue);
+        wake_up(&slave->master->request_queue);
     }
 
     while (!list_empty(&slave->soe_requests)) {
@@ -231,7 +224,7 @@
         EC_SLAVE_WARN(slave, "Discarding SoE request,"
                 " slave about to be deleted.\n");
         request->state = EC_INT_REQUEST_FAILURE;
-        wake_up(&slave->soe_queue);
+        wake_up(&slave->master->request_queue);
     }
 
     if (slave->config) {
--- a/master/slave.h	Tue Dec 04 14:54:12 2012 +0100
+++ b/master/slave.h	Tue Dec 04 16:05:23 2012 +0100
@@ -225,17 +225,10 @@
     unsigned long jiffies_preop; /**< Time, the slave went to PREOP. */
 
     struct list_head 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 access requests. */
-    wait_queue_head_t reg_queue; /**< Wait queue for register access requests
-                                   from user space. */
     struct list_head foe_requests; /**< FoE write requests. */
-    wait_queue_head_t foe_queue; /**< Wait queue for FoE requests from user
-                                   space. */
-    struct list_head soe_requests; /**< FoE write requests. */
-    wait_queue_head_t soe_queue; /**< Wait queue for SoE requests from user
-                                   space. */
+    struct list_head soe_requests; /**< SoE write requests. */
+
     ec_fsm_slave_t fsm; /**< Slave state machine. */
     ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */
 };