diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-03-28 17:29:55 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-03-28 17:29:55 -0400 |
commit | 811fa4004485dec8977176bf605a5b0508ee206c (patch) | |
tree | afa0924a75f217a27f7438e34758747413ba635a /drivers/base | |
parent | fe2e39d8782d885755139304d8dba0b3e5bfa878 (diff) |
firmware_class: Split _request_firmware() into three functions, v2
Split _request_firmware() into three functions,
_request_firmware_prepare() doing preparatory work that need not be
done under umhelper_sem, _request_firmware_cleanup() doing the
post-error cleanup and _request_firmware() carrying out the remaining
operations.
This change is requisite for moving the acquisition of umhelper_sem
from _request_firmware() to the callers, which is going to be done
subsequently.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/firmware_class.c | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index deee871e509c..60290671f04a 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -435,7 +435,7 @@ static void firmware_class_timeout(u_long data) | |||
435 | } | 435 | } |
436 | 436 | ||
437 | static struct firmware_priv * | 437 | static struct firmware_priv * |
438 | fw_create_instance(struct firmware *firmware, const char *fw_name, | 438 | fw_create_instance(const struct firmware *firmware, const char *fw_name, |
439 | struct device *device, bool uevent, bool nowait) | 439 | struct device *device, bool uevent, bool nowait) |
440 | { | 440 | { |
441 | struct firmware_priv *fw_priv; | 441 | struct firmware_priv *fw_priv; |
@@ -449,7 +449,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, | |||
449 | goto err_out; | 449 | goto err_out; |
450 | } | 450 | } |
451 | 451 | ||
452 | fw_priv->fw = firmware; | 452 | fw_priv->fw = (struct firmware *)firmware; |
453 | fw_priv->nowait = nowait; | 453 | fw_priv->nowait = nowait; |
454 | strcpy(fw_priv->fw_id, fw_name); | 454 | strcpy(fw_priv->fw_id, fw_name); |
455 | init_completion(&fw_priv->completion); | 455 | init_completion(&fw_priv->completion); |
@@ -510,13 +510,10 @@ static void fw_destroy_instance(struct firmware_priv *fw_priv) | |||
510 | device_unregister(f_dev); | 510 | device_unregister(f_dev); |
511 | } | 511 | } |
512 | 512 | ||
513 | static int _request_firmware(const struct firmware **firmware_p, | 513 | static int _request_firmware_prepare(const struct firmware **firmware_p, |
514 | const char *name, struct device *device, | 514 | const char *name, struct device *device) |
515 | bool uevent, bool nowait) | ||
516 | { | 515 | { |
517 | struct firmware_priv *fw_priv; | ||
518 | struct firmware *firmware; | 516 | struct firmware *firmware; |
519 | int retval = 0; | ||
520 | 517 | ||
521 | if (!firmware_p) | 518 | if (!firmware_p) |
522 | return -EINVAL; | 519 | return -EINVAL; |
@@ -533,10 +530,26 @@ static int _request_firmware(const struct firmware **firmware_p, | |||
533 | return 0; | 530 | return 0; |
534 | } | 531 | } |
535 | 532 | ||
533 | return 1; | ||
534 | } | ||
535 | |||
536 | static void _request_firmware_cleanup(const struct firmware **firmware_p) | ||
537 | { | ||
538 | release_firmware(*firmware_p); | ||
539 | *firmware_p = NULL; | ||
540 | } | ||
541 | |||
542 | static int _request_firmware(const struct firmware *firmware, | ||
543 | const char *name, struct device *device, | ||
544 | bool uevent, bool nowait) | ||
545 | { | ||
546 | struct firmware_priv *fw_priv; | ||
547 | int retval; | ||
548 | |||
536 | retval = usermodehelper_read_trylock(); | 549 | retval = usermodehelper_read_trylock(); |
537 | if (WARN_ON(retval)) { | 550 | if (WARN_ON(retval)) { |
538 | dev_err(device, "firmware: %s will not be loaded\n", name); | 551 | dev_err(device, "firmware: %s will not be loaded\n", name); |
539 | goto out_nolock; | 552 | return retval; |
540 | } | 553 | } |
541 | 554 | ||
542 | if (uevent) | 555 | if (uevent) |
@@ -572,13 +585,6 @@ static int _request_firmware(const struct firmware **firmware_p, | |||
572 | 585 | ||
573 | out: | 586 | out: |
574 | usermodehelper_read_unlock(); | 587 | usermodehelper_read_unlock(); |
575 | |||
576 | out_nolock: | ||
577 | if (retval) { | ||
578 | release_firmware(firmware); | ||
579 | *firmware_p = NULL; | ||
580 | } | ||
581 | |||
582 | return retval; | 588 | return retval; |
583 | } | 589 | } |
584 | 590 | ||
@@ -601,7 +607,17 @@ int | |||
601 | request_firmware(const struct firmware **firmware_p, const char *name, | 607 | request_firmware(const struct firmware **firmware_p, const char *name, |
602 | struct device *device) | 608 | struct device *device) |
603 | { | 609 | { |
604 | return _request_firmware(firmware_p, name, device, true, false); | 610 | int ret; |
611 | |||
612 | ret = _request_firmware_prepare(firmware_p, name, device); | ||
613 | if (ret <= 0) | ||
614 | return ret; | ||
615 | |||
616 | ret = _request_firmware(*firmware_p, name, device, true, false); | ||
617 | if (ret) | ||
618 | _request_firmware_cleanup(firmware_p); | ||
619 | |||
620 | return ret; | ||
605 | } | 621 | } |
606 | 622 | ||
607 | /** | 623 | /** |
@@ -639,8 +655,16 @@ static int request_firmware_work_func(void *arg) | |||
639 | return 0; | 655 | return 0; |
640 | } | 656 | } |
641 | 657 | ||
642 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, | 658 | ret = _request_firmware_prepare(&fw, fw_work->name, fw_work->device); |
659 | if (ret <= 0) | ||
660 | goto out; | ||
661 | |||
662 | ret = _request_firmware(fw, fw_work->name, fw_work->device, | ||
643 | fw_work->uevent, true); | 663 | fw_work->uevent, true); |
664 | if (ret) | ||
665 | _request_firmware_cleanup(&fw); | ||
666 | |||
667 | out: | ||
644 | fw_work->cont(fw, fw_work->context); | 668 | fw_work->cont(fw, fw_work->context); |
645 | 669 | ||
646 | module_put(fw_work->module); | 670 | module_put(fw_work->module); |