diff options
Diffstat (limited to 'net/sched/sch_generic.c')
| -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 c84b65920d1..b1721d71c27 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)  	return false;  } +/** + * 	dev_deactivate_many - deactivate transmissions on several devices + * 	@head: list of devices to deactivate + * + *	This function returns only when all outstanding transmissions + *	have completed, unless all devices are in dismantle phase. + */  void dev_deactivate_many(struct list_head *head)  {  	struct net_device *dev; +	bool sync_needed = false;  	list_for_each_entry(dev, head, unreg_list) {  		netdev_for_each_tx_queue(dev, dev_deactivate_queue, @@ -827,10 +835,15 @@ void dev_deactivate_many(struct list_head *head)  					     &noop_qdisc);  		dev_watchdog_down(dev); +		sync_needed |= !dev->dismantle;  	} -	/* Wait for outstanding qdisc-less dev_queue_xmit calls. */ -	synchronize_rcu(); +	/* Wait for outstanding qdisc-less dev_queue_xmit calls. +	 * This is avoided if all devices are in dismantle phase : +	 * Caller will call synchronize_net() for us +	 */ +	if (sync_needed) +		synchronize_net();  	/* Wait for outstanding qdisc_run calls. */  	list_for_each_entry(dev, head, unreg_list)  |