firmware: share fw fallback killing on reboot/suspend
authorLuis R. Rodriguez <mcgrof@kernel.org>
Tue, 2 May 2017 08:31:03 +0000 (01:31 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 3 Jun 2017 10:15:49 +0000 (19:15 +0900)
We kill pending fallback requests on suspend and reboot,
the only difference is that on suspend we only kill custom
fallback requests. Provide a wrapper that lets us customize
the request with a flag.

This also lets us simplify the #ifdef'ery over the calls.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/firmware_class.c

index 900b139668e86f03d945af7b7a910a4f42a9c434..58b661df6d341845b8aacb27516fa829b02a1533 100644 (file)
@@ -562,32 +562,29 @@ static void fw_load_abort(struct firmware_priv *fw_priv)
 
 static LIST_HEAD(pending_fw_head);
 
-#ifdef CONFIG_PM_SLEEP
-/* kill pending requests without uevent to avoid blocking suspend */
-static void kill_requests_without_uevent(void)
+static void kill_pending_fw_fallback_reqs(bool only_kill_custom)
 {
        struct firmware_buf *buf;
        struct firmware_buf *next;
 
        mutex_lock(&fw_lock);
        list_for_each_entry_safe(buf, next, &pending_fw_head, pending_list) {
-               if (!buf->need_uevent)
+               if (!buf->need_uevent || !only_kill_custom)
                         __fw_load_abort(buf);
        }
        mutex_unlock(&fw_lock);
 }
-#endif
 
 /* reboot notifier for avoid deadlock with usermode_lock */
 static int fw_shutdown_notify(struct notifier_block *unused1,
                              unsigned long unused2, void *unused3)
 {
-       mutex_lock(&fw_lock);
-       while (!list_empty(&pending_fw_head))
-               __fw_load_abort(list_first_entry(&pending_fw_head,
-                                              struct firmware_buf,
-                                              pending_list));
-       mutex_unlock(&fw_lock);
+       /*
+        * Kill all pending fallback requests to avoid both stalling shutdown,
+        * and avoid a deadlock with the usermode_lock.
+        */
+       kill_pending_fw_fallback_reqs(false);
+
        return NOTIFY_DONE;
 }
 
@@ -1073,9 +1070,7 @@ fw_load_from_user_helper(struct firmware *firmware, const char *name,
        return -ENOENT;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static inline void kill_requests_without_uevent(void) { }
-#endif
+static inline void kill_pending_fw_fallback_reqs(bool only_kill_custom) { }
 
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
@@ -1724,7 +1719,11 @@ static int fw_pm_notify(struct notifier_block *notify_block,
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
        case PM_RESTORE_PREPARE:
-               kill_requests_without_uevent();
+               /*
+                * kill pending fallback requests with a custom fallback
+                * to avoid stalling suspend.
+                */
+               kill_pending_fw_fallback_reqs(true);
                device_cache_fw_images();
                break;