summaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index c84b65920d1..69fca279880 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -189,15 +189,15 @@ static inline int qdisc_restart(struct Qdisc *q)
void __qdisc_run(struct Qdisc *q)
{
- unsigned long start_time = jiffies;
+ int quota = weight_p;
while (qdisc_restart(q)) {
/*
- * Postpone processing if
- * 1. another process needs the CPU;
- * 2. we've been doing it for too long.
+ * Ordered by possible occurrence: Postpone processing if
+ * 1. we've exceeded packet quota
+ * 2. another process needs the CPU;
*/
- if (need_resched() || jiffies != start_time) {
+ if (--quota <= 0 || need_resched()) {
__netif_schedule(q);
break;
}
@@ -251,9 +251,8 @@ static void dev_watchdog(unsigned long arg)
}
if (some_queue_timedout) {
- char drivername[64];
WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n",
- dev->name, netdev_drivername(dev, drivername, 64), i);
+ dev->name, netdev_drivername(dev), i);
dev->netdev_ops->ndo_tx_timeout(dev);
}
if (!mod_timer(&dev->watchdog_timer,
@@ -815,9 +814,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 +834,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)