diff options
Diffstat (limited to 'drivers/base/firmware_loader/fallback.c')
-rw-r--r-- | drivers/base/firmware_loader/fallback.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 358354148dec..b676a99c469c 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c | |||
@@ -125,7 +125,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr, | |||
125 | } | 125 | } |
126 | 126 | ||
127 | /** | 127 | /** |
128 | * firmware_timeout_store - set number of seconds to wait for firmware | 128 | * firmware_timeout_store() - set number of seconds to wait for firmware |
129 | * @class: device class pointer | 129 | * @class: device class pointer |
130 | * @attr: device attribute pointer | 130 | * @attr: device attribute pointer |
131 | * @buf: buffer to scan for timeout value | 131 | * @buf: buffer to scan for timeout value |
@@ -239,7 +239,7 @@ static int map_fw_priv_pages(struct fw_priv *fw_priv) | |||
239 | } | 239 | } |
240 | 240 | ||
241 | /** | 241 | /** |
242 | * firmware_loading_store - set value in the 'loading' control file | 242 | * firmware_loading_store() - set value in the 'loading' control file |
243 | * @dev: device pointer | 243 | * @dev: device pointer |
244 | * @attr: device attribute pointer | 244 | * @attr: device attribute pointer |
245 | * @buf: buffer to scan for loading control value | 245 | * @buf: buffer to scan for loading control value |
@@ -431,7 +431,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | /** | 433 | /** |
434 | * firmware_data_write - write method for firmware | 434 | * firmware_data_write() - write method for firmware |
435 | * @filp: open sysfs file | 435 | * @filp: open sysfs file |
436 | * @kobj: kobject for the device | 436 | * @kobj: kobject for the device |
437 | * @bin_attr: bin_attr structure | 437 | * @bin_attr: bin_attr structure |
@@ -512,7 +512,7 @@ static const struct attribute_group *fw_dev_attr_groups[] = { | |||
512 | 512 | ||
513 | static struct fw_sysfs * | 513 | static struct fw_sysfs * |
514 | fw_create_instance(struct firmware *firmware, const char *fw_name, | 514 | fw_create_instance(struct firmware *firmware, const char *fw_name, |
515 | struct device *device, unsigned int opt_flags) | 515 | struct device *device, enum fw_opt opt_flags) |
516 | { | 516 | { |
517 | struct fw_sysfs *fw_sysfs; | 517 | struct fw_sysfs *fw_sysfs; |
518 | struct device *f_dev; | 518 | struct device *f_dev; |
@@ -537,7 +537,7 @@ exit: | |||
537 | } | 537 | } |
538 | 538 | ||
539 | /** | 539 | /** |
540 | * fw_load_sysfs_fallback - load a firmware via the sysfs fallback mechanism | 540 | * fw_load_sysfs_fallback() - load a firmware via the sysfs fallback mechanism |
541 | * @fw_sysfs: firmware sysfs information for the firmware to load | 541 | * @fw_sysfs: firmware sysfs information for the firmware to load |
542 | * @opt_flags: flags of options, FW_OPT_* | 542 | * @opt_flags: flags of options, FW_OPT_* |
543 | * @timeout: timeout to wait for the load | 543 | * @timeout: timeout to wait for the load |
@@ -545,7 +545,7 @@ exit: | |||
545 | * In charge of constructing a sysfs fallback interface for firmware loading. | 545 | * In charge of constructing a sysfs fallback interface for firmware loading. |
546 | **/ | 546 | **/ |
547 | static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, | 547 | static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, |
548 | unsigned int opt_flags, long timeout) | 548 | enum fw_opt opt_flags, long timeout) |
549 | { | 549 | { |
550 | int retval = 0; | 550 | int retval = 0; |
551 | struct device *f_dev = &fw_sysfs->dev; | 551 | struct device *f_dev = &fw_sysfs->dev; |
@@ -599,7 +599,7 @@ err_put_dev: | |||
599 | 599 | ||
600 | static int fw_load_from_user_helper(struct firmware *firmware, | 600 | static int fw_load_from_user_helper(struct firmware *firmware, |
601 | const char *name, struct device *device, | 601 | const char *name, struct device *device, |
602 | unsigned int opt_flags) | 602 | enum fw_opt opt_flags) |
603 | { | 603 | { |
604 | struct fw_sysfs *fw_sysfs; | 604 | struct fw_sysfs *fw_sysfs; |
605 | long timeout; | 605 | long timeout; |
@@ -640,7 +640,7 @@ out_unlock: | |||
640 | return ret; | 640 | return ret; |
641 | } | 641 | } |
642 | 642 | ||
643 | static bool fw_force_sysfs_fallback(unsigned int opt_flags) | 643 | static bool fw_force_sysfs_fallback(enum fw_opt opt_flags) |
644 | { | 644 | { |
645 | if (fw_fallback_config.force_sysfs_fallback) | 645 | if (fw_fallback_config.force_sysfs_fallback) |
646 | return true; | 646 | return true; |
@@ -649,7 +649,7 @@ static bool fw_force_sysfs_fallback(unsigned int opt_flags) | |||
649 | return true; | 649 | return true; |
650 | } | 650 | } |
651 | 651 | ||
652 | static bool fw_run_sysfs_fallback(unsigned int opt_flags) | 652 | static bool fw_run_sysfs_fallback(enum fw_opt opt_flags) |
653 | { | 653 | { |
654 | if (fw_fallback_config.ignore_sysfs_fallback) { | 654 | if (fw_fallback_config.ignore_sysfs_fallback) { |
655 | pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n"); | 655 | pr_info_once("Ignoring firmware sysfs fallback due to sysctl knob\n"); |
@@ -662,14 +662,39 @@ static bool fw_run_sysfs_fallback(unsigned int opt_flags) | |||
662 | return fw_force_sysfs_fallback(opt_flags); | 662 | return fw_force_sysfs_fallback(opt_flags); |
663 | } | 663 | } |
664 | 664 | ||
665 | int fw_sysfs_fallback(struct firmware *fw, const char *name, | 665 | /** |
666 | struct device *device, | 666 | * firmware_fallback_sysfs() - use the fallback mechanism to find firmware |
667 | unsigned int opt_flags, | 667 | * @fw: pointer to firmware image |
668 | int ret) | 668 | * @name: name of firmware file to look for |
669 | * @device: device for which firmware is being loaded | ||
670 | * @opt_flags: options to control firmware loading behaviour | ||
671 | * @ret: return value from direct lookup which triggered the fallback mechanism | ||
672 | * | ||
673 | * This function is called if direct lookup for the firmware failed, it enables | ||
674 | * a fallback mechanism through userspace by exposing a sysfs loading | ||
675 | * interface. Userspace is in charge of loading the firmware through the syfs | ||
676 | * loading interface. This syfs fallback mechanism may be disabled completely | ||
677 | * on a system by setting the proc sysctl value ignore_sysfs_fallback to true. | ||
678 | * If this false we check if the internal API caller set the @FW_OPT_NOFALLBACK | ||
679 | * flag, if so it would also disable the fallback mechanism. A system may want | ||
680 | * to enfoce the sysfs fallback mechanism at all times, it can do this by | ||
681 | * setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. | ||
682 | * Enabling force_sysfs_fallback is functionally equivalent to build a kernel | ||
683 | * with CONFIG_FW_LOADER_USER_HELPER_FALLBACK. | ||
684 | **/ | ||
685 | int firmware_fallback_sysfs(struct firmware *fw, const char *name, | ||
686 | struct device *device, | ||
687 | enum fw_opt opt_flags, | ||
688 | int ret) | ||
669 | { | 689 | { |
670 | if (!fw_run_sysfs_fallback(opt_flags)) | 690 | if (!fw_run_sysfs_fallback(opt_flags)) |
671 | return ret; | 691 | return ret; |
672 | 692 | ||
673 | dev_warn(device, "Falling back to user helper\n"); | 693 | if (!(opt_flags & FW_OPT_NO_WARN)) |
694 | dev_warn(device, "Falling back to syfs fallback for: %s\n", | ||
695 | name); | ||
696 | else | ||
697 | dev_dbg(device, "Falling back to sysfs fallback for: %s\n", | ||
698 | name); | ||
674 | return fw_load_from_user_helper(fw, name, device, opt_flags); | 699 | return fw_load_from_user_helper(fw, name, device, opt_flags); |
675 | } | 700 | } |