|
@@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
|
|
|
goto done;
|
|
|
|
|
|
spin_lock_irqsave(&target_list_lock, flags);
|
|
|
+restart:
|
|
|
list_for_each_entry(nt, &target_list, list) {
|
|
|
netconsole_target_get(nt);
|
|
|
if (nt->np.dev == dev) {
|
|
@@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
|
|
|
case NETDEV_UNREGISTER:
|
|
|
/*
|
|
|
* rtnl_lock already held
|
|
|
+ * we might sleep in __netpoll_cleanup()
|
|
|
*/
|
|
|
- if (nt->np.dev) {
|
|
|
- __netpoll_cleanup(&nt->np);
|
|
|
- dev_put(nt->np.dev);
|
|
|
- nt->np.dev = NULL;
|
|
|
- }
|
|
|
+ spin_unlock_irqrestore(&target_list_lock, flags);
|
|
|
+ __netpoll_cleanup(&nt->np);
|
|
|
+ spin_lock_irqsave(&target_list_lock, flags);
|
|
|
+ dev_put(nt->np.dev);
|
|
|
+ nt->np.dev = NULL;
|
|
|
nt->enabled = 0;
|
|
|
stopped = true;
|
|
|
- break;
|
|
|
+ netconsole_target_put(nt);
|
|
|
+ goto restart;
|
|
|
}
|
|
|
}
|
|
|
netconsole_target_put(nt);
|