diff options
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index b1e4c5e20ac7..74d4a1dceeec 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -90,14 +90,17 @@ void qdisc_unlock_tree(struct net_device *dev) | |||
90 | NOTE: Called under dev->queue_lock with locally disabled BH. | 90 | NOTE: Called under dev->queue_lock with locally disabled BH. |
91 | */ | 91 | */ |
92 | 92 | ||
93 | int qdisc_restart(struct net_device *dev) | 93 | static inline int qdisc_restart(struct net_device *dev) |
94 | { | 94 | { |
95 | struct Qdisc *q = dev->qdisc; | 95 | struct Qdisc *q = dev->qdisc; |
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 @@ 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 @@ int qdisc_restart(struct net_device *dev) | |||
171 | */ | 172 | */ |
172 | 173 | ||
173 | requeue: | 174 | requeue: |
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 | } |
@@ -179,6 +183,18 @@ requeue: | |||
179 | return q->q.qlen; | 183 | return q->q.qlen; |
180 | } | 184 | } |
181 | 185 | ||
186 | void __qdisc_run(struct net_device *dev) | ||
187 | { | ||
188 | if (unlikely(dev->qdisc == &noop_qdisc)) | ||
189 | goto out; | ||
190 | |||
191 | while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) | ||
192 | /* NOTHING */; | ||
193 | |||
194 | out: | ||
195 | clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); | ||
196 | } | ||
197 | |||
182 | static void dev_watchdog(unsigned long arg) | 198 | static void dev_watchdog(unsigned long arg) |
183 | { | 199 | { |
184 | struct net_device *dev = (struct net_device *)arg; | 200 | struct net_device *dev = (struct net_device *)arg; |
@@ -575,10 +591,17 @@ void dev_deactivate(struct net_device *dev) | |||
575 | 591 | ||
576 | dev_watchdog_down(dev); | 592 | dev_watchdog_down(dev); |
577 | 593 | ||
578 | 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)) | ||
579 | yield(); | 599 | yield(); |
580 | 600 | ||
581 | spin_unlock_wait(&dev->_xmit_lock); | 601 | if (dev->gso_skb) { |
602 | kfree_skb(dev->gso_skb); | ||
603 | dev->gso_skb = NULL; | ||
604 | } | ||
582 | } | 605 | } |
583 | 606 | ||
584 | void dev_init_scheduler(struct net_device *dev) | 607 | void dev_init_scheduler(struct net_device *dev) |
@@ -620,6 +643,5 @@ EXPORT_SYMBOL(qdisc_create_dflt); | |||
620 | EXPORT_SYMBOL(qdisc_alloc); | 643 | EXPORT_SYMBOL(qdisc_alloc); |
621 | EXPORT_SYMBOL(qdisc_destroy); | 644 | EXPORT_SYMBOL(qdisc_destroy); |
622 | EXPORT_SYMBOL(qdisc_reset); | 645 | EXPORT_SYMBOL(qdisc_reset); |
623 | EXPORT_SYMBOL(qdisc_restart); | ||
624 | EXPORT_SYMBOL(qdisc_lock_tree); | 646 | EXPORT_SYMBOL(qdisc_lock_tree); |
625 | EXPORT_SYMBOL(qdisc_unlock_tree); | 647 | EXPORT_SYMBOL(qdisc_unlock_tree); |