From: Rafael J. Wysocki <rjw@xxxxxxx> Use a hibernation and suspend notifier to disable the firmware requesting mechanism before a hibernation/suspend and enable it after the operation. Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx> drivers/base/firmware_class.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) Index: linux-2.6.22-rc3/drivers/base/firmware_class.c =================================================================== --- linux-2.6.22-rc3.orig/drivers/base/firmware_class.c 2007-05-27 19:43:03.000000000 +0200 +++ linux-2.6.22-rc3/drivers/base/firmware_class.c 2007-05-27 19:44:06.000000000 +0200 @@ -17,6 +17,8 @@ #include <linux/bitops.h> #include <linux/mutex.h> #include <linux/kthread.h> +#include <linux/notifier.h> +#include <linux/suspend.h> #include <linux/firmware.h> #include "base.h" @@ -35,6 +37,9 @@ enum { static int loading_timeout = 60; /* In seconds */ +/* If set, _request_firmware() will exit immediately returning -EBUSY */ +static int requesting_firmware_disabled; + /* fw_lock could be moved to 'struct firmware_priv' but since it is just * guarding for corner cases a global lock should be OK */ static DEFINE_MUTEX(fw_lock); @@ -397,6 +402,9 @@ _request_firmware(const struct firmware struct firmware *firmware; int retval; + if (requesting_firmware_disabled) + return -EBUSY; + if (!firmware_p) return -EINVAL; @@ -568,6 +576,26 @@ request_firmware_nowait( return 0; } +static int firmware_class_pm_callback(struct notifier_block *nfb, + unsigned long action, + void *ignored) +{ + switch (action) { + case PM_PRE_FREEZE: + requesting_firmware_disabled = 1; + return NOTIFY_OK; + case PM_POST_THAW: + requesting_firmware_disabled = 0; + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + +static struct notifier_block firmware_class_pm_nb = { + .notifier_call = firmware_class_pm_callback, +}; + static int __init firmware_class_init(void) { @@ -582,6 +610,13 @@ firmware_class_init(void) printk(KERN_ERR "%s: class_create_file failed\n", __FUNCTION__); class_unregister(&firmware_class); + return error; + } + error = register_pm_notifier(&firmware_class_pm_nb); + if (error) { + printk(KERN_ERR "%s: register_pm_notifier failed\n", + __FUNCTION__); + class_unregister(&firmware_class); } return error; @@ -589,6 +624,7 @@ firmware_class_init(void) static void __exit firmware_class_exit(void) { + unregister_pm_notifier(&firmware_class_pm_nb); class_unregister(&firmware_class); } _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm