diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
commit | ff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch) | |
tree | 85205005c611ab774702148558321c6fb92f1ccd /net/sched/sch_generic.c | |
parent | 30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff) | |
parent | d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff) |
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 373 |
1 files changed, 237 insertions, 136 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 13afa7214392..4ac7e3a8c253 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -29,58 +29,36 @@ | |||
29 | /* Main transmission queue. */ | 29 | /* Main transmission queue. */ |
30 | 30 | ||
31 | /* Modifications to data participating in scheduling must be protected with | 31 | /* Modifications to data participating in scheduling must be protected with |
32 | * dev->queue_lock spinlock. | 32 | * qdisc_root_lock(qdisc) spinlock. |
33 | * | 33 | * |
34 | * The idea is the following: | 34 | * The idea is the following: |
35 | * - enqueue, dequeue are serialized via top level device | 35 | * - enqueue, dequeue are serialized via qdisc root lock |
36 | * spinlock dev->queue_lock. | 36 | * - ingress filtering is also serialized via qdisc root lock |
37 | * - ingress filtering is serialized via top level device | ||
38 | * spinlock dev->ingress_lock. | ||
39 | * - updates to tree and tree walking are only done under the rtnl mutex. | 37 | * - updates to tree and tree walking are only done under the rtnl mutex. |
40 | */ | 38 | */ |
41 | 39 | ||
42 | void qdisc_lock_tree(struct net_device *dev) | ||
43 | __acquires(dev->queue_lock) | ||
44 | __acquires(dev->ingress_lock) | ||
45 | { | ||
46 | spin_lock_bh(&dev->queue_lock); | ||
47 | spin_lock(&dev->ingress_lock); | ||
48 | } | ||
49 | EXPORT_SYMBOL(qdisc_lock_tree); | ||
50 | |||
51 | void qdisc_unlock_tree(struct net_device *dev) | ||
52 | __releases(dev->ingress_lock) | ||
53 | __releases(dev->queue_lock) | ||
54 | { | ||
55 | spin_unlock(&dev->ingress_lock); | ||
56 | spin_unlock_bh(&dev->queue_lock); | ||
57 | } | ||
58 | EXPORT_SYMBOL(qdisc_unlock_tree); | ||
59 | |||
60 | static inline int qdisc_qlen(struct Qdisc *q) | 40 | static inline int qdisc_qlen(struct Qdisc *q) |
61 | { | 41 | { |
62 | return q->q.qlen; | 42 | return q->q.qlen; |
63 | } | 43 | } |
64 | 44 | ||
65 | static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev, | 45 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) |
66 | struct Qdisc *q) | ||
67 | { | 46 | { |
68 | if (unlikely(skb->next)) | 47 | if (unlikely(skb->next)) |
69 | dev->gso_skb = skb; | 48 | q->gso_skb = skb; |
70 | else | 49 | else |
71 | q->ops->requeue(skb, q); | 50 | q->ops->requeue(skb, q); |
72 | 51 | ||
73 | netif_schedule(dev); | 52 | __netif_schedule(q); |
74 | return 0; | 53 | return 0; |
75 | } | 54 | } |
76 | 55 | ||
77 | static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev, | 56 | static inline struct sk_buff *dequeue_skb(struct Qdisc *q) |
78 | struct Qdisc *q) | ||
79 | { | 57 | { |
80 | struct sk_buff *skb; | 58 | struct sk_buff *skb; |
81 | 59 | ||
82 | if ((skb = dev->gso_skb)) | 60 | if ((skb = q->gso_skb)) |
83 | dev->gso_skb = NULL; | 61 | q->gso_skb = NULL; |
84 | else | 62 | else |
85 | skb = q->dequeue(q); | 63 | skb = q->dequeue(q); |
86 | 64 | ||
@@ -88,12 +66,12 @@ static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev, | |||
88 | } | 66 | } |
89 | 67 | ||
90 | static inline int handle_dev_cpu_collision(struct sk_buff *skb, | 68 | static inline int handle_dev_cpu_collision(struct sk_buff *skb, |
91 | struct net_device *dev, | 69 | struct netdev_queue *dev_queue, |
92 | struct Qdisc *q) | 70 | struct Qdisc *q) |
93 | { | 71 | { |
94 | int ret; | 72 | int ret; |
95 | 73 | ||
96 | if (unlikely(dev->xmit_lock_owner == smp_processor_id())) { | 74 | if (unlikely(dev_queue->xmit_lock_owner == smp_processor_id())) { |
97 | /* | 75 | /* |
98 | * Same CPU holding the lock. It may be a transient | 76 | * Same CPU holding the lock. It may be a transient |
99 | * configuration error, when hard_start_xmit() recurses. We | 77 | * configuration error, when hard_start_xmit() recurses. We |
@@ -103,7 +81,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
103 | kfree_skb(skb); | 81 | kfree_skb(skb); |
104 | if (net_ratelimit()) | 82 | if (net_ratelimit()) |
105 | printk(KERN_WARNING "Dead loop on netdevice %s, " | 83 | printk(KERN_WARNING "Dead loop on netdevice %s, " |
106 | "fix it urgently!\n", dev->name); | 84 | "fix it urgently!\n", dev_queue->dev->name); |
107 | ret = qdisc_qlen(q); | 85 | ret = qdisc_qlen(q); |
108 | } else { | 86 | } else { |
109 | /* | 87 | /* |
@@ -111,22 +89,22 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
111 | * some time. | 89 | * some time. |
112 | */ | 90 | */ |
113 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | 91 | __get_cpu_var(netdev_rx_stat).cpu_collision++; |
114 | ret = dev_requeue_skb(skb, dev, q); | 92 | ret = dev_requeue_skb(skb, q); |
115 | } | 93 | } |
116 | 94 | ||
117 | return ret; | 95 | return ret; |
118 | } | 96 | } |
119 | 97 | ||
120 | /* | 98 | /* |
121 | * NOTE: Called under dev->queue_lock with locally disabled BH. | 99 | * NOTE: Called under qdisc_lock(q) with locally disabled BH. |
122 | * | 100 | * |
123 | * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this | 101 | * __QDISC_STATE_RUNNING guarantees only one CPU can process |
124 | * device at a time. dev->queue_lock serializes queue accesses for | 102 | * this qdisc at a time. qdisc_lock(q) serializes queue accesses for |
125 | * this device AND dev->qdisc pointer itself. | 103 | * this queue. |
126 | * | 104 | * |
127 | * netif_tx_lock serializes accesses to device driver. | 105 | * netif_tx_lock serializes accesses to device driver. |
128 | * | 106 | * |
129 | * dev->queue_lock and netif_tx_lock are mutually exclusive, | 107 | * qdisc_lock(q) and netif_tx_lock are mutually exclusive, |
130 | * if one is grabbed, another must be free. | 108 | * if one is grabbed, another must be free. |
131 | * | 109 | * |
132 | * Note, that this procedure can be called by a watchdog timer | 110 | * Note, that this procedure can be called by a watchdog timer |
@@ -136,27 +114,32 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
136 | * >0 - queue is not empty. | 114 | * >0 - queue is not empty. |
137 | * | 115 | * |
138 | */ | 116 | */ |
139 | static inline int qdisc_restart(struct net_device *dev) | 117 | static inline int qdisc_restart(struct Qdisc *q) |
140 | { | 118 | { |
141 | struct Qdisc *q = dev->qdisc; | 119 | struct netdev_queue *txq; |
142 | struct sk_buff *skb; | ||
143 | int ret = NETDEV_TX_BUSY; | 120 | int ret = NETDEV_TX_BUSY; |
121 | struct net_device *dev; | ||
122 | spinlock_t *root_lock; | ||
123 | struct sk_buff *skb; | ||
144 | 124 | ||
145 | /* Dequeue packet */ | 125 | /* Dequeue packet */ |
146 | if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL)) | 126 | if (unlikely((skb = dequeue_skb(q)) == NULL)) |
147 | return 0; | 127 | return 0; |
148 | 128 | ||
129 | root_lock = qdisc_root_lock(q); | ||
130 | |||
131 | /* And release qdisc */ | ||
132 | spin_unlock(root_lock); | ||
149 | 133 | ||
150 | /* And release queue */ | 134 | dev = qdisc_dev(q); |
151 | spin_unlock(&dev->queue_lock); | 135 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
152 | 136 | ||
153 | HARD_TX_LOCK(dev, smp_processor_id()); | 137 | HARD_TX_LOCK(dev, txq, smp_processor_id()); |
154 | if (!netif_subqueue_stopped(dev, skb)) | 138 | if (!netif_subqueue_stopped(dev, skb)) |
155 | ret = dev_hard_start_xmit(skb, dev); | 139 | ret = dev_hard_start_xmit(skb, dev, txq); |
156 | HARD_TX_UNLOCK(dev); | 140 | HARD_TX_UNLOCK(dev, txq); |
157 | 141 | ||
158 | spin_lock(&dev->queue_lock); | 142 | spin_lock(root_lock); |
159 | q = dev->qdisc; | ||
160 | 143 | ||
161 | switch (ret) { | 144 | switch (ret) { |
162 | case NETDEV_TX_OK: | 145 | case NETDEV_TX_OK: |
@@ -166,7 +149,7 @@ static inline int qdisc_restart(struct net_device *dev) | |||
166 | 149 | ||
167 | case NETDEV_TX_LOCKED: | 150 | case NETDEV_TX_LOCKED: |
168 | /* Driver try lock failed */ | 151 | /* Driver try lock failed */ |
169 | ret = handle_dev_cpu_collision(skb, dev, q); | 152 | ret = handle_dev_cpu_collision(skb, txq, q); |
170 | break; | 153 | break; |
171 | 154 | ||
172 | default: | 155 | default: |
@@ -175,33 +158,33 @@ static inline int qdisc_restart(struct net_device *dev) | |||
175 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", | 158 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", |
176 | dev->name, ret, q->q.qlen); | 159 | dev->name, ret, q->q.qlen); |
177 | 160 | ||
178 | ret = dev_requeue_skb(skb, dev, q); | 161 | ret = dev_requeue_skb(skb, q); |
179 | break; | 162 | break; |
180 | } | 163 | } |
181 | 164 | ||
165 | if (ret && netif_tx_queue_stopped(txq)) | ||
166 | ret = 0; | ||
167 | |||
182 | return ret; | 168 | return ret; |
183 | } | 169 | } |
184 | 170 | ||
185 | void __qdisc_run(struct net_device *dev) | 171 | void __qdisc_run(struct Qdisc *q) |
186 | { | 172 | { |
187 | unsigned long start_time = jiffies; | 173 | unsigned long start_time = jiffies; |
188 | 174 | ||
189 | while (qdisc_restart(dev)) { | 175 | while (qdisc_restart(q)) { |
190 | if (netif_queue_stopped(dev)) | ||
191 | break; | ||
192 | |||
193 | /* | 176 | /* |
194 | * Postpone processing if | 177 | * Postpone processing if |
195 | * 1. another process needs the CPU; | 178 | * 1. another process needs the CPU; |
196 | * 2. we've been doing it for too long. | 179 | * 2. we've been doing it for too long. |
197 | */ | 180 | */ |
198 | if (need_resched() || jiffies != start_time) { | 181 | if (need_resched() || jiffies != start_time) { |
199 | netif_schedule(dev); | 182 | __netif_schedule(q); |
200 | break; | 183 | break; |
201 | } | 184 | } |
202 | } | 185 | } |
203 | 186 | ||
204 | clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); | 187 | clear_bit(__QDISC_STATE_RUNNING, &q->state); |
205 | } | 188 | } |
206 | 189 | ||
207 | static void dev_watchdog(unsigned long arg) | 190 | static void dev_watchdog(unsigned long arg) |
@@ -209,19 +192,35 @@ static void dev_watchdog(unsigned long arg) | |||
209 | struct net_device *dev = (struct net_device *)arg; | 192 | struct net_device *dev = (struct net_device *)arg; |
210 | 193 | ||
211 | netif_tx_lock(dev); | 194 | netif_tx_lock(dev); |
212 | if (dev->qdisc != &noop_qdisc) { | 195 | if (!qdisc_tx_is_noop(dev)) { |
213 | if (netif_device_present(dev) && | 196 | if (netif_device_present(dev) && |
214 | netif_running(dev) && | 197 | netif_running(dev) && |
215 | netif_carrier_ok(dev)) { | 198 | netif_carrier_ok(dev)) { |
216 | if (netif_queue_stopped(dev) && | 199 | int some_queue_stopped = 0; |
217 | time_after(jiffies, dev->trans_start + dev->watchdog_timeo)) { | 200 | unsigned int i; |
218 | 201 | ||
219 | printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", | 202 | for (i = 0; i < dev->num_tx_queues; i++) { |
220 | dev->name); | 203 | struct netdev_queue *txq; |
204 | |||
205 | txq = netdev_get_tx_queue(dev, i); | ||
206 | if (netif_tx_queue_stopped(txq)) { | ||
207 | some_queue_stopped = 1; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | if (some_queue_stopped && | ||
213 | time_after(jiffies, (dev->trans_start + | ||
214 | dev->watchdog_timeo))) { | ||
215 | char drivername[64]; | ||
216 | printk(KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n", | ||
217 | dev->name, netdev_drivername(dev, drivername, 64)); | ||
221 | dev->tx_timeout(dev); | 218 | dev->tx_timeout(dev); |
222 | WARN_ON_ONCE(1); | 219 | WARN_ON_ONCE(1); |
223 | } | 220 | } |
224 | if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo))) | 221 | if (!mod_timer(&dev->watchdog_timer, |
222 | round_jiffies(jiffies + | ||
223 | dev->watchdog_timeo))) | ||
225 | dev_hold(dev); | 224 | dev_hold(dev); |
226 | } | 225 | } |
227 | } | 226 | } |
@@ -317,12 +316,18 @@ struct Qdisc_ops noop_qdisc_ops __read_mostly = { | |||
317 | .owner = THIS_MODULE, | 316 | .owner = THIS_MODULE, |
318 | }; | 317 | }; |
319 | 318 | ||
319 | static struct netdev_queue noop_netdev_queue = { | ||
320 | .qdisc = &noop_qdisc, | ||
321 | }; | ||
322 | |||
320 | struct Qdisc noop_qdisc = { | 323 | struct Qdisc noop_qdisc = { |
321 | .enqueue = noop_enqueue, | 324 | .enqueue = noop_enqueue, |
322 | .dequeue = noop_dequeue, | 325 | .dequeue = noop_dequeue, |
323 | .flags = TCQ_F_BUILTIN, | 326 | .flags = TCQ_F_BUILTIN, |
324 | .ops = &noop_qdisc_ops, | 327 | .ops = &noop_qdisc_ops, |
325 | .list = LIST_HEAD_INIT(noop_qdisc.list), | 328 | .list = LIST_HEAD_INIT(noop_qdisc.list), |
329 | .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), | ||
330 | .dev_queue = &noop_netdev_queue, | ||
326 | }; | 331 | }; |
327 | EXPORT_SYMBOL(noop_qdisc); | 332 | EXPORT_SYMBOL(noop_qdisc); |
328 | 333 | ||
@@ -335,12 +340,19 @@ static struct Qdisc_ops noqueue_qdisc_ops __read_mostly = { | |||
335 | .owner = THIS_MODULE, | 340 | .owner = THIS_MODULE, |
336 | }; | 341 | }; |
337 | 342 | ||
343 | static struct Qdisc noqueue_qdisc; | ||
344 | static struct netdev_queue noqueue_netdev_queue = { | ||
345 | .qdisc = &noqueue_qdisc, | ||
346 | }; | ||
347 | |||
338 | static struct Qdisc noqueue_qdisc = { | 348 | static struct Qdisc noqueue_qdisc = { |
339 | .enqueue = NULL, | 349 | .enqueue = NULL, |
340 | .dequeue = noop_dequeue, | 350 | .dequeue = noop_dequeue, |
341 | .flags = TCQ_F_BUILTIN, | 351 | .flags = TCQ_F_BUILTIN, |
342 | .ops = &noqueue_qdisc_ops, | 352 | .ops = &noqueue_qdisc_ops, |
343 | .list = LIST_HEAD_INIT(noqueue_qdisc.list), | 353 | .list = LIST_HEAD_INIT(noqueue_qdisc.list), |
354 | .q.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), | ||
355 | .dev_queue = &noqueue_netdev_queue, | ||
344 | }; | 356 | }; |
345 | 357 | ||
346 | 358 | ||
@@ -364,7 +376,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) | |||
364 | { | 376 | { |
365 | struct sk_buff_head *list = prio2list(skb, qdisc); | 377 | struct sk_buff_head *list = prio2list(skb, qdisc); |
366 | 378 | ||
367 | if (skb_queue_len(list) < qdisc->dev->tx_queue_len) { | 379 | if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) { |
368 | qdisc->q.qlen++; | 380 | qdisc->q.qlen++; |
369 | return __qdisc_enqueue_tail(skb, qdisc, list); | 381 | return __qdisc_enqueue_tail(skb, qdisc, list); |
370 | } | 382 | } |
@@ -440,7 +452,8 @@ static struct Qdisc_ops pfifo_fast_ops __read_mostly = { | |||
440 | .owner = THIS_MODULE, | 452 | .owner = THIS_MODULE, |
441 | }; | 453 | }; |
442 | 454 | ||
443 | struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) | 455 | struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
456 | struct Qdisc_ops *ops) | ||
444 | { | 457 | { |
445 | void *p; | 458 | void *p; |
446 | struct Qdisc *sch; | 459 | struct Qdisc *sch; |
@@ -462,8 +475,8 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) | |||
462 | sch->ops = ops; | 475 | sch->ops = ops; |
463 | sch->enqueue = ops->enqueue; | 476 | sch->enqueue = ops->enqueue; |
464 | sch->dequeue = ops->dequeue; | 477 | sch->dequeue = ops->dequeue; |
465 | sch->dev = dev; | 478 | sch->dev_queue = dev_queue; |
466 | dev_hold(dev); | 479 | dev_hold(qdisc_dev(sch)); |
467 | atomic_set(&sch->refcnt, 1); | 480 | atomic_set(&sch->refcnt, 1); |
468 | 481 | ||
469 | return sch; | 482 | return sch; |
@@ -471,15 +484,16 @@ errout: | |||
471 | return ERR_PTR(err); | 484 | return ERR_PTR(err); |
472 | } | 485 | } |
473 | 486 | ||
474 | struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, | 487 | struct Qdisc * qdisc_create_dflt(struct net_device *dev, |
488 | struct netdev_queue *dev_queue, | ||
489 | struct Qdisc_ops *ops, | ||
475 | unsigned int parentid) | 490 | unsigned int parentid) |
476 | { | 491 | { |
477 | struct Qdisc *sch; | 492 | struct Qdisc *sch; |
478 | 493 | ||
479 | sch = qdisc_alloc(dev, ops); | 494 | sch = qdisc_alloc(dev_queue, ops); |
480 | if (IS_ERR(sch)) | 495 | if (IS_ERR(sch)) |
481 | goto errout; | 496 | goto errout; |
482 | sch->stats_lock = &dev->queue_lock; | ||
483 | sch->parent = parentid; | 497 | sch->parent = parentid; |
484 | 498 | ||
485 | if (!ops->init || ops->init(sch, NULL) == 0) | 499 | if (!ops->init || ops->init(sch, NULL) == 0) |
@@ -491,7 +505,7 @@ errout: | |||
491 | } | 505 | } |
492 | EXPORT_SYMBOL(qdisc_create_dflt); | 506 | EXPORT_SYMBOL(qdisc_create_dflt); |
493 | 507 | ||
494 | /* Under dev->queue_lock and BH! */ | 508 | /* Under qdisc_root_lock(qdisc) and BH! */ |
495 | 509 | ||
496 | void qdisc_reset(struct Qdisc *qdisc) | 510 | void qdisc_reset(struct Qdisc *qdisc) |
497 | { | 511 | { |
@@ -508,86 +522,161 @@ EXPORT_SYMBOL(qdisc_reset); | |||
508 | static void __qdisc_destroy(struct rcu_head *head) | 522 | static void __qdisc_destroy(struct rcu_head *head) |
509 | { | 523 | { |
510 | struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu); | 524 | struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu); |
525 | const struct Qdisc_ops *ops = qdisc->ops; | ||
526 | |||
527 | #ifdef CONFIG_NET_SCHED | ||
528 | qdisc_put_stab(qdisc->stab); | ||
529 | #endif | ||
530 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); | ||
531 | if (ops->reset) | ||
532 | ops->reset(qdisc); | ||
533 | if (ops->destroy) | ||
534 | ops->destroy(qdisc); | ||
535 | |||
536 | module_put(ops->owner); | ||
537 | dev_put(qdisc_dev(qdisc)); | ||
538 | |||
539 | kfree_skb(qdisc->gso_skb); | ||
540 | |||
511 | kfree((char *) qdisc - qdisc->padded); | 541 | kfree((char *) qdisc - qdisc->padded); |
512 | } | 542 | } |
513 | 543 | ||
514 | /* Under dev->queue_lock and BH! */ | 544 | /* Under qdisc_root_lock(qdisc) and BH! */ |
515 | 545 | ||
516 | void qdisc_destroy(struct Qdisc *qdisc) | 546 | void qdisc_destroy(struct Qdisc *qdisc) |
517 | { | 547 | { |
518 | const struct Qdisc_ops *ops = qdisc->ops; | ||
519 | |||
520 | if (qdisc->flags & TCQ_F_BUILTIN || | 548 | if (qdisc->flags & TCQ_F_BUILTIN || |
521 | !atomic_dec_and_test(&qdisc->refcnt)) | 549 | !atomic_dec_and_test(&qdisc->refcnt)) |
522 | return; | 550 | return; |
523 | 551 | ||
524 | list_del(&qdisc->list); | 552 | if (qdisc->parent) |
525 | gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); | 553 | list_del(&qdisc->list); |
526 | if (ops->reset) | ||
527 | ops->reset(qdisc); | ||
528 | if (ops->destroy) | ||
529 | ops->destroy(qdisc); | ||
530 | 554 | ||
531 | module_put(ops->owner); | ||
532 | dev_put(qdisc->dev); | ||
533 | call_rcu(&qdisc->q_rcu, __qdisc_destroy); | 555 | call_rcu(&qdisc->q_rcu, __qdisc_destroy); |
534 | } | 556 | } |
535 | EXPORT_SYMBOL(qdisc_destroy); | 557 | EXPORT_SYMBOL(qdisc_destroy); |
536 | 558 | ||
559 | static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) | ||
560 | { | ||
561 | unsigned int i; | ||
562 | |||
563 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
564 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
565 | |||
566 | if (txq->qdisc_sleeping != &noop_qdisc) | ||
567 | return false; | ||
568 | } | ||
569 | return true; | ||
570 | } | ||
571 | |||
572 | static void attach_one_default_qdisc(struct net_device *dev, | ||
573 | struct netdev_queue *dev_queue, | ||
574 | void *_unused) | ||
575 | { | ||
576 | struct Qdisc *qdisc; | ||
577 | |||
578 | if (dev->tx_queue_len) { | ||
579 | qdisc = qdisc_create_dflt(dev, dev_queue, | ||
580 | &pfifo_fast_ops, TC_H_ROOT); | ||
581 | if (!qdisc) { | ||
582 | printk(KERN_INFO "%s: activation failed\n", dev->name); | ||
583 | return; | ||
584 | } | ||
585 | } else { | ||
586 | qdisc = &noqueue_qdisc; | ||
587 | } | ||
588 | dev_queue->qdisc_sleeping = qdisc; | ||
589 | } | ||
590 | |||
591 | static void transition_one_qdisc(struct net_device *dev, | ||
592 | struct netdev_queue *dev_queue, | ||
593 | void *_need_watchdog) | ||
594 | { | ||
595 | struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping; | ||
596 | int *need_watchdog_p = _need_watchdog; | ||
597 | |||
598 | rcu_assign_pointer(dev_queue->qdisc, new_qdisc); | ||
599 | if (new_qdisc != &noqueue_qdisc) | ||
600 | *need_watchdog_p = 1; | ||
601 | } | ||
602 | |||
537 | void dev_activate(struct net_device *dev) | 603 | void dev_activate(struct net_device *dev) |
538 | { | 604 | { |
605 | int need_watchdog; | ||
606 | |||
539 | /* No queueing discipline is attached to device; | 607 | /* No queueing discipline is attached to device; |
540 | create default one i.e. pfifo_fast for devices, | 608 | create default one i.e. pfifo_fast for devices, |
541 | which need queueing and noqueue_qdisc for | 609 | which need queueing and noqueue_qdisc for |
542 | virtual interfaces | 610 | virtual interfaces |
543 | */ | 611 | */ |
544 | 612 | ||
545 | if (dev->qdisc_sleeping == &noop_qdisc) { | 613 | if (dev_all_qdisc_sleeping_noop(dev)) |
546 | struct Qdisc *qdisc; | 614 | netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); |
547 | if (dev->tx_queue_len) { | ||
548 | qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops, | ||
549 | TC_H_ROOT); | ||
550 | if (qdisc == NULL) { | ||
551 | printk(KERN_INFO "%s: activation failed\n", dev->name); | ||
552 | return; | ||
553 | } | ||
554 | list_add_tail(&qdisc->list, &dev->qdisc_list); | ||
555 | } else { | ||
556 | qdisc = &noqueue_qdisc; | ||
557 | } | ||
558 | dev->qdisc_sleeping = qdisc; | ||
559 | } | ||
560 | 615 | ||
561 | if (!netif_carrier_ok(dev)) | 616 | if (!netif_carrier_ok(dev)) |
562 | /* Delay activation until next carrier-on event */ | 617 | /* Delay activation until next carrier-on event */ |
563 | return; | 618 | return; |
564 | 619 | ||
565 | spin_lock_bh(&dev->queue_lock); | 620 | need_watchdog = 0; |
566 | rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping); | 621 | netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog); |
567 | if (dev->qdisc != &noqueue_qdisc) { | 622 | |
623 | if (need_watchdog) { | ||
568 | dev->trans_start = jiffies; | 624 | dev->trans_start = jiffies; |
569 | dev_watchdog_up(dev); | 625 | dev_watchdog_up(dev); |
570 | } | 626 | } |
571 | spin_unlock_bh(&dev->queue_lock); | ||
572 | } | 627 | } |
573 | 628 | ||
574 | void dev_deactivate(struct net_device *dev) | 629 | static void dev_deactivate_queue(struct net_device *dev, |
630 | struct netdev_queue *dev_queue, | ||
631 | void *_qdisc_default) | ||
575 | { | 632 | { |
633 | struct Qdisc *qdisc_default = _qdisc_default; | ||
576 | struct Qdisc *qdisc; | 634 | struct Qdisc *qdisc; |
577 | struct sk_buff *skb; | ||
578 | int running; | ||
579 | 635 | ||
580 | spin_lock_bh(&dev->queue_lock); | 636 | qdisc = dev_queue->qdisc; |
581 | qdisc = dev->qdisc; | 637 | if (qdisc) { |
582 | dev->qdisc = &noop_qdisc; | 638 | spin_lock_bh(qdisc_lock(qdisc)); |
583 | 639 | ||
584 | qdisc_reset(qdisc); | 640 | dev_queue->qdisc = qdisc_default; |
641 | qdisc_reset(qdisc); | ||
585 | 642 | ||
586 | skb = dev->gso_skb; | 643 | spin_unlock_bh(qdisc_lock(qdisc)); |
587 | dev->gso_skb = NULL; | 644 | } |
588 | spin_unlock_bh(&dev->queue_lock); | 645 | } |
589 | 646 | ||
590 | kfree_skb(skb); | 647 | static bool some_qdisc_is_running(struct net_device *dev, int lock) |
648 | { | ||
649 | unsigned int i; | ||
650 | |||
651 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
652 | struct netdev_queue *dev_queue; | ||
653 | spinlock_t *root_lock; | ||
654 | struct Qdisc *q; | ||
655 | int val; | ||
656 | |||
657 | dev_queue = netdev_get_tx_queue(dev, i); | ||
658 | q = dev_queue->qdisc; | ||
659 | root_lock = qdisc_root_lock(q); | ||
660 | |||
661 | if (lock) | ||
662 | spin_lock_bh(root_lock); | ||
663 | |||
664 | val = test_bit(__QDISC_STATE_RUNNING, &q->state); | ||
665 | |||
666 | if (lock) | ||
667 | spin_unlock_bh(root_lock); | ||
668 | |||
669 | if (val) | ||
670 | return true; | ||
671 | } | ||
672 | return false; | ||
673 | } | ||
674 | |||
675 | void dev_deactivate(struct net_device *dev) | ||
676 | { | ||
677 | bool running; | ||
678 | |||
679 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); | ||
591 | 680 | ||
592 | dev_watchdog_down(dev); | 681 | dev_watchdog_down(dev); |
593 | 682 | ||
@@ -596,16 +685,14 @@ void dev_deactivate(struct net_device *dev) | |||
596 | 685 | ||
597 | /* Wait for outstanding qdisc_run calls. */ | 686 | /* Wait for outstanding qdisc_run calls. */ |
598 | do { | 687 | do { |
599 | while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state)) | 688 | while (some_qdisc_is_running(dev, 0)) |
600 | yield(); | 689 | yield(); |
601 | 690 | ||
602 | /* | 691 | /* |
603 | * Double-check inside queue lock to ensure that all effects | 692 | * Double-check inside queue lock to ensure that all effects |
604 | * of the queue run are visible when we return. | 693 | * of the queue run are visible when we return. |
605 | */ | 694 | */ |
606 | spin_lock_bh(&dev->queue_lock); | 695 | running = some_qdisc_is_running(dev, 1); |
607 | running = test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); | ||
608 | spin_unlock_bh(&dev->queue_lock); | ||
609 | 696 | ||
610 | /* | 697 | /* |
611 | * The running flag should never be set at this point because | 698 | * The running flag should never be set at this point because |
@@ -618,32 +705,46 @@ void dev_deactivate(struct net_device *dev) | |||
618 | } while (WARN_ON_ONCE(running)); | 705 | } while (WARN_ON_ONCE(running)); |
619 | } | 706 | } |
620 | 707 | ||
708 | static void dev_init_scheduler_queue(struct net_device *dev, | ||
709 | struct netdev_queue *dev_queue, | ||
710 | void *_qdisc) | ||
711 | { | ||
712 | struct Qdisc *qdisc = _qdisc; | ||
713 | |||
714 | dev_queue->qdisc = qdisc; | ||
715 | dev_queue->qdisc_sleeping = qdisc; | ||
716 | } | ||
717 | |||
621 | void dev_init_scheduler(struct net_device *dev) | 718 | void dev_init_scheduler(struct net_device *dev) |
622 | { | 719 | { |
623 | qdisc_lock_tree(dev); | 720 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); |
624 | dev->qdisc = &noop_qdisc; | 721 | dev_init_scheduler_queue(dev, &dev->rx_queue, NULL); |
625 | dev->qdisc_sleeping = &noop_qdisc; | ||
626 | INIT_LIST_HEAD(&dev->qdisc_list); | ||
627 | qdisc_unlock_tree(dev); | ||
628 | 722 | ||
629 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); | 723 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); |
630 | } | 724 | } |
631 | 725 | ||
632 | void dev_shutdown(struct net_device *dev) | 726 | static void shutdown_scheduler_queue(struct net_device *dev, |
727 | struct netdev_queue *dev_queue, | ||
728 | void *_qdisc_default) | ||
633 | { | 729 | { |
634 | struct Qdisc *qdisc; | 730 | struct Qdisc *qdisc = dev_queue->qdisc_sleeping; |
731 | struct Qdisc *qdisc_default = _qdisc_default; | ||
732 | |||
733 | if (qdisc) { | ||
734 | spinlock_t *root_lock = qdisc_root_lock(qdisc); | ||
735 | |||
736 | dev_queue->qdisc = qdisc_default; | ||
737 | dev_queue->qdisc_sleeping = qdisc_default; | ||
635 | 738 | ||
636 | qdisc_lock_tree(dev); | 739 | spin_lock(root_lock); |
637 | qdisc = dev->qdisc_sleeping; | ||
638 | dev->qdisc = &noop_qdisc; | ||
639 | dev->qdisc_sleeping = &noop_qdisc; | ||
640 | qdisc_destroy(qdisc); | ||
641 | #if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE) | ||
642 | if ((qdisc = dev->qdisc_ingress) != NULL) { | ||
643 | dev->qdisc_ingress = NULL; | ||
644 | qdisc_destroy(qdisc); | 740 | qdisc_destroy(qdisc); |
741 | spin_unlock(root_lock); | ||
645 | } | 742 | } |
646 | #endif | 743 | } |
744 | |||
745 | void dev_shutdown(struct net_device *dev) | ||
746 | { | ||
747 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); | ||
748 | shutdown_scheduler_queue(dev, &dev->rx_queue, NULL); | ||
647 | BUG_TRAP(!timer_pending(&dev->watchdog_timer)); | 749 | BUG_TRAP(!timer_pending(&dev->watchdog_timer)); |
648 | qdisc_unlock_tree(dev); | ||
649 | } | 750 | } |