3268 ec_master_t *master, /**< EtherCAT master. */ |
3268 ec_master_t *master, /**< EtherCAT master. */ |
3269 unsigned long arg /**< ioctl() argument. */ |
3269 unsigned long arg /**< ioctl() argument. */ |
3270 ) |
3270 ) |
3271 { |
3271 { |
3272 ec_ioctl_slave_foe_t data; |
3272 ec_ioctl_slave_foe_t data; |
3273 ec_master_foe_request_t request; |
3273 ec_master_foe_request_t* request; |
3274 int retval; |
3274 int retval; |
3275 |
3275 |
3276 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3276 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3277 return -EFAULT; |
3277 return -EFAULT; |
3278 } |
3278 } |
3279 |
3279 |
3280 ec_foe_request_init(&request.req, data.file_name); |
3280 request = kmalloc(sizeof(*request), GFP_KERNEL); |
3281 ec_foe_request_read(&request.req); |
3281 if (!request) |
3282 ec_foe_request_alloc(&request.req, 10000); // FIXME |
3282 return -ENOMEM; |
3283 |
3283 kref_init(&request->refcount); |
3284 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
3284 |
3285 return -EINTR; |
3285 ec_foe_request_init(&request->req, data.file_name); |
3286 |
3286 ec_foe_request_read(&request->req); |
3287 if (!(request.slave = ec_master_find_slave( |
3287 ec_foe_request_alloc(&request->req, 10000); // FIXME |
|
3288 |
|
3289 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
3290 kref_put(&request->refcount,ec_master_foe_request_release); |
|
3291 return -EINTR; |
|
3292 } |
|
3293 if (!(request->slave = ec_master_find_slave( |
3288 master, 0, data.slave_position))) { |
3294 master, 0, data.slave_position))) { |
3289 ec_mutex_unlock(&master->master_mutex); |
3295 ec_mutex_unlock(&master->master_mutex); |
3290 ec_foe_request_clear(&request.req); |
3296 kref_put(&request->refcount,ec_master_foe_request_release); |
3291 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3297 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3292 data.slave_position); |
3298 data.slave_position); |
3293 return -EINVAL; |
3299 return -EINVAL; |
3294 } |
3300 } |
3295 |
3301 |
3296 // schedule request. |
3302 // schedule request. |
3297 list_add_tail(&request.list, &request.slave->foe_requests); |
3303 list_add_tail(&request->list, &request->slave->foe_requests); |
3298 |
3304 kref_get(&request->refcount); |
3299 ec_mutex_unlock(&master->master_mutex); |
3305 |
3300 |
3306 ec_mutex_unlock(&master->master_mutex); |
3301 EC_SLAVE_DBG(request.slave, 1, "Scheduled FoE read request.\n"); |
3307 |
|
3308 EC_SLAVE_DBG(request->slave, 1, "Scheduled FoE read request %p.\n",request); |
3302 |
3309 |
3303 // wait for processing through FSM |
3310 // wait for processing through FSM |
3304 if (wait_event_interruptible(request.slave->foe_queue, |
3311 if (wait_event_interruptible(request->slave->foe_queue, |
3305 request.req.state != EC_INT_REQUEST_QUEUED)) { |
3312 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
3306 // interrupted by signal |
3313 // interrupted by signal |
3307 ec_mutex_lock(&master->master_mutex); |
3314 kref_put(&request->refcount,ec_master_foe_request_release); |
3308 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
3315 return -EINTR; |
3309 list_del(&request.list); |
3316 } |
3310 ec_mutex_unlock(&master->master_mutex); |
3317 |
3311 ec_foe_request_clear(&request.req); |
3318 data.result = request->req.result; |
3312 return -EINTR; |
3319 data.error_code = request->req.error_code; |
3313 } |
3320 |
3314 // request already processing: interrupt not possible. |
3321 EC_SLAVE_DBG(request->slave, 1, "Read %zd bytes via FoE" |
3315 ec_mutex_unlock(&master->master_mutex); |
3322 " (result = 0x%x).\n", request->req.data_size, request->req.result); |
3316 } |
3323 |
3317 |
3324 if (request->req.state != EC_INT_REQUEST_SUCCESS) { |
3318 // wait until master FSM has finished processing |
|
3319 wait_event(request.slave->foe_queue, |
|
3320 request.req.state != EC_INT_REQUEST_BUSY); |
|
3321 |
|
3322 data.result = request.req.result; |
|
3323 data.error_code = request.req.error_code; |
|
3324 |
|
3325 EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via FoE" |
|
3326 " (result = 0x%x).\n", request.req.data_size, request.req.result); |
|
3327 |
|
3328 if (request.req.state != EC_INT_REQUEST_SUCCESS) { |
|
3329 data.data_size = 0; |
3325 data.data_size = 0; |
3330 retval = -EIO; |
3326 retval = -EIO; |
3331 } else { |
3327 } else { |
3332 if (request.req.data_size > data.buffer_size) { |
3328 if (request->req.data_size > data.buffer_size) { |
3333 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3329 EC_MASTER_ERR(master, "Buffer too small.\n"); |
3334 ec_foe_request_clear(&request.req); |
3330 kref_put(&request->refcount,ec_master_foe_request_release); |
3335 return -EOVERFLOW; |
3331 return -EOVERFLOW; |
3336 } |
3332 } |
3337 data.data_size = request.req.data_size; |
3333 data.data_size = request->req.data_size; |
3338 if (copy_to_user((void __user *) data.buffer, |
3334 if (copy_to_user((void __user *) data.buffer, |
3339 request.req.buffer, data.data_size)) { |
3335 request->req.buffer, data.data_size)) { |
3340 ec_foe_request_clear(&request.req); |
3336 kref_put(&request->refcount,ec_master_foe_request_release); |
3341 return -EFAULT; |
3337 return -EFAULT; |
3342 } |
3338 } |
3343 retval = 0; |
3339 retval = 0; |
3344 } |
3340 } |
3345 |
3341 |
3346 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3342 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3347 retval = -EFAULT; |
3343 retval = -EFAULT; |
3348 } |
3344 } |
3349 |
3345 |
3350 EC_SLAVE_DBG(request.slave, 1, "Finished FoE read request.\n"); |
3346 EC_SLAVE_DBG(request->slave, 1, "Finished FoE read request %p.\n",request); |
3351 |
3347 kref_put(&request->refcount,ec_master_foe_request_release); |
3352 ec_foe_request_clear(&request.req); |
|
3353 |
3348 |
3354 return retval; |
3349 return retval; |
3355 } |
3350 } |
3356 |
3351 |
3357 /*****************************************************************************/ |
3352 /*****************************************************************************/ |
3362 ec_master_t *master, /**< EtherCAT master. */ |
3357 ec_master_t *master, /**< EtherCAT master. */ |
3363 unsigned long arg /**< ioctl() argument. */ |
3358 unsigned long arg /**< ioctl() argument. */ |
3364 ) |
3359 ) |
3365 { |
3360 { |
3366 ec_ioctl_slave_foe_t data; |
3361 ec_ioctl_slave_foe_t data; |
3367 ec_master_foe_request_t request; |
3362 ec_master_foe_request_t* request; |
3368 int retval; |
3363 int retval; |
3369 |
3364 |
3370 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3365 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
3371 return -EFAULT; |
3366 return -EFAULT; |
3372 } |
3367 } |
3373 |
3368 |
3374 INIT_LIST_HEAD(&request.list); |
3369 request = kmalloc(sizeof(*request), GFP_KERNEL); |
3375 |
3370 if (!request) |
3376 ec_foe_request_init(&request.req, data.file_name); |
|
3377 |
|
3378 if (ec_foe_request_alloc(&request.req, data.buffer_size)) { |
|
3379 ec_foe_request_clear(&request.req); |
|
3380 return -ENOMEM; |
3371 return -ENOMEM; |
3381 } |
3372 kref_init(&request->refcount); |
3382 if (copy_from_user(request.req.buffer, |
3373 |
|
3374 INIT_LIST_HEAD(&request->list); |
|
3375 |
|
3376 ec_foe_request_init(&request->req, data.file_name); |
|
3377 |
|
3378 if (ec_foe_request_alloc(&request->req, data.buffer_size)) { |
|
3379 kref_put(&request->refcount,ec_master_foe_request_release); |
|
3380 return -ENOMEM; |
|
3381 } |
|
3382 if (copy_from_user(request->req.buffer, |
3383 (void __user *) data.buffer, data.buffer_size)) { |
3383 (void __user *) data.buffer, data.buffer_size)) { |
3384 ec_foe_request_clear(&request.req); |
3384 kref_put(&request->refcount,ec_master_foe_request_release); |
3385 return -EFAULT; |
3385 return -EFAULT; |
3386 } |
3386 } |
3387 request.req.data_size = data.buffer_size; |
3387 request->req.data_size = data.buffer_size; |
3388 ec_foe_request_write(&request.req); |
3388 ec_foe_request_write(&request->req); |
3389 |
3389 |
3390 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
3390 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
3391 return -EINTR; |
3391 return -EINTR; |
3392 |
3392 |
3393 if (!(request.slave = ec_master_find_slave( |
3393 if (!(request->slave = ec_master_find_slave( |
3394 master, 0, data.slave_position))) { |
3394 master, 0, data.slave_position))) { |
3395 ec_mutex_unlock(&master->master_mutex); |
3395 ec_mutex_unlock(&master->master_mutex); |
3396 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3396 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
3397 data.slave_position); |
3397 data.slave_position); |
3398 ec_foe_request_clear(&request.req); |
3398 kref_put(&request->refcount,ec_master_foe_request_release); |
3399 return -EINVAL; |
3399 return -EINVAL; |
3400 } |
3400 } |
3401 |
3401 |
3402 EC_SLAVE_DBG(request.slave, 1, "Scheduling FoE write request.\n"); |
3402 EC_SLAVE_DBG(request->slave, 1, "Scheduling FoE write request %p.\n",request); |
3403 |
3403 |
3404 // schedule FoE write request. |
3404 // schedule FoE write request. |
3405 list_add_tail(&request.list, &request.slave->foe_requests); |
3405 list_add_tail(&request->list, &request->slave->foe_requests); |
|
3406 kref_get(&request->refcount); |
3406 |
3407 |
3407 ec_mutex_unlock(&master->master_mutex); |
3408 ec_mutex_unlock(&master->master_mutex); |
3408 |
3409 |
3409 // wait for processing through FSM |
3410 // wait for processing through FSM |
3410 if (wait_event_interruptible(request.slave->foe_queue, |
3411 if (wait_event_interruptible(request->slave->foe_queue, |
3411 request.req.state != EC_INT_REQUEST_QUEUED)) { |
3412 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
3412 // interrupted by signal |
3413 // interrupted by signal |
3413 ec_mutex_lock(&master->master_mutex); |
3414 kref_put(&request->refcount,ec_master_foe_request_release); |
3414 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
3415 return -EINTR; |
3415 // abort request |
3416 } |
3416 list_del(&request.list); |
3417 |
3417 ec_mutex_unlock(&master->master_mutex); |
3418 data.result = request->req.result; |
3418 ec_foe_request_clear(&request.req); |
3419 data.error_code = request->req.error_code; |
3419 return -EINTR; |
3420 |
3420 } |
3421 retval = request->req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
3421 ec_mutex_unlock(&master->master_mutex); |
|
3422 } |
|
3423 |
|
3424 // wait until master FSM has finished processing |
|
3425 wait_event(request.slave->foe_queue, |
|
3426 request.req.state != EC_INT_REQUEST_BUSY); |
|
3427 |
|
3428 data.result = request.req.result; |
|
3429 data.error_code = request.req.error_code; |
|
3430 |
|
3431 retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
|
3432 |
3422 |
3433 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3423 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
3434 retval = -EFAULT; |
3424 retval = -EFAULT; |
3435 } |
3425 } |
3436 |
3426 |
3437 ec_foe_request_clear(&request.req); |
3427 EC_SLAVE_DBG(request->slave, 1, "Finished FoE write request %p.\n",request); |
3438 |
3428 kref_put(&request->refcount,ec_master_foe_request_release); |
3439 EC_SLAVE_DBG(request.slave, 1, "Finished FoE write request.\n"); |
|
3440 |
3429 |
3441 return retval; |
3430 return retval; |
3442 } |
3431 } |
3443 |
3432 |
3444 /*****************************************************************************/ |
3433 /*****************************************************************************/ |