diff -r e6cc33cac6a2 -r 35611452b785 master/master.c --- a/master/master.c Tue Dec 04 14:26:30 2012 +0100 +++ b/master/master.c Tue Dec 04 14:49:23 2012 +0100 @@ -2919,73 +2919,76 @@ uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, uint16_t *error_code) { - ec_master_soe_request_t request; - int retval; + ec_soe_request_t request; + ec_slave_t *slave; + int ret; if (drive_no > 7) { EC_MASTER_ERR(master, "Invalid drive number!\n"); return -EINVAL; } - INIT_LIST_HEAD(&request.list); - ec_soe_request_init(&request.req); - ec_soe_request_set_drive_no(&request.req, drive_no); - ec_soe_request_set_idn(&request.req, idn); - - if (ec_soe_request_alloc(&request.req, data_size)) { - ec_soe_request_clear(&request.req); - return -ENOMEM; - } - - memcpy(request.req.data, data, data_size); - request.req.data_size = data_size; - ec_soe_request_write(&request.req); - - if (down_interruptible(&master->master_sem)) + ec_soe_request_init(&request); + ec_soe_request_set_drive_no(&request, drive_no); + ec_soe_request_set_idn(&request, idn); + + ret = ec_soe_request_alloc(&request, data_size); + if (ret) { + ec_soe_request_clear(&request); + return ret; + } + + memcpy(request.data, data, data_size); + request.data_size = data_size; + ec_soe_request_write(&request); + + if (down_interruptible(&master->master_sem)) { + ec_soe_request_clear(&request); return -EINTR; - - if (!(request.slave = ec_master_find_slave( - master, 0, slave_position))) { + } + + if (!(slave = ec_master_find_slave(master, 0, slave_position))) { up(&master->master_sem); EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); - ec_soe_request_clear(&request.req); + ec_soe_request_clear(&request); return -EINVAL; } - EC_SLAVE_DBG(request.slave, 1, "Scheduling SoE write request.\n"); + EC_SLAVE_DBG(slave, 1, "Scheduling SoE write request.\n"); // schedule SoE write request. - list_add_tail(&request.list, &request.slave->soe_requests); + list_add_tail(&request.list, &slave->soe_requests); up(&master->master_sem); // wait for processing through FSM - if (wait_event_interruptible(request.slave->soe_queue, - request.req.state != EC_INT_REQUEST_QUEUED)) { + if (wait_event_interruptible(slave->soe_queue, + request.state != EC_INT_REQUEST_QUEUED)) { // interrupted by signal down(&master->master_sem); - if (request.req.state == EC_INT_REQUEST_QUEUED) { + if (request.state == EC_INT_REQUEST_QUEUED) { // abort request list_del(&request.list); up(&master->master_sem); - ec_soe_request_clear(&request.req); + ec_soe_request_clear(&request); return -EINTR; } up(&master->master_sem); } + // FIXME slave may become invalid + // wait until master FSM has finished processing - wait_event(request.slave->soe_queue, - request.req.state != EC_INT_REQUEST_BUSY); + wait_event(slave->soe_queue, request.state != EC_INT_REQUEST_BUSY); if (error_code) { - *error_code = request.req.error_code; - } - retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; - ec_soe_request_clear(&request.req); - - return retval; + *error_code = request.error_code; + } + ret = request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; + ec_soe_request_clear(&request); + + return ret; } /*****************************************************************************/ @@ -2994,80 +2997,86 @@ uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, size_t *result_size, uint16_t *error_code) { - ec_master_soe_request_t request; + ec_soe_request_t request; + ec_slave_t *slave; + int ret; if (drive_no > 7) { EC_MASTER_ERR(master, "Invalid drive number!\n"); return -EINVAL; } - INIT_LIST_HEAD(&request.list); - ec_soe_request_init(&request.req); - ec_soe_request_set_drive_no(&request.req, drive_no); - ec_soe_request_set_idn(&request.req, idn); - ec_soe_request_read(&request.req); - - if (down_interruptible(&master->master_sem)) + ec_soe_request_init(&request); + ec_soe_request_set_drive_no(&request, drive_no); + ec_soe_request_set_idn(&request, idn); + ec_soe_request_read(&request); + + if (down_interruptible(&master->master_sem)) { + ec_soe_request_clear(&request); return -EINTR; - - if (!(request.slave = ec_master_find_slave(master, 0, slave_position))) { + } + + if (!(slave = ec_master_find_slave(master, 0, slave_position))) { up(&master->master_sem); - ec_soe_request_clear(&request.req); + ec_soe_request_clear(&request); EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); return -EINVAL; } // schedule request. - list_add_tail(&request.list, &request.slave->soe_requests); + list_add_tail(&request.list, &slave->soe_requests); up(&master->master_sem); - EC_SLAVE_DBG(request.slave, 1, "Scheduled SoE read request.\n"); + EC_SLAVE_DBG(slave, 1, "Scheduled SoE read request.\n"); // wait for processing through FSM - if (wait_event_interruptible(request.slave->soe_queue, - request.req.state != EC_INT_REQUEST_QUEUED)) { + if (wait_event_interruptible(slave->soe_queue, + request.state != EC_INT_REQUEST_QUEUED)) { // interrupted by signal down(&master->master_sem); - if (request.req.state == EC_INT_REQUEST_QUEUED) { + if (request.state == EC_INT_REQUEST_QUEUED) { list_del(&request.list); up(&master->master_sem); - ec_soe_request_clear(&request.req); + ec_soe_request_clear(&request); return -EINTR; } // request already processing: interrupt not possible. up(&master->master_sem); } + // FIXME slave may become invalid + // wait until master FSM has finished processing - wait_event(request.slave->soe_queue, - request.req.state != EC_INT_REQUEST_BUSY); + wait_event(slave->soe_queue, request.state != EC_INT_REQUEST_BUSY); if (error_code) { - *error_code = request.req.error_code; - } - - EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via SoE.\n", - request.req.data_size); - - if (request.req.state != EC_INT_REQUEST_SUCCESS) { + *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; } - ec_soe_request_clear(&request.req); - return -EIO; - } else { - if (request.req.data_size > target_size) { + ret = -EIO; + } else { // success + if (request.data_size > target_size) { EC_MASTER_ERR(master, "Buffer too small.\n"); - ec_soe_request_clear(&request.req); - return -EOVERFLOW; - } - if (result_size) { - *result_size = request.req.data_size; - } - memcpy(target, request.req.data, request.req.data_size); - return 0; - } + ret = -EOVERFLOW; + } + else { // data fits in buffer + if (result_size) { + *result_size = request.data_size; + } + memcpy(target, request.data, request.data_size); + ret = 0; + } + } + + ec_soe_request_clear(&request); + return ret; } /*****************************************************************************/