diff options
-rw-r--r-- | net/sched/sch_generic.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index c84b65920d1b..b1721d71c27c 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -815,9 +815,17 @@ static bool some_qdisc_is_busy(struct net_device *dev) | |||
815 | return false; | 815 | return false; |
816 | } | 816 | } |
817 | 817 | ||
818 | /** | ||
819 | * dev_deactivate_many - deactivate transmissions on several devices | ||
820 | * @head: list of devices to deactivate | ||
821 | * | ||
822 | * This function returns only when all outstanding transmissions | ||
823 | * have completed, unless all devices are in dismantle phase. | ||
824 | */ | ||
818 | void dev_deactivate_many(struct list_head *head) | 825 | void dev_deactivate_many(struct list_head *head) |
819 | { | 826 | { |
820 | struct net_device *dev; | 827 | struct net_device *dev; |
828 | bool sync_needed = false; | ||
821 | 829 | ||
822 | list_for_each_entry(dev, head, unreg_list) { | 830 | list_for_each_entry(dev, head, unreg_list) { |
823 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, | 831 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, |
@@ -827,10 +835,15 @@ void dev_deactivate_many(struct list_head *head) | |||
827 | &noop_qdisc); | 835 | &noop_qdisc); |
828 | 836 | ||
829 | dev_watchdog_down(dev); | 837 | dev_watchdog_down(dev); |
838 | sync_needed |= !dev->dismantle; | ||
830 | } | 839 | } |
831 | 840 | ||
832 | /* Wait for outstanding qdisc-less dev_queue_xmit calls. */ | 841 | /* Wait for outstanding qdisc-less dev_queue_xmit calls. |
833 | synchronize_rcu(); | 842 | * This is avoided if all devices are in dismantle phase : |
843 | * Caller will call synchronize_net() for us | ||
844 | */ | ||
845 | if (sync_needed) | ||
846 | synchronize_net(); | ||
834 | 847 | ||
835 | /* Wait for outstanding qdisc_run calls. */ | 848 | /* Wait for outstanding qdisc_run calls. */ |
836 | list_for_each_entry(dev, head, unreg_list) | 849 | list_for_each_entry(dev, head, unreg_list) |