288 { |
288 { |
289 ec_master_t *master; |
289 ec_master_t *master; |
290 |
290 |
291 if (!(master = ec_find_master(master_index))) return NULL; |
291 if (!(master = ec_find_master(master_index))) return NULL; |
292 |
292 |
|
293 if (down_interruptible(&master->device_sem)) { |
|
294 EC_ERR("Interrupted while waiting for device!\n"); |
|
295 goto out_return; |
|
296 } |
|
297 |
293 if (master->device) { |
298 if (master->device) { |
294 EC_ERR("Master %i already has a device!\n", master_index); |
299 EC_ERR("Master %i already has a device!\n", master_index); |
295 goto out_return; |
300 goto out_up; |
296 } |
301 } |
297 |
302 |
298 if (!(master->device = |
303 if (!(master->device = |
299 (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { |
304 (ec_device_t *) kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { |
300 EC_ERR("Failed to allocate device!\n"); |
305 EC_ERR("Failed to allocate device!\n"); |
301 goto out_return; |
306 goto out_up; |
302 } |
307 } |
303 |
308 |
304 if (ec_device_init(master->device, master, net_dev, isr, module)) { |
309 if (ec_device_init(master->device, master, net_dev, isr, module)) { |
305 EC_ERR("Failed to init device!\n"); |
310 EC_ERR("Failed to init device!\n"); |
306 goto out_free; |
311 goto out_free; |
307 } |
312 } |
308 |
313 |
|
314 up(&master->device_sem); |
309 return master->device; |
315 return master->device; |
310 |
316 |
311 out_free: |
317 out_free: |
312 kfree(master->device); |
318 kfree(master->device); |
313 master->device = NULL; |
319 master->device = NULL; |
|
320 out_up: |
|
321 up(&master->device_sem); |
314 out_return: |
322 out_return: |
315 return NULL; |
323 return NULL; |
316 } |
324 } |
317 |
325 |
318 /*****************************************************************************/ |
326 /*****************************************************************************/ |
332 { |
340 { |
333 ec_master_t *master; |
341 ec_master_t *master; |
334 |
342 |
335 if (!(master = ec_find_master(master_index))) return; |
343 if (!(master = ec_find_master(master_index))) return; |
336 |
344 |
|
345 down(&master->device_sem); |
|
346 |
337 if (!master->device || master->device != device) { |
347 if (!master->device || master->device != device) { |
|
348 up(&master->device_sem); |
338 EC_WARN("Unable to unregister device!\n"); |
349 EC_WARN("Unable to unregister device!\n"); |
339 return; |
350 return; |
340 } |
351 } |
341 |
352 |
342 ec_device_clear(master->device); |
353 ec_device_clear(master->device); |
343 kfree(master->device); |
354 kfree(master->device); |
344 master->device = NULL; |
355 master->device = NULL; |
|
356 |
|
357 up(&master->device_sem); |
345 } |
358 } |
346 |
359 |
347 /*****************************************************************************/ |
360 /*****************************************************************************/ |
348 |
361 |
349 /** |
362 /** |
413 atomic_inc(&master->available); |
426 atomic_inc(&master->available); |
414 EC_ERR("Master %i is already in use!\n", master_index); |
427 EC_ERR("Master %i is already in use!\n", master_index); |
415 goto out_return; |
428 goto out_return; |
416 } |
429 } |
417 |
430 |
|
431 if (down_interruptible(&master->device_sem)) { |
|
432 EC_ERR("Interrupted while waiting for device!\n"); |
|
433 goto out_release; |
|
434 } |
|
435 |
418 if (!master->device) { |
436 if (!master->device) { |
|
437 up(&master->device_sem); |
419 EC_ERR("Master %i has no assigned device!\n", master_index); |
438 EC_ERR("Master %i has no assigned device!\n", master_index); |
420 goto out_release; |
439 goto out_release; |
421 } |
440 } |
422 |
441 |
423 if (!try_module_get(master->device->module)) { // possible race? |
442 if (!try_module_get(master->device->module)) { |
424 EC_ERR("Failed to reserve device module!\n"); |
443 up(&master->device_sem); |
|
444 EC_ERR("Device module is unloading!\n"); |
425 goto out_release; |
445 goto out_release; |
426 } |
446 } |
|
447 |
|
448 up(&master->device_sem); |
427 |
449 |
428 if (!master->device->link_state) { |
450 if (!master->device->link_state) { |
429 EC_ERR("Link is DOWN.\n"); |
451 EC_ERR("Link is DOWN.\n"); |
430 goto out_module_put; |
452 goto out_module_put; |
431 } |
453 } |