diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 6 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 12 |
2 files changed, 12 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index ab39fe17cb58..29e3888102bc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1295,7 +1295,7 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1295 | /* Disable soft irqs for various locks below. Also | 1295 | /* Disable soft irqs for various locks below. Also |
1296 | * stops preemption for RCU. | 1296 | * stops preemption for RCU. |
1297 | */ | 1297 | */ |
1298 | local_bh_disable(); | 1298 | rcu_read_lock_bh(); |
1299 | 1299 | ||
1300 | /* Updates of qdisc are serialized by queue_lock. | 1300 | /* Updates of qdisc are serialized by queue_lock. |
1301 | * The struct Qdisc which is pointed to by qdisc is now a | 1301 | * The struct Qdisc which is pointed to by qdisc is now a |
@@ -1369,13 +1369,13 @@ int dev_queue_xmit(struct sk_buff *skb) | |||
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | rc = -ENETDOWN; | 1371 | rc = -ENETDOWN; |
1372 | local_bh_enable(); | 1372 | rcu_read_unlock_bh(); |
1373 | 1373 | ||
1374 | out_kfree_skb: | 1374 | out_kfree_skb: |
1375 | kfree_skb(skb); | 1375 | kfree_skb(skb); |
1376 | return rc; | 1376 | return rc; |
1377 | out: | 1377 | out: |
1378 | local_bh_enable(); | 1378 | rcu_read_unlock_bh(); |
1379 | return rc; | 1379 | return rc; |
1380 | } | 1380 | } |
1381 | 1381 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d7aca8ef524a..7aad0121232c 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -181,9 +181,13 @@ requeue: | |||
181 | 181 | ||
182 | void __qdisc_run(struct net_device *dev) | 182 | void __qdisc_run(struct net_device *dev) |
183 | { | 183 | { |
184 | if (unlikely(dev->qdisc == &noop_qdisc)) | ||
185 | goto out; | ||
186 | |||
184 | while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) | 187 | while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev)) |
185 | /* NOTHING */; | 188 | /* NOTHING */; |
186 | 189 | ||
190 | out: | ||
187 | clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); | 191 | clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); |
188 | } | 192 | } |
189 | 193 | ||
@@ -583,10 +587,12 @@ void dev_deactivate(struct net_device *dev) | |||
583 | 587 | ||
584 | dev_watchdog_down(dev); | 588 | dev_watchdog_down(dev); |
585 | 589 | ||
586 | while (test_bit(__LINK_STATE_SCHED, &dev->state)) | 590 | /* Wait for outstanding dev_queue_xmit calls. */ |
587 | yield(); | 591 | synchronize_rcu(); |
588 | 592 | ||
589 | spin_unlock_wait(&dev->_xmit_lock); | 593 | /* Wait for outstanding qdisc_run calls. */ |
594 | while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) | ||
595 | yield(); | ||
590 | } | 596 | } |
591 | 597 | ||
592 | void dev_init_scheduler(struct net_device *dev) | 598 | void dev_init_scheduler(struct net_device *dev) |