diff options
Diffstat (limited to 'drivers/fpga')
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 52 | ||||
-rw-r--r-- | drivers/fpga/fpga-region.c | 14 |
2 files changed, 48 insertions, 18 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index a8dd54945470..d27e8d2a149c 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c | |||
@@ -410,28 +410,19 @@ ATTRIBUTE_GROUPS(fpga_mgr); | |||
410 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) | 410 | static struct fpga_manager *__fpga_mgr_get(struct device *dev) |
411 | { | 411 | { |
412 | struct fpga_manager *mgr; | 412 | struct fpga_manager *mgr; |
413 | int ret = -ENODEV; | ||
414 | 413 | ||
415 | mgr = to_fpga_manager(dev); | 414 | mgr = to_fpga_manager(dev); |
416 | if (!mgr) | 415 | if (!mgr) |
417 | goto err_dev; | 416 | goto err_dev; |
418 | 417 | ||
419 | /* Get exclusive use of fpga manager */ | ||
420 | if (!mutex_trylock(&mgr->ref_mutex)) { | ||
421 | ret = -EBUSY; | ||
422 | goto err_dev; | ||
423 | } | ||
424 | |||
425 | if (!try_module_get(dev->parent->driver->owner)) | 418 | if (!try_module_get(dev->parent->driver->owner)) |
426 | goto err_ll_mod; | 419 | goto err_dev; |
427 | 420 | ||
428 | return mgr; | 421 | return mgr; |
429 | 422 | ||
430 | err_ll_mod: | ||
431 | mutex_unlock(&mgr->ref_mutex); | ||
432 | err_dev: | 423 | err_dev: |
433 | put_device(dev); | 424 | put_device(dev); |
434 | return ERR_PTR(ret); | 425 | return ERR_PTR(-ENODEV); |
435 | } | 426 | } |
436 | 427 | ||
437 | static int fpga_mgr_dev_match(struct device *dev, const void *data) | 428 | static int fpga_mgr_dev_match(struct device *dev, const void *data) |
@@ -440,10 +431,10 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) | |||
440 | } | 431 | } |
441 | 432 | ||
442 | /** | 433 | /** |
443 | * fpga_mgr_get - get an exclusive reference to a fpga mgr | 434 | * fpga_mgr_get - get a reference to a fpga mgr |
444 | * @dev: parent device that fpga mgr was registered with | 435 | * @dev: parent device that fpga mgr was registered with |
445 | * | 436 | * |
446 | * Given a device, get an exclusive reference to a fpga mgr. | 437 | * Given a device, get a reference to a fpga mgr. |
447 | * | 438 | * |
448 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 439 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
449 | */ | 440 | */ |
@@ -464,10 +455,10 @@ static int fpga_mgr_of_node_match(struct device *dev, const void *data) | |||
464 | } | 455 | } |
465 | 456 | ||
466 | /** | 457 | /** |
467 | * of_fpga_mgr_get - get an exclusive reference to a fpga mgr | 458 | * of_fpga_mgr_get - get a reference to a fpga mgr |
468 | * @node: device node | 459 | * @node: device node |
469 | * | 460 | * |
470 | * Given a device node, get an exclusive reference to a fpga mgr. | 461 | * Given a device node, get a reference to a fpga mgr. |
471 | * | 462 | * |
472 | * Return: fpga manager struct or IS_ERR() condition containing error code. | 463 | * Return: fpga manager struct or IS_ERR() condition containing error code. |
473 | */ | 464 | */ |
@@ -491,12 +482,41 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get); | |||
491 | void fpga_mgr_put(struct fpga_manager *mgr) | 482 | void fpga_mgr_put(struct fpga_manager *mgr) |
492 | { | 483 | { |
493 | module_put(mgr->dev.parent->driver->owner); | 484 | module_put(mgr->dev.parent->driver->owner); |
494 | mutex_unlock(&mgr->ref_mutex); | ||
495 | put_device(&mgr->dev); | 485 | put_device(&mgr->dev); |
496 | } | 486 | } |
497 | EXPORT_SYMBOL_GPL(fpga_mgr_put); | 487 | EXPORT_SYMBOL_GPL(fpga_mgr_put); |
498 | 488 | ||
499 | /** | 489 | /** |
490 | * fpga_mgr_lock - Lock FPGA manager for exclusive use | ||
491 | * @mgr: fpga manager | ||
492 | * | ||
493 | * Given a pointer to FPGA Manager (from fpga_mgr_get() or | ||
494 | * of_fpga_mgr_put()) attempt to get the mutex. | ||
495 | * | ||
496 | * Return: 0 for success or -EBUSY | ||
497 | */ | ||
498 | int fpga_mgr_lock(struct fpga_manager *mgr) | ||
499 | { | ||
500 | if (!mutex_trylock(&mgr->ref_mutex)) { | ||
501 | dev_err(&mgr->dev, "FPGA manager is in use.\n"); | ||
502 | return -EBUSY; | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | EXPORT_SYMBOL_GPL(fpga_mgr_lock); | ||
508 | |||
509 | /** | ||
510 | * fpga_mgr_unlock - Unlock FPGA manager | ||
511 | * @mgr: fpga manager | ||
512 | */ | ||
513 | void fpga_mgr_unlock(struct fpga_manager *mgr) | ||
514 | { | ||
515 | mutex_unlock(&mgr->ref_mutex); | ||
516 | } | ||
517 | EXPORT_SYMBOL_GPL(fpga_mgr_unlock); | ||
518 | |||
519 | /** | ||
500 | * fpga_mgr_register - register a low level fpga manager driver | 520 | * fpga_mgr_register - register a low level fpga manager driver |
501 | * @dev: fpga manager device from pdev | 521 | * @dev: fpga manager device from pdev |
502 | * @name: fpga manager name | 522 | * @name: fpga manager name |
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 120c496eb7bd..1e1640a29306 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c | |||
@@ -125,7 +125,7 @@ static void fpga_region_put(struct fpga_region *region) | |||
125 | } | 125 | } |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * fpga_region_get_manager - get exclusive reference for FPGA manager | 128 | * fpga_region_get_manager - get reference for FPGA manager |
129 | * @region: FPGA region | 129 | * @region: FPGA region |
130 | * | 130 | * |
131 | * Get FPGA Manager from "fpga-mgr" property or from ancestor region. | 131 | * Get FPGA Manager from "fpga-mgr" property or from ancestor region. |
@@ -233,6 +233,7 @@ static int fpga_region_get_bridges(struct fpga_region *region, | |||
233 | static int fpga_region_program_fpga(struct fpga_region *region, | 233 | static int fpga_region_program_fpga(struct fpga_region *region, |
234 | struct device_node *overlay) | 234 | struct device_node *overlay) |
235 | { | 235 | { |
236 | struct device *dev = ®ion->dev; | ||
236 | struct fpga_manager *mgr; | 237 | struct fpga_manager *mgr; |
237 | int ret; | 238 | int ret; |
238 | 239 | ||
@@ -249,10 +250,16 @@ static int fpga_region_program_fpga(struct fpga_region *region, | |||
249 | goto err_put_region; | 250 | goto err_put_region; |
250 | } | 251 | } |
251 | 252 | ||
253 | ret = fpga_mgr_lock(mgr); | ||
254 | if (ret) { | ||
255 | dev_err(dev, "FPGA manager is busy\n"); | ||
256 | goto err_put_mgr; | ||
257 | } | ||
258 | |||
252 | ret = fpga_region_get_bridges(region, overlay); | 259 | ret = fpga_region_get_bridges(region, overlay); |
253 | if (ret) { | 260 | if (ret) { |
254 | pr_err("failed to get fpga region bridges\n"); | 261 | pr_err("failed to get fpga region bridges\n"); |
255 | goto err_put_mgr; | 262 | goto err_unlock_mgr; |
256 | } | 263 | } |
257 | 264 | ||
258 | ret = fpga_bridges_disable(®ion->bridge_list); | 265 | ret = fpga_bridges_disable(®ion->bridge_list); |
@@ -273,6 +280,7 @@ static int fpga_region_program_fpga(struct fpga_region *region, | |||
273 | goto err_put_br; | 280 | goto err_put_br; |
274 | } | 281 | } |
275 | 282 | ||
283 | fpga_mgr_unlock(mgr); | ||
276 | fpga_mgr_put(mgr); | 284 | fpga_mgr_put(mgr); |
277 | fpga_region_put(region); | 285 | fpga_region_put(region); |
278 | 286 | ||
@@ -280,6 +288,8 @@ static int fpga_region_program_fpga(struct fpga_region *region, | |||
280 | 288 | ||
281 | err_put_br: | 289 | err_put_br: |
282 | fpga_bridges_put(®ion->bridge_list); | 290 | fpga_bridges_put(®ion->bridge_list); |
291 | err_unlock_mgr: | ||
292 | fpga_mgr_unlock(mgr); | ||
283 | err_put_mgr: | 293 | err_put_mgr: |
284 | fpga_mgr_put(mgr); | 294 | fpga_mgr_put(mgr); |
285 | err_put_region: | 295 | err_put_region: |