blob: 1894eb72f6cf8ffc60761fed6de0251470cce630 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * net/sched/sch_generic.c Generic packet scheduler routines.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * Jamal Hadi Salim, <hadi@cyberus.ca> 990601
11 * - Ingress support
12 */
13
14#include <asm/uaccess.h>
15#include <asm/system.h>
16#include <linux/bitops.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/module.h>
18#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/sched.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/socket.h>
24#include <linux/sockios.h>
25#include <linux/in.h>
26#include <linux/errno.h>
27#include <linux/interrupt.h>
28#include <linux/netdevice.h>
29#include <linux/skbuff.h>
30#include <linux/rtnetlink.h>
31#include <linux/init.h>
32#include <linux/rcupdate.h>
33#include <linux/list.h>
34#include <net/sock.h>
35#include <net/pkt_sched.h>
36
37/* Main transmission queue. */
38
Patrick McHardy0463d4a2007-04-16 17:02:10 -070039/* Modifications to data participating in scheduling must be protected with
40 * dev->queue_lock spinlock.
41 *
42 * The idea is the following:
43 * - enqueue, dequeue are serialized via top level device
44 * spinlock dev->queue_lock.
45 * - updates to tree and tree walking are only done under the rtnl mutex.
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48void qdisc_lock_tree(struct net_device *dev)
49{
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 spin_lock_bh(&dev->queue_lock);
51}
52
53void qdisc_unlock_tree(struct net_device *dev)
54{
55 spin_unlock_bh(&dev->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056}
57
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090058/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 dev->queue_lock serializes queue accesses for this device
60 AND dev->qdisc pointer itself.
61
Herbert Xu932ff272006-06-09 12:20:56 -070062 netif_tx_lock serializes accesses to device driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Herbert Xu932ff272006-06-09 12:20:56 -070064 dev->queue_lock and netif_tx_lock are mutually exclusive,
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 if one is grabbed, another must be free.
66 */
67
68
69/* Kick device.
70 Note, that this procedure can be called by a watchdog timer, so that
71 we do not check dev->tbusy flag here.
72
73 Returns: 0 - queue is empty.
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +090074 >0 - queue is not empty, but throttled.
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 <0 - queue is not empty. Device is throttled, if dev->tbusy != 0.
76
77 NOTE: Called under dev->queue_lock with locally disabled BH.
78*/
79
Herbert Xu48d83322006-06-19 23:57:59 -070080static inline int qdisc_restart(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
82 struct Qdisc *q = dev->qdisc;
83 struct sk_buff *skb;
84
85 /* Dequeue packet */
Herbert Xuf6a78bf2006-06-22 02:57:17 -070086 if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 unsigned nolock = (dev->features & NETIF_F_LLTX);
Herbert Xuf6a78bf2006-06-22 02:57:17 -070088
89 dev->gso_skb = NULL;
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 /*
92 * When the driver has LLTX set it does its own locking
93 * in start_xmit. No need to add additional overhead by
94 * locking again. These checks are worth it because
95 * even uncongested locks can be quite expensive.
96 * The driver can do trylock like here too, in case
97 * of lock congestion it should return -1 and the packet
98 * will be requeued.
99 */
100 if (!nolock) {
Herbert Xu932ff272006-06-09 12:20:56 -0700101 if (!netif_tx_trylock(dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 collision:
103 /* So, someone grabbed the driver. */
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 /* It may be transient configuration error,
106 when hard_start_xmit() recurses. We detect
107 it by checking xmit owner and drop the
108 packet when deadloop is detected.
109 */
110 if (dev->xmit_lock_owner == smp_processor_id()) {
111 kfree_skb(skb);
112 if (net_ratelimit())
113 printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
114 return -1;
115 }
116 __get_cpu_var(netdev_rx_stat).cpu_collision++;
117 goto requeue;
118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 }
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 {
122 /* And release queue */
123 spin_unlock(&dev->queue_lock);
124
125 if (!netif_queue_stopped(dev)) {
126 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Herbert Xuf6a78bf2006-06-22 02:57:17 -0700128 ret = dev_hard_start_xmit(skb, dev);
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900129 if (ret == NETDEV_TX_OK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 if (!nolock) {
Herbert Xu932ff272006-06-09 12:20:56 -0700131 netif_tx_unlock(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 }
133 spin_lock(&dev->queue_lock);
134 return -1;
135 }
136 if (ret == NETDEV_TX_LOCKED && nolock) {
137 spin_lock(&dev->queue_lock);
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900138 goto collision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 }
140 }
141
142 /* NETDEV_TX_BUSY - we need to requeue */
143 /* Release the driver */
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900144 if (!nolock) {
Herbert Xu932ff272006-06-09 12:20:56 -0700145 netif_tx_unlock(dev);
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 spin_lock(&dev->queue_lock);
148 q = dev->qdisc;
149 }
150
151 /* Device kicked us out :(
152 This is possible in three cases:
153
154 0. driver is locked
155 1. fastroute is enabled
156 2. device cannot determine busy state
157 before start of transmission (f.e. dialout)
158 3. device is buggy (ppp)
159 */
160
161requeue:
Herbert Xuf6a78bf2006-06-22 02:57:17 -0700162 if (skb->next)
163 dev->gso_skb = skb;
164 else
165 q->ops->requeue(skb, q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 netif_schedule(dev);
167 return 1;
168 }
Stephen Hemminger8cbe1d42005-05-03 16:24:03 -0700169 BUG_ON((int) q->q.qlen < 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 return q->q.qlen;
171}
172
Herbert Xu48d83322006-06-19 23:57:59 -0700173void __qdisc_run(struct net_device *dev)
174{
Herbert Xud4828d82006-06-22 02:28:18 -0700175 if (unlikely(dev->qdisc == &noop_qdisc))
176 goto out;
177
Herbert Xu48d83322006-06-19 23:57:59 -0700178 while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
179 /* NOTHING */;
180
Herbert Xud4828d82006-06-22 02:28:18 -0700181out:
Herbert Xu48d83322006-06-19 23:57:59 -0700182 clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
183}
184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185static void dev_watchdog(unsigned long arg)
186{
187 struct net_device *dev = (struct net_device *)arg;
188
Herbert Xu932ff272006-06-09 12:20:56 -0700189 netif_tx_lock(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 if (dev->qdisc != &noop_qdisc) {
191 if (netif_device_present(dev) &&
192 netif_running(dev) &&
193 netif_carrier_ok(dev)) {
194 if (netif_queue_stopped(dev) &&
Stephen Hemminger338f7562006-05-16 15:02:12 -0700195 time_after(jiffies, dev->trans_start + dev->watchdog_timeo)) {
196
197 printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n",
198 dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 dev->tx_timeout(dev);
200 }
Arjan van de Venf5a6e012007-02-05 17:59:51 -0800201 if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 dev_hold(dev);
203 }
204 }
Herbert Xu932ff272006-06-09 12:20:56 -0700205 netif_tx_unlock(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 dev_put(dev);
208}
209
210static void dev_watchdog_init(struct net_device *dev)
211{
212 init_timer(&dev->watchdog_timer);
213 dev->watchdog_timer.data = (unsigned long)dev;
214 dev->watchdog_timer.function = dev_watchdog;
215}
216
217void __netdev_watchdog_up(struct net_device *dev)
218{
219 if (dev->tx_timeout) {
220 if (dev->watchdog_timeo <= 0)
221 dev->watchdog_timeo = 5*HZ;
222 if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
223 dev_hold(dev);
224 }
225}
226
227static void dev_watchdog_up(struct net_device *dev)
228{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 __netdev_watchdog_up(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230}
231
232static void dev_watchdog_down(struct net_device *dev)
233{
Herbert Xu932ff272006-06-09 12:20:56 -0700234 netif_tx_lock_bh(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 if (del_timer(&dev->watchdog_timer))
Stephen Hemminger15333062006-03-20 22:32:28 -0800236 dev_put(dev);
Herbert Xu932ff272006-06-09 12:20:56 -0700237 netif_tx_unlock_bh(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238}
239
Denis Vlasenko0a242ef2005-08-11 15:32:53 -0700240void netif_carrier_on(struct net_device *dev)
241{
242 if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
243 linkwatch_fire_event(dev);
244 if (netif_running(dev))
245 __netdev_watchdog_up(dev);
246}
247
248void netif_carrier_off(struct net_device *dev)
249{
250 if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state))
251 linkwatch_fire_event(dev);
252}
253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
255 under all circumstances. It is difficult to invent anything faster or
256 cheaper.
257 */
258
Thomas Graf94df1092005-06-18 22:59:08 -0700259static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
261 kfree_skb(skb);
262 return NET_XMIT_CN;
263}
264
Thomas Graf94df1092005-06-18 22:59:08 -0700265static struct sk_buff *noop_dequeue(struct Qdisc * qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
267 return NULL;
268}
269
Thomas Graf94df1092005-06-18 22:59:08 -0700270static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 if (net_ratelimit())
Thomas Graf94df1092005-06-18 22:59:08 -0700273 printk(KERN_DEBUG "%s deferred output. It is buggy.\n",
274 skb->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 kfree_skb(skb);
276 return NET_XMIT_CN;
277}
278
279struct Qdisc_ops noop_qdisc_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .id = "noop",
281 .priv_size = 0,
282 .enqueue = noop_enqueue,
283 .dequeue = noop_dequeue,
284 .requeue = noop_requeue,
285 .owner = THIS_MODULE,
286};
287
288struct Qdisc noop_qdisc = {
289 .enqueue = noop_enqueue,
290 .dequeue = noop_dequeue,
291 .flags = TCQ_F_BUILTIN,
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900292 .ops = &noop_qdisc_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 .list = LIST_HEAD_INIT(noop_qdisc.list),
294};
295
296static struct Qdisc_ops noqueue_qdisc_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 .id = "noqueue",
298 .priv_size = 0,
299 .enqueue = noop_enqueue,
300 .dequeue = noop_dequeue,
301 .requeue = noop_requeue,
302 .owner = THIS_MODULE,
303};
304
305static struct Qdisc noqueue_qdisc = {
306 .enqueue = NULL,
307 .dequeue = noop_dequeue,
308 .flags = TCQ_F_BUILTIN,
309 .ops = &noqueue_qdisc_ops,
310 .list = LIST_HEAD_INIT(noqueue_qdisc.list),
311};
312
313
314static const u8 prio2band[TC_PRIO_MAX+1] =
315 { 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
316
317/* 3-band FIFO queue: old style, but should be a bit faster than
318 generic prio+fifo combination.
319 */
320
Thomas Graff87a9c32005-06-18 22:58:53 -0700321#define PFIFO_FAST_BANDS 3
322
Thomas Graf321090e2005-06-18 22:58:35 -0700323static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
324 struct Qdisc *qdisc)
325{
326 struct sk_buff_head *list = qdisc_priv(qdisc);
327 return list + prio2band[skb->priority & TC_PRIO_MAX];
328}
329
Thomas Graff87a9c32005-06-18 22:58:53 -0700330static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331{
Thomas Graf321090e2005-06-18 22:58:35 -0700332 struct sk_buff_head *list = prio2list(skb, qdisc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Thomas Graf821d24a2005-06-18 22:58:15 -0700334 if (skb_queue_len(list) < qdisc->dev->tx_queue_len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 qdisc->q.qlen++;
Thomas Graf821d24a2005-06-18 22:58:15 -0700336 return __qdisc_enqueue_tail(skb, qdisc, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
Thomas Graf821d24a2005-06-18 22:58:15 -0700338
339 return qdisc_drop(skb, qdisc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340}
341
Thomas Graff87a9c32005-06-18 22:58:53 -0700342static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343{
344 int prio;
345 struct sk_buff_head *list = qdisc_priv(qdisc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Thomas Graf452f2992005-07-18 13:30:53 -0700347 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
348 if (!skb_queue_empty(list + prio)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 qdisc->q.qlen--;
Thomas Graf452f2992005-07-18 13:30:53 -0700350 return __qdisc_dequeue_head(qdisc, list + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
352 }
Thomas Graff87a9c32005-06-18 22:58:53 -0700353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 return NULL;
355}
356
Thomas Graff87a9c32005-06-18 22:58:53 -0700357static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 qdisc->q.qlen++;
Thomas Graf321090e2005-06-18 22:58:35 -0700360 return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361}
362
Thomas Graff87a9c32005-06-18 22:58:53 -0700363static void pfifo_fast_reset(struct Qdisc* qdisc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364{
365 int prio;
366 struct sk_buff_head *list = qdisc_priv(qdisc);
367
Thomas Graff87a9c32005-06-18 22:58:53 -0700368 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
Thomas Graf821d24a2005-06-18 22:58:15 -0700369 __qdisc_reset_queue(qdisc, list + prio);
370
371 qdisc->qstats.backlog = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 qdisc->q.qlen = 0;
373}
374
375static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
376{
Thomas Graff87a9c32005-06-18 22:58:53 -0700377 struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
380 RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
381 return skb->len;
382
383rtattr_failure:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 return -1;
385}
386
387static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
388{
Thomas Graff87a9c32005-06-18 22:58:53 -0700389 int prio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 struct sk_buff_head *list = qdisc_priv(qdisc);
391
Thomas Graff87a9c32005-06-18 22:58:53 -0700392 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
393 skb_queue_head_init(list + prio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
395 return 0;
396}
397
398static struct Qdisc_ops pfifo_fast_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 .id = "pfifo_fast",
Thomas Graff87a9c32005-06-18 22:58:53 -0700400 .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 .enqueue = pfifo_fast_enqueue,
402 .dequeue = pfifo_fast_dequeue,
403 .requeue = pfifo_fast_requeue,
404 .init = pfifo_fast_init,
405 .reset = pfifo_fast_reset,
406 .dump = pfifo_fast_dump,
407 .owner = THIS_MODULE,
408};
409
Thomas Graf3d54b822005-07-05 14:15:09 -0700410struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
412 void *p;
413 struct Qdisc *sch;
Thomas Graf3d54b822005-07-05 14:15:09 -0700414 unsigned int size;
415 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417 /* ensure that the Qdisc and the private data are 32-byte aligned */
Thomas Graf3d54b822005-07-05 14:15:09 -0700418 size = QDISC_ALIGN(sizeof(*sch));
419 size += ops->priv_size + (QDISC_ALIGNTO - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700421 p = kzalloc(size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 if (!p)
Thomas Graf3d54b822005-07-05 14:15:09 -0700423 goto errout;
Thomas Graf3d54b822005-07-05 14:15:09 -0700424 sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
425 sch->padded = (char *) sch - (char *) p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
427 INIT_LIST_HEAD(&sch->list);
428 skb_queue_head_init(&sch->q);
429 sch->ops = ops;
430 sch->enqueue = ops->enqueue;
431 sch->dequeue = ops->dequeue;
432 sch->dev = dev;
433 dev_hold(dev);
434 sch->stats_lock = &dev->queue_lock;
435 atomic_set(&sch->refcnt, 1);
Thomas Graf3d54b822005-07-05 14:15:09 -0700436
437 return sch;
438errout:
439 return ERR_PTR(-err);
440}
441
Patrick McHardy9f9afec2006-11-29 17:35:18 -0800442struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
443 unsigned int parentid)
Thomas Graf3d54b822005-07-05 14:15:09 -0700444{
445 struct Qdisc *sch;
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900446
Thomas Graf3d54b822005-07-05 14:15:09 -0700447 sch = qdisc_alloc(dev, ops);
448 if (IS_ERR(sch))
449 goto errout;
Patrick McHardy9f9afec2006-11-29 17:35:18 -0800450 sch->parent = parentid;
Thomas Graf3d54b822005-07-05 14:15:09 -0700451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 if (!ops->init || ops->init(sch, NULL) == 0)
453 return sch;
454
Thomas Graf0fbbeb12005-08-23 10:12:44 -0700455 qdisc_destroy(sch);
Thomas Graf3d54b822005-07-05 14:15:09 -0700456errout:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return NULL;
458}
459
460/* Under dev->queue_lock and BH! */
461
462void qdisc_reset(struct Qdisc *qdisc)
463{
464 struct Qdisc_ops *ops = qdisc->ops;
465
466 if (ops->reset)
467 ops->reset(qdisc);
468}
469
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900470/* this is the rcu callback function to clean up a qdisc when there
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 * are no further references to it */
472
473static void __qdisc_destroy(struct rcu_head *head)
474{
475 struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 kfree((char *) qdisc - qdisc->padded);
477}
478
479/* Under dev->queue_lock and BH! */
480
481void qdisc_destroy(struct Qdisc *qdisc)
482{
Patrick McHardy85670cc2006-09-27 16:45:45 -0700483 struct Qdisc_ops *ops = qdisc->ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 if (qdisc->flags & TCQ_F_BUILTIN ||
Patrick McHardy85670cc2006-09-27 16:45:45 -0700486 !atomic_dec_and_test(&qdisc->refcnt))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 return;
488
Patrick McHardy85670cc2006-09-27 16:45:45 -0700489 list_del(&qdisc->list);
490#ifdef CONFIG_NET_ESTIMATOR
491 gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
492#endif
493 if (ops->reset)
494 ops->reset(qdisc);
495 if (ops->destroy)
496 ops->destroy(qdisc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
Patrick McHardy85670cc2006-09-27 16:45:45 -0700498 module_put(ops->owner);
499 dev_put(qdisc->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 call_rcu(&qdisc->q_rcu, __qdisc_destroy);
501}
502
503void dev_activate(struct net_device *dev)
504{
505 /* No queueing discipline is attached to device;
506 create default one i.e. pfifo_fast for devices,
507 which need queueing and noqueue_qdisc for
508 virtual interfaces
509 */
510
511 if (dev->qdisc_sleeping == &noop_qdisc) {
512 struct Qdisc *qdisc;
513 if (dev->tx_queue_len) {
Patrick McHardy9f9afec2006-11-29 17:35:18 -0800514 qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops,
515 TC_H_ROOT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 if (qdisc == NULL) {
517 printk(KERN_INFO "%s: activation failed\n", dev->name);
518 return;
519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 list_add_tail(&qdisc->list, &dev->qdisc_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 } else {
522 qdisc = &noqueue_qdisc;
523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 dev->qdisc_sleeping = qdisc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 }
526
Tommy S. Christensencacaddf2005-05-03 16:18:52 -0700527 if (!netif_carrier_ok(dev))
528 /* Delay activation until next carrier-on event */
529 return;
530
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 spin_lock_bh(&dev->queue_lock);
532 rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping);
533 if (dev->qdisc != &noqueue_qdisc) {
534 dev->trans_start = jiffies;
535 dev_watchdog_up(dev);
536 }
537 spin_unlock_bh(&dev->queue_lock);
538}
539
540void dev_deactivate(struct net_device *dev)
541{
542 struct Qdisc *qdisc;
543
544 spin_lock_bh(&dev->queue_lock);
545 qdisc = dev->qdisc;
546 dev->qdisc = &noop_qdisc;
547
548 qdisc_reset(qdisc);
549
550 spin_unlock_bh(&dev->queue_lock);
551
552 dev_watchdog_down(dev);
553
Herbert Xud4828d82006-06-22 02:28:18 -0700554 /* Wait for outstanding dev_queue_xmit calls. */
555 synchronize_rcu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Herbert Xud4828d82006-06-22 02:28:18 -0700557 /* Wait for outstanding qdisc_run calls. */
558 while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
559 yield();
Herbert Xuf6a78bf2006-06-22 02:57:17 -0700560
561 if (dev->gso_skb) {
562 kfree_skb(dev->gso_skb);
563 dev->gso_skb = NULL;
564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565}
566
567void dev_init_scheduler(struct net_device *dev)
568{
569 qdisc_lock_tree(dev);
570 dev->qdisc = &noop_qdisc;
571 dev->qdisc_sleeping = &noop_qdisc;
572 INIT_LIST_HEAD(&dev->qdisc_list);
573 qdisc_unlock_tree(dev);
574
575 dev_watchdog_init(dev);
576}
577
578void dev_shutdown(struct net_device *dev)
579{
580 struct Qdisc *qdisc;
581
582 qdisc_lock_tree(dev);
583 qdisc = dev->qdisc_sleeping;
584 dev->qdisc = &noop_qdisc;
585 dev->qdisc_sleeping = &noop_qdisc;
586 qdisc_destroy(qdisc);
587#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900588 if ((qdisc = dev->qdisc_ingress) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 dev->qdisc_ingress = NULL;
590 qdisc_destroy(qdisc);
YOSHIFUJI Hideaki10297b92007-02-09 23:25:16 +0900591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592#endif
593 BUG_TRAP(!timer_pending(&dev->watchdog_timer));
594 qdisc_unlock_tree(dev);
595}
596
Denis Vlasenko0a242ef2005-08-11 15:32:53 -0700597EXPORT_SYMBOL(netif_carrier_on);
598EXPORT_SYMBOL(netif_carrier_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599EXPORT_SYMBOL(noop_qdisc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600EXPORT_SYMBOL(qdisc_create_dflt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601EXPORT_SYMBOL(qdisc_destroy);
602EXPORT_SYMBOL(qdisc_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603EXPORT_SYMBOL(qdisc_lock_tree);
604EXPORT_SYMBOL(qdisc_unlock_tree);