2727#include <linux/pm.h>
2828#include <linux/suspend.h>
2929#include <linux/syscore_ops.h>
30+ #include <linux/reboot.h>
3031
3132#include <generated/utsrelease.h>
3233
@@ -130,6 +131,7 @@ struct firmware_buf {
130131 struct page * * pages ;
131132 int nr_pages ;
132133 int page_array_size ;
134+ struct list_head pending_list ;
133135#endif
134136 char fw_id [];
135137};
@@ -171,6 +173,9 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
171173 strcpy (buf -> fw_id , fw_name );
172174 buf -> fwc = fwc ;
173175 init_completion (& buf -> completion );
176+ #ifdef CONFIG_FW_LOADER_USER_HELPER
177+ INIT_LIST_HEAD (& buf -> pending_list );
178+ #endif
174179
175180 pr_debug ("%s: fw-%s buf=%p\n" , __func__ , fw_name , buf );
176181
@@ -446,17 +451,35 @@ static struct firmware_priv *to_firmware_priv(struct device *dev)
446451 return container_of (dev , struct firmware_priv , dev );
447452}
448453
449- static void fw_load_abort (struct firmware_priv * fw_priv )
454+ static void fw_load_abort (struct firmware_buf * buf )
450455{
451- struct firmware_buf * buf = fw_priv -> buf ;
452-
456+ list_del_init (& buf -> pending_list );
453457 set_bit (FW_STATUS_ABORT , & buf -> status );
454458 complete_all (& buf -> completion );
455459}
456460
457461#define is_fw_load_aborted (buf ) \
458462 test_bit(FW_STATUS_ABORT, &(buf)->status)
459463
464+ static LIST_HEAD (pending_fw_head );
465+
466+ /* reboot notifier for avoid deadlock with usermode_lock */
467+ static int fw_shutdown_notify (struct notifier_block * unused1 ,
468+ unsigned long unused2 , void * unused3 )
469+ {
470+ mutex_lock (& fw_lock );
471+ while (!list_empty (& pending_fw_head ))
472+ fw_load_abort (list_first_entry (& pending_fw_head ,
473+ struct firmware_buf ,
474+ pending_list ));
475+ mutex_unlock (& fw_lock );
476+ return NOTIFY_DONE ;
477+ }
478+
479+ static struct notifier_block fw_shutdown_nb = {
480+ .notifier_call = fw_shutdown_notify ,
481+ };
482+
460483static ssize_t firmware_timeout_show (struct class * class ,
461484 struct class_attribute * attr ,
462485 char * buf )
@@ -604,6 +627,7 @@ static ssize_t firmware_loading_store(struct device *dev,
604627 * is completed.
605628 * */
606629 fw_map_pages_buf (fw_buf );
630+ list_del_init (& fw_buf -> pending_list );
607631 complete_all (& fw_buf -> completion );
608632 break ;
609633 }
@@ -612,7 +636,7 @@ static ssize_t firmware_loading_store(struct device *dev,
612636 dev_err (dev , "%s: unexpected value (%d)\n" , __func__ , loading );
613637 /* fallthrough */
614638 case -1 :
615- fw_load_abort (fw_priv );
639+ fw_load_abort (fw_buf );
616640 break ;
617641 }
618642out :
@@ -680,7 +704,7 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
680704 new_pages = kmalloc (new_array_size * sizeof (void * ),
681705 GFP_KERNEL );
682706 if (!new_pages ) {
683- fw_load_abort (fw_priv );
707+ fw_load_abort (buf );
684708 return - ENOMEM ;
685709 }
686710 memcpy (new_pages , buf -> pages ,
@@ -697,7 +721,7 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
697721 alloc_page (GFP_KERNEL | __GFP_HIGHMEM );
698722
699723 if (!buf -> pages [buf -> nr_pages ]) {
700- fw_load_abort (fw_priv );
724+ fw_load_abort (buf );
701725 return - ENOMEM ;
702726 }
703727 buf -> nr_pages ++ ;
@@ -781,7 +805,7 @@ static void firmware_class_timeout_work(struct work_struct *work)
781805 mutex_unlock (& fw_lock );
782806 return ;
783807 }
784- fw_load_abort (fw_priv );
808+ fw_load_abort (fw_priv -> buf );
785809 mutex_unlock (& fw_lock );
786810}
787811
@@ -857,6 +881,10 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
857881 kobject_uevent (& fw_priv -> dev .kobj , KOBJ_ADD );
858882 }
859883
884+ mutex_lock (& fw_lock );
885+ list_add (& buf -> pending_list , & pending_fw_head );
886+ mutex_unlock (& fw_lock );
887+
860888 wait_for_completion (& buf -> completion );
861889
862890 cancel_delayed_work_sync (& fw_priv -> timeout_work );
@@ -1517,6 +1545,7 @@ static int __init firmware_class_init(void)
15171545{
15181546 fw_cache_init ();
15191547#ifdef CONFIG_FW_LOADER_USER_HELPER
1548+ register_reboot_notifier (& fw_shutdown_nb );
15201549 return class_register (& firmware_class );
15211550#else
15221551 return 0 ;
@@ -1530,6 +1559,7 @@ static void __exit firmware_class_exit(void)
15301559 unregister_pm_notifier (& fw_cache .pm_notify );
15311560#endif
15321561#ifdef CONFIG_FW_LOADER_USER_HELPER
1562+ unregister_reboot_notifier (& fw_shutdown_nb );
15331563 class_unregister (& firmware_class );
15341564#endif
15351565}
0 commit comments