aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-19 12:59:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-19 12:59:02 -0400
commit4309e092421e08f411830b2675bc1538a9b90e9b (patch)
tree018a21fceba5edb73ec0dfb770a602eef54cb564 /net/sched/sch_generic.c
parent1fca25427482387689fa27594c992a961d98768f (diff)
parent195648bbc5ae0848e82f771ecf4cd7497054c212 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits) pkt_sched: Prevent livelock in TX queue running. Revert "pkt_sched: Add BH protection for qdisc_stab_lock." Revert "pkt_sched: Protect gen estimators under est_lock." pkt_sched: remove bogus block (cleanup) nf_nat: use secure_ipv4_port_ephemeral() for NAT port randomization netfilter: ctnetlink: sleepable allocation with spin lock bh netfilter: ctnetlink: fix sleep in read-side lock section netfilter: ctnetlink: fix double helper assignation for NAT'ed conntracks netfilter: ipt_addrtype: Fix matching of inverted destination address type dccp: Fix panic caused by too early termination of retransmission mechanism pkt_sched: Don't hold qdisc lock over qdisc_destroy(). pkt_sched: Add lockdep annotation for qdisc locks pkt_sched: Never schedule non-root qdiscs. removed unused #include <version.h> rt2x00: Fix txdone_entry_desc_flags b43: Fix for another Bluetooth Coexistence SPROM Programming error for BCM4306 mac80211: remove kdoc references to IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE p54u: reset skb's data/tail pointer on requeue p54: move p54_vdcf_init to the right place. iwlwifi: fix printk newlines ...
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c68
1 files changed, 19 insertions, 49 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 468574682caa..c3ed4d44fc14 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -518,14 +518,17 @@ void qdisc_reset(struct Qdisc *qdisc)
518} 518}
519EXPORT_SYMBOL(qdisc_reset); 519EXPORT_SYMBOL(qdisc_reset);
520 520
521/* this is the rcu callback function to clean up a qdisc when there 521void qdisc_destroy(struct Qdisc *qdisc)
522 * are no further references to it */
523
524static void __qdisc_destroy(struct rcu_head *head)
525{ 522{
526 struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
527 const struct Qdisc_ops *ops = qdisc->ops; 523 const struct Qdisc_ops *ops = qdisc->ops;
528 524
525 if (qdisc->flags & TCQ_F_BUILTIN ||
526 !atomic_dec_and_test(&qdisc->refcnt))
527 return;
528
529 if (qdisc->parent)
530 list_del(&qdisc->list);
531
529#ifdef CONFIG_NET_SCHED 532#ifdef CONFIG_NET_SCHED
530 qdisc_put_stab(qdisc->stab); 533 qdisc_put_stab(qdisc->stab);
531#endif 534#endif
@@ -542,20 +545,6 @@ static void __qdisc_destroy(struct rcu_head *head)
542 545
543 kfree((char *) qdisc - qdisc->padded); 546 kfree((char *) qdisc - qdisc->padded);
544} 547}
545
546/* Under qdisc_lock(qdisc) and BH! */
547
548void qdisc_destroy(struct Qdisc *qdisc)
549{
550 if (qdisc->flags & TCQ_F_BUILTIN ||
551 !atomic_dec_and_test(&qdisc->refcnt))
552 return;
553
554 if (qdisc->parent)
555 list_del(&qdisc->list);
556
557 call_rcu(&qdisc->q_rcu, __qdisc_destroy);
558}
559EXPORT_SYMBOL(qdisc_destroy); 548EXPORT_SYMBOL(qdisc_destroy);
560 549
561static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) 550static bool dev_all_qdisc_sleeping_noop(struct net_device *dev)
@@ -597,6 +586,9 @@ static void transition_one_qdisc(struct net_device *dev,
597 struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping; 586 struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping;
598 int *need_watchdog_p = _need_watchdog; 587 int *need_watchdog_p = _need_watchdog;
599 588
589 if (!(new_qdisc->flags & TCQ_F_BUILTIN))
590 clear_bit(__QDISC_STATE_DEACTIVATED, &new_qdisc->state);
591
600 rcu_assign_pointer(dev_queue->qdisc, new_qdisc); 592 rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
601 if (need_watchdog_p && new_qdisc != &noqueue_qdisc) 593 if (need_watchdog_p && new_qdisc != &noqueue_qdisc)
602 *need_watchdog_p = 1; 594 *need_watchdog_p = 1;
@@ -640,6 +632,9 @@ static void dev_deactivate_queue(struct net_device *dev,
640 if (qdisc) { 632 if (qdisc) {
641 spin_lock_bh(qdisc_lock(qdisc)); 633 spin_lock_bh(qdisc_lock(qdisc));
642 634
635 if (!(qdisc->flags & TCQ_F_BUILTIN))
636 set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
637
643 dev_queue->qdisc = qdisc_default; 638 dev_queue->qdisc = qdisc_default;
644 qdisc_reset(qdisc); 639 qdisc_reset(qdisc);
645 640
@@ -647,7 +642,7 @@ static void dev_deactivate_queue(struct net_device *dev,
647 } 642 }
648} 643}
649 644
650static bool some_qdisc_is_busy(struct net_device *dev, int lock) 645static bool some_qdisc_is_busy(struct net_device *dev)
651{ 646{
652 unsigned int i; 647 unsigned int i;
653 648
@@ -661,14 +656,12 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock)
661 q = dev_queue->qdisc_sleeping; 656 q = dev_queue->qdisc_sleeping;
662 root_lock = qdisc_lock(q); 657 root_lock = qdisc_lock(q);
663 658
664 if (lock) 659 spin_lock_bh(root_lock);
665 spin_lock_bh(root_lock);
666 660
667 val = (test_bit(__QDISC_STATE_RUNNING, &q->state) || 661 val = (test_bit(__QDISC_STATE_RUNNING, &q->state) ||
668 test_bit(__QDISC_STATE_SCHED, &q->state)); 662 test_bit(__QDISC_STATE_SCHED, &q->state));
669 663
670 if (lock) 664 spin_unlock_bh(root_lock);
671 spin_unlock_bh(root_lock);
672 665
673 if (val) 666 if (val)
674 return true; 667 return true;
@@ -678,8 +671,6 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock)
678 671
679void dev_deactivate(struct net_device *dev) 672void dev_deactivate(struct net_device *dev)
680{ 673{
681 bool running;
682
683 netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); 674 netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc);
684 dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc); 675 dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc);
685 676
@@ -689,25 +680,8 @@ void dev_deactivate(struct net_device *dev)
689 synchronize_rcu(); 680 synchronize_rcu();
690 681
691 /* Wait for outstanding qdisc_run calls. */ 682 /* Wait for outstanding qdisc_run calls. */
692 do { 683 while (some_qdisc_is_busy(dev))
693 while (some_qdisc_is_busy(dev, 0)) 684 yield();
694 yield();
695
696 /*
697 * Double-check inside queue lock to ensure that all effects
698 * of the queue run are visible when we return.
699 */
700 running = some_qdisc_is_busy(dev, 1);
701
702 /*
703 * The running flag should never be set at this point because
704 * we've already set dev->qdisc to noop_qdisc *inside* the same
705 * pair of spin locks. That is, if any qdisc_run starts after
706 * our initial test it should see the noop_qdisc and then
707 * clear the RUNNING bit before dropping the queue lock. So
708 * if it is set here then we've found a bug.
709 */
710 } while (WARN_ON_ONCE(running));
711} 685}
712 686
713static void dev_init_scheduler_queue(struct net_device *dev, 687static void dev_init_scheduler_queue(struct net_device *dev,
@@ -736,14 +710,10 @@ static void shutdown_scheduler_queue(struct net_device *dev,
736 struct Qdisc *qdisc_default = _qdisc_default; 710 struct Qdisc *qdisc_default = _qdisc_default;
737 711
738 if (qdisc) { 712 if (qdisc) {
739 spinlock_t *root_lock = qdisc_lock(qdisc);
740
741 dev_queue->qdisc = qdisc_default; 713 dev_queue->qdisc = qdisc_default;
742 dev_queue->qdisc_sleeping = qdisc_default; 714 dev_queue->qdisc_sleeping = qdisc_default;
743 715
744 spin_lock_bh(root_lock);
745 qdisc_destroy(qdisc); 716 qdisc_destroy(qdisc);
746 spin_unlock_bh(root_lock);
747 } 717 }
748} 718}
749 719