aboutsummaryrefslogtreecommitdiffstats
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.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index d7aca8ef524a..74d4a1dceeec 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -96,8 +96,11 @@ static inline int qdisc_restart(struct net_device *dev)
96 struct sk_buff *skb; 96 struct sk_buff *skb;
97 97
98 /* Dequeue packet */ 98 /* Dequeue packet */
99 if ((skb = q->dequeue(q)) != NULL) { 99 if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
100 unsigned nolock = (dev->features & NETIF_F_LLTX); 100 unsigned nolock = (dev->features & NETIF_F_LLTX);
101
102 dev->gso_skb = NULL;
103
101 /* 104 /*
102 * When the driver has LLTX set it does its own locking 105 * When the driver has LLTX set it does its own locking
103 * in start_xmit. No need to add additional overhead by 106 * in start_xmit. No need to add additional overhead by
@@ -134,10 +137,8 @@ static inline int qdisc_restart(struct net_device *dev)
134 137
135 if (!netif_queue_stopped(dev)) { 138 if (!netif_queue_stopped(dev)) {
136 int ret; 139 int ret;
137 if (netdev_nit)
138 dev_queue_xmit_nit(skb, dev);
139 140
140 ret = dev->hard_start_xmit(skb, dev); 141 ret = dev_hard_start_xmit(skb, dev);
141 if (ret == NETDEV_TX_OK) { 142 if (ret == NETDEV_TX_OK) {
142 if (!nolock) { 143 if (!nolock) {
143 netif_tx_unlock(dev); 144 netif_tx_unlock(dev);
@@ -171,7 +172,10 @@ static inline int qdisc_restart(struct net_device *dev)
171 */ 172 */
172 173
173requeue: 174requeue:
174 q->ops->requeue(skb, q); 175 if (skb->next)
176 dev->gso_skb = skb;
177 else
178 q->ops->requeue(skb, q);
175 netif_schedule(dev); 179 netif_schedule(dev);
176 return 1; 180 return 1;
177 } 181 }
@@ -181,9 +185,13 @@ requeue:
181 185
182void __qdisc_run(struct net_device *dev) 186void __qdisc_run(struct net_device *dev)
183{ 187{
188 if (unlikely(dev->qdisc == &noop_qdisc))
189 goto out;
190
184 while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) 191 while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
185 /* NOTHING */; 192 /* NOTHING */;
186 193
194out:
187 clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); 195 clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
188} 196}
189 197
@@ -583,10 +591,17 @@ void dev_deactivate(struct net_device *dev)
583 591
584 dev_watchdog_down(dev); 592 dev_watchdog_down(dev);
585 593
586 while (test_bit(__LINK_STATE_SCHED, &dev->state)) 594 /* Wait for outstanding dev_queue_xmit calls. */
595 synchronize_rcu();
596
597 /* Wait for outstanding qdisc_run calls. */
598 while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
587 yield(); 599 yield();
588 600
589 spin_unlock_wait(&dev->_xmit_lock); 601 if (dev->gso_skb) {
602 kfree_skb(dev->gso_skb);
603 dev->gso_skb = NULL;
604 }
590} 605}
591 606
592void dev_init_scheduler(struct net_device *dev) 607void dev_init_scheduler(struct net_device *dev)