aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netconsole.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netconsole.c')
-rw-r--r--drivers/net/netconsole.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 37add21a3d7d..59ac143dec25 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
666 goto done; 666 goto done;
667 667
668 spin_lock_irqsave(&target_list_lock, flags); 668 spin_lock_irqsave(&target_list_lock, flags);
669restart:
669 list_for_each_entry(nt, &target_list, list) { 670 list_for_each_entry(nt, &target_list, list) {
670 netconsole_target_get(nt); 671 netconsole_target_get(nt);
671 if (nt->np.dev == dev) { 672 if (nt->np.dev == dev) {
@@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
678 case NETDEV_UNREGISTER: 679 case NETDEV_UNREGISTER:
679 /* 680 /*
680 * rtnl_lock already held 681 * rtnl_lock already held
682 * we might sleep in __netpoll_cleanup()
681 */ 683 */
682 if (nt->np.dev) { 684 spin_unlock_irqrestore(&target_list_lock, flags);
683 __netpoll_cleanup(&nt->np); 685 __netpoll_cleanup(&nt->np);
684 dev_put(nt->np.dev); 686 spin_lock_irqsave(&target_list_lock, flags);
685 nt->np.dev = NULL; 687 dev_put(nt->np.dev);
686 } 688 nt->np.dev = NULL;
687 nt->enabled = 0; 689 nt->enabled = 0;
688 stopped = true; 690 stopped = true;
689 break; 691 netconsole_target_put(nt);
692 goto restart;
690 } 693 }
691 } 694 }
692 netconsole_target_put(nt); 695 netconsole_target_put(nt);