2304 |
2304 |
2305 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
2305 int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, |
2306 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
2306 uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, |
2307 uint16_t *error_code) |
2307 uint16_t *error_code) |
2308 { |
2308 { |
2309 ec_master_soe_request_t request; |
2309 ec_master_soe_request_t* request; |
2310 int retval; |
2310 int retval; |
2311 |
2311 |
2312 if (drive_no > 7) { |
2312 if (drive_no > 7) { |
2313 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2313 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2314 return -EINVAL; |
2314 return -EINVAL; |
2315 } |
2315 } |
2316 |
2316 |
2317 INIT_LIST_HEAD(&request.list); |
2317 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2318 ec_soe_request_init(&request.req); |
2318 if (!request) |
2319 ec_soe_request_set_drive_no(&request.req, drive_no); |
|
2320 ec_soe_request_set_idn(&request.req, idn); |
|
2321 |
|
2322 if (ec_soe_request_alloc(&request.req, data_size)) { |
|
2323 ec_soe_request_clear(&request.req); |
|
2324 return -ENOMEM; |
2319 return -ENOMEM; |
2325 } |
2320 kref_init(&request->refcount); |
2326 |
2321 |
2327 memcpy(request.req.data, data, data_size); |
2322 INIT_LIST_HEAD(&request->list); |
2328 request.req.data_size = data_size; |
2323 ec_soe_request_init(&request->req); |
2329 ec_soe_request_write(&request.req); |
2324 ec_soe_request_set_drive_no(&request->req, drive_no); |
2330 |
2325 ec_soe_request_set_idn(&request->req, idn); |
2331 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
2326 |
|
2327 if (ec_soe_request_alloc(&request->req, data_size)) { |
|
2328 ec_soe_request_clear(&request->req); |
|
2329 kref_put(&request->refcount,ec_master_soe_request_release); |
|
2330 return -ENOMEM; |
|
2331 } |
|
2332 |
|
2333 memcpy(request->req.data, data, data_size); |
|
2334 request->req.data_size = data_size; |
|
2335 ec_soe_request_write(&request->req); |
|
2336 |
|
2337 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2338 kref_put(&request->refcount,ec_master_soe_request_release); |
2332 return -EINTR; |
2339 return -EINTR; |
2333 |
2340 } |
2334 if (!(request.slave = ec_master_find_slave( |
2341 |
|
2342 if (!(request->slave = ec_master_find_slave( |
2335 master, 0, slave_position))) { |
2343 master, 0, slave_position))) { |
2336 ec_mutex_unlock(&master->master_mutex); |
2344 ec_mutex_unlock(&master->master_mutex); |
2337 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
2345 EC_MASTER_ERR(master, "Slave %u does not exist!\n", |
2338 slave_position); |
2346 slave_position); |
2339 ec_soe_request_clear(&request.req); |
2347 kref_put(&request->refcount,ec_master_soe_request_release); |
2340 return -EINVAL; |
2348 return -EINVAL; |
2341 } |
2349 } |
2342 |
2350 |
2343 EC_SLAVE_DBG(request.slave, 1, "Scheduling SoE write request.\n"); |
2351 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE write request %p.\n",request); |
2344 |
2352 |
2345 // schedule SoE write request. |
2353 // schedule SoE write request. |
2346 list_add_tail(&request.list, &request.slave->soe_requests); |
2354 list_add_tail(&request->list, &request->slave->soe_requests); |
|
2355 kref_get(&request->refcount); |
2347 |
2356 |
2348 ec_mutex_unlock(&master->master_mutex); |
2357 ec_mutex_unlock(&master->master_mutex); |
2349 |
2358 |
2350 // wait for processing through FSM |
2359 // wait for processing through FSM |
2351 if (wait_event_interruptible(request.slave->soe_queue, |
2360 if (wait_event_interruptible(request->slave->soe_queue, |
2352 request.req.state != EC_INT_REQUEST_QUEUED)) { |
2361 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
2353 // interrupted by signal |
2362 // interrupted by signal |
2354 ec_mutex_lock(&master->master_mutex); |
2363 kref_put(&request->refcount,ec_master_soe_request_release); |
2355 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
2364 return -EINTR; |
2356 // abort request |
2365 } |
2357 list_del(&request.list); |
|
2358 ec_mutex_unlock(&master->master_mutex); |
|
2359 ec_soe_request_clear(&request.req); |
|
2360 return -EINTR; |
|
2361 } |
|
2362 ec_mutex_unlock(&master->master_mutex); |
|
2363 } |
|
2364 |
|
2365 // wait until master FSM has finished processing |
|
2366 wait_event(request.slave->soe_queue, |
|
2367 request.req.state != EC_INT_REQUEST_BUSY); |
|
2368 |
2366 |
2369 if (error_code) { |
2367 if (error_code) { |
2370 *error_code = request.req.error_code; |
2368 *error_code = request->req.error_code; |
2371 } |
2369 } |
2372 retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
2370 retval = request->req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
2373 ec_soe_request_clear(&request.req); |
2371 kref_put(&request->refcount,ec_master_soe_request_release); |
2374 |
2372 |
2375 return retval; |
2373 return retval; |
2376 } |
2374 } |
2377 |
2375 |
2378 /*****************************************************************************/ |
2376 /*****************************************************************************/ |
2379 |
2377 |
2380 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
2378 int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, |
2381 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
2379 uint8_t drive_no, uint16_t idn, uint8_t *target, size_t target_size, |
2382 size_t *result_size, uint16_t *error_code) |
2380 size_t *result_size, uint16_t *error_code) |
2383 { |
2381 { |
2384 ec_master_soe_request_t request; |
2382 ec_master_soe_request_t* request; |
2385 |
2383 |
2386 if (drive_no > 7) { |
2384 if (drive_no > 7) { |
2387 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2385 EC_MASTER_ERR(master, "Invalid drive number!\n"); |
2388 return -EINVAL; |
2386 return -EINVAL; |
2389 } |
2387 } |
2390 |
2388 |
2391 INIT_LIST_HEAD(&request.list); |
2389 request = kmalloc(sizeof(*request), GFP_KERNEL); |
2392 ec_soe_request_init(&request.req); |
2390 if (!request) |
2393 ec_soe_request_set_drive_no(&request.req, drive_no); |
2391 return -ENOMEM; |
2394 ec_soe_request_set_idn(&request.req, idn); |
2392 kref_init(&request->refcount); |
2395 ec_soe_request_read(&request.req); |
2393 |
2396 |
2394 INIT_LIST_HEAD(&request->list); |
2397 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
2395 ec_soe_request_init(&request->req); |
|
2396 ec_soe_request_set_drive_no(&request->req, drive_no); |
|
2397 ec_soe_request_set_idn(&request->req, idn); |
|
2398 ec_soe_request_read(&request->req); |
|
2399 |
|
2400 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
|
2401 kref_put(&request->refcount,ec_master_soe_request_release); |
2398 return -EINTR; |
2402 return -EINTR; |
2399 |
2403 } |
2400 if (!(request.slave = ec_master_find_slave(master, 0, slave_position))) { |
2404 |
|
2405 if (!(request->slave = ec_master_find_slave(master, 0, slave_position))) { |
2401 ec_mutex_unlock(&master->master_mutex); |
2406 ec_mutex_unlock(&master->master_mutex); |
2402 ec_soe_request_clear(&request.req); |
2407 kref_put(&request->refcount,ec_master_soe_request_release); |
2403 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2408 EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position); |
2404 return -EINVAL; |
2409 return -EINVAL; |
2405 } |
2410 } |
2406 |
2411 |
2407 // schedule request. |
2412 // schedule request. |
2408 list_add_tail(&request.list, &request.slave->soe_requests); |
2413 list_add_tail(&request->list, &request->slave->soe_requests); |
|
2414 kref_get(&request->refcount); |
2409 |
2415 |
2410 ec_mutex_unlock(&master->master_mutex); |
2416 ec_mutex_unlock(&master->master_mutex); |
2411 |
2417 |
2412 EC_SLAVE_DBG(request.slave, 1, "Scheduled SoE read request.\n"); |
2418 EC_SLAVE_DBG(request->slave, 1, "Scheduled SoE read request %p.\n",request); |
2413 |
2419 |
2414 // wait for processing through FSM |
2420 // wait for processing through FSM |
2415 if (wait_event_interruptible(request.slave->soe_queue, |
2421 if (wait_event_interruptible(request->slave->soe_queue, |
2416 request.req.state != EC_INT_REQUEST_QUEUED)) { |
2422 ((request->req.state == EC_INT_REQUEST_SUCCESS) || (request->req.state == EC_INT_REQUEST_FAILURE)))) { |
2417 // interrupted by signal |
2423 // interrupted by signal |
2418 ec_mutex_lock(&master->master_mutex); |
2424 kref_put(&request->refcount,ec_master_soe_request_release); |
2419 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
2425 return -EINTR; |
2420 list_del(&request.list); |
2426 } |
2421 ec_mutex_unlock(&master->master_mutex); |
|
2422 ec_soe_request_clear(&request.req); |
|
2423 return -EINTR; |
|
2424 } |
|
2425 // request already processing: interrupt not possible. |
|
2426 ec_mutex_unlock(&master->master_mutex); |
|
2427 } |
|
2428 |
|
2429 // wait until master FSM has finished processing |
|
2430 wait_event(request.slave->soe_queue, |
|
2431 request.req.state != EC_INT_REQUEST_BUSY); |
|
2432 |
2427 |
2433 if (error_code) { |
2428 if (error_code) { |
2434 *error_code = request.req.error_code; |
2429 *error_code = request->req.error_code; |
2435 } |
2430 } |
2436 |
2431 |
2437 EC_SLAVE_DBG(request.slave, 1, "Read %zd bytes via SoE.\n", |
2432 EC_SLAVE_DBG(request->slave, 1, "SoE request %p read %zd bytes via SoE.\n", |
2438 request.req.data_size); |
2433 request,request->req.data_size); |
2439 |
2434 |
2440 if (request.req.state != EC_INT_REQUEST_SUCCESS) { |
2435 if (request->req.state != EC_INT_REQUEST_SUCCESS) { |
2441 if (result_size) { |
2436 if (result_size) { |
2442 *result_size = 0; |
2437 *result_size = 0; |
2443 } |
2438 } |
2444 ec_soe_request_clear(&request.req); |
2439 kref_put(&request->refcount,ec_master_soe_request_release); |
2445 return -EIO; |
2440 return -EIO; |
2446 } else { |
2441 } else { |
2447 if (request.req.data_size > target_size) { |
2442 if (request->req.data_size > target_size) { |
2448 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2443 EC_MASTER_ERR(master, "Buffer too small.\n"); |
2449 ec_soe_request_clear(&request.req); |
2444 kref_put(&request->refcount,ec_master_soe_request_release); |
2450 return -EOVERFLOW; |
2445 return -EOVERFLOW; |
2451 } |
2446 } |
2452 if (result_size) { |
2447 if (result_size) { |
2453 *result_size = request.req.data_size; |
2448 *result_size = request->req.data_size; |
2454 } |
2449 } |
2455 memcpy(target, request.req.data, request.req.data_size); |
2450 memcpy(target, request->req.data, request->req.data_size); |
|
2451 kref_put(&request->refcount,ec_master_soe_request_release); |
2456 return 0; |
2452 return 0; |
2457 } |
2453 } |
2458 } |
2454 } |
2459 |
2455 |
2460 /*****************************************************************************/ |
2456 /*****************************************************************************/ |