OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [sched/] [sch_generic.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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 <asm/bitops.h>
17
#include <linux/config.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 <net/sock.h>
33
#include <net/pkt_sched.h>
34
 
35
/* Main transmission queue. */
36
 
37
/* Main qdisc structure lock.
38
 
39
   However, modifications
40
   to data, participating in scheduling must be additionally
41
   protected with dev->queue_lock spinlock.
42
 
43
   The idea is the following:
44
   - enqueue, dequeue are serialized via top level device
45
     spinlock dev->queue_lock.
46
   - tree walking is protected by read_lock(qdisc_tree_lock)
47
     and this lock is used only in process context.
48
   - updates to tree are made only under rtnl semaphore,
49
     hence this lock may be made without local bh disabling.
50
 
51
   qdisc_tree_lock must be grabbed BEFORE dev->queue_lock!
52
 */
53
rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED;
54
 
55
/*
56
   dev->queue_lock serializes queue accesses for this device
57
   AND dev->qdisc pointer itself.
58
 
59
   dev->xmit_lock serializes accesses to device driver.
60
 
61
   dev->queue_lock and dev->xmit_lock are mutually exclusive,
62
   if one is grabbed, another must be free.
63
 */
64
 
65
 
66
/* Kick device.
67
   Note, that this procedure can be called by a watchdog timer, so that
68
   we do not check dev->tbusy flag here.
69
 
70
   Returns:  0  - queue is empty.
71
            >0  - queue is not empty, but throttled.
72
            <0  - queue is not empty. Device is throttled, if dev->tbusy != 0.
73
 
74
   NOTE: Called under dev->queue_lock with locally disabled BH.
75
*/
76
 
77
int qdisc_restart(struct net_device *dev)
78
{
79
        struct Qdisc *q = dev->qdisc;
80
        struct sk_buff *skb;
81
 
82
        /* Dequeue packet */
83
        if ((skb = q->dequeue(q)) != NULL) {
84
                if (spin_trylock(&dev->xmit_lock)) {
85
                        /* Remember that the driver is grabbed by us. */
86
                        dev->xmit_lock_owner = smp_processor_id();
87
 
88
                        /* And release queue */
89
                        spin_unlock(&dev->queue_lock);
90
 
91
                        if (!netif_queue_stopped(dev)) {
92
                                if (netdev_nit)
93
                                        dev_queue_xmit_nit(skb, dev);
94
 
95
                                if (dev->hard_start_xmit(skb, dev) == 0) {
96
                                        dev->xmit_lock_owner = -1;
97
                                        spin_unlock(&dev->xmit_lock);
98
 
99
                                        spin_lock(&dev->queue_lock);
100
                                        return -1;
101
                                }
102
                        }
103
 
104
                        /* Release the driver */
105
                        dev->xmit_lock_owner = -1;
106
                        spin_unlock(&dev->xmit_lock);
107
                        spin_lock(&dev->queue_lock);
108
                        q = dev->qdisc;
109
                } else {
110
                        /* So, someone grabbed the driver. */
111
 
112
                        /* It may be transient configuration error,
113
                           when hard_start_xmit() recurses. We detect
114
                           it by checking xmit owner and drop the
115
                           packet when deadloop is detected.
116
                         */
117
                        if (dev->xmit_lock_owner == smp_processor_id()) {
118
                                kfree_skb(skb);
119
                                if (net_ratelimit())
120
                                        printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
121
                                return -1;
122
                        }
123
                        netdev_rx_stat[smp_processor_id()].cpu_collision++;
124
                }
125
 
126
                /* Device kicked us out :(
127
                   This is possible in three cases:
128
 
129
                   0. driver is locked
130
                   1. fastroute is enabled
131
                   2. device cannot determine busy state
132
                      before start of transmission (f.e. dialout)
133
                   3. device is buggy (ppp)
134
                 */
135
 
136
                q->ops->requeue(skb, q);
137
                netif_schedule(dev);
138
                return 1;
139
        }
140
        return q->q.qlen;
141
}
142
 
143
static void dev_watchdog(unsigned long arg)
144
{
145
        struct net_device *dev = (struct net_device *)arg;
146
 
147
        spin_lock(&dev->xmit_lock);
148
        if (dev->qdisc != &noop_qdisc) {
149
                if (netif_device_present(dev) &&
150
                    netif_running(dev) &&
151
                    netif_carrier_ok(dev)) {
152
                        if (netif_queue_stopped(dev) &&
153
                            (jiffies - dev->trans_start) > dev->watchdog_timeo) {
154
                                printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", dev->name);
155
                                dev->tx_timeout(dev);
156
                        }
157
                        if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
158
                                dev_hold(dev);
159
                }
160
        }
161
        spin_unlock(&dev->xmit_lock);
162
 
163
        dev_put(dev);
164
}
165
 
166
static void dev_watchdog_init(struct net_device *dev)
167
{
168
        init_timer(&dev->watchdog_timer);
169
        dev->watchdog_timer.data = (unsigned long)dev;
170
        dev->watchdog_timer.function = dev_watchdog;
171
}
172
 
173
void __netdev_watchdog_up(struct net_device *dev)
174
{
175
        if (dev->tx_timeout) {
176
                if (dev->watchdog_timeo <= 0)
177
                        dev->watchdog_timeo = 5*HZ;
178
                if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
179
                        dev_hold(dev);
180
        }
181
}
182
 
183
static void dev_watchdog_up(struct net_device *dev)
184
{
185
        spin_lock_bh(&dev->xmit_lock);
186
        __netdev_watchdog_up(dev);
187
        spin_unlock_bh(&dev->xmit_lock);
188
}
189
 
190
static void dev_watchdog_down(struct net_device *dev)
191
{
192
        spin_lock_bh(&dev->xmit_lock);
193
        if (del_timer(&dev->watchdog_timer))
194
                __dev_put(dev);
195
        spin_unlock_bh(&dev->xmit_lock);
196
}
197
 
198
/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
199
   under all circumstances. It is difficult to invent anything faster or
200
   cheaper.
201
 */
202
 
203
static int
204
noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
205
{
206
        kfree_skb(skb);
207
        return NET_XMIT_CN;
208
}
209
 
210
static struct sk_buff *
211
noop_dequeue(struct Qdisc * qdisc)
212
{
213
        return NULL;
214
}
215
 
216
static int
217
noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
218
{
219
        if (net_ratelimit())
220
                printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
221
        kfree_skb(skb);
222
        return NET_XMIT_CN;
223
}
224
 
225
struct Qdisc_ops noop_qdisc_ops =
226
{
227
        NULL,
228
        NULL,
229
        "noop",
230
        0,
231
 
232
        noop_enqueue,
233
        noop_dequeue,
234
        noop_requeue,
235
};
236
 
237
struct Qdisc noop_qdisc =
238
{
239
        noop_enqueue,
240
        noop_dequeue,
241
        TCQ_F_BUILTIN,
242
        &noop_qdisc_ops,
243
};
244
 
245
 
246
struct Qdisc_ops noqueue_qdisc_ops =
247
{
248
        NULL,
249
        NULL,
250
        "noqueue",
251
        0,
252
 
253
        noop_enqueue,
254
        noop_dequeue,
255
        noop_requeue,
256
 
257
};
258
 
259
struct Qdisc noqueue_qdisc =
260
{
261
        NULL,
262
        noop_dequeue,
263
        TCQ_F_BUILTIN,
264
        &noqueue_qdisc_ops,
265
};
266
 
267
 
268
static const u8 prio2band[TC_PRIO_MAX+1] =
269
{ 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
270
 
271
/* 3-band FIFO queue: old style, but should be a bit faster than
272
   generic prio+fifo combination.
273
 */
274
 
275
static int
276
pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
277
{
278
        struct sk_buff_head *list;
279
 
280
        list = ((struct sk_buff_head*)qdisc->data) +
281
                prio2band[skb->priority&TC_PRIO_MAX];
282
 
283
        if (list->qlen < qdisc->dev->tx_queue_len) {
284
                __skb_queue_tail(list, skb);
285
                qdisc->q.qlen++;
286
                qdisc->stats.bytes += skb->len;
287
                qdisc->stats.packets++;
288
                return 0;
289
        }
290
        qdisc->stats.drops++;
291
        kfree_skb(skb);
292
        return NET_XMIT_DROP;
293
}
294
 
295
static struct sk_buff *
296
pfifo_fast_dequeue(struct Qdisc* qdisc)
297
{
298
        int prio;
299
        struct sk_buff_head *list = ((struct sk_buff_head*)qdisc->data);
300
        struct sk_buff *skb;
301
 
302
        for (prio = 0; prio < 3; prio++, list++) {
303
                skb = __skb_dequeue(list);
304
                if (skb) {
305
                        qdisc->q.qlen--;
306
                        return skb;
307
                }
308
        }
309
        return NULL;
310
}
311
 
312
static int
313
pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
314
{
315
        struct sk_buff_head *list;
316
 
317
        list = ((struct sk_buff_head*)qdisc->data) +
318
                prio2band[skb->priority&TC_PRIO_MAX];
319
 
320
        __skb_queue_head(list, skb);
321
        qdisc->q.qlen++;
322
        return 0;
323
}
324
 
325
static void
326
pfifo_fast_reset(struct Qdisc* qdisc)
327
{
328
        int prio;
329
        struct sk_buff_head *list = ((struct sk_buff_head*)qdisc->data);
330
 
331
        for (prio=0; prio < 3; prio++)
332
                skb_queue_purge(list+prio);
333
        qdisc->q.qlen = 0;
334
}
335
 
336
static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
337
{
338
        unsigned char    *b = skb->tail;
339
        struct tc_prio_qopt opt;
340
 
341
        opt.bands = 3;
342
        memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
343
        RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
344
        return skb->len;
345
 
346
rtattr_failure:
347
        skb_trim(skb, b - skb->data);
348
        return -1;
349
}
350
 
351
static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
352
{
353
        int i;
354
        struct sk_buff_head *list;
355
 
356
        list = ((struct sk_buff_head*)qdisc->data);
357
 
358
        for (i=0; i<3; i++)
359
                skb_queue_head_init(list+i);
360
 
361
        return 0;
362
}
363
 
364
static struct Qdisc_ops pfifo_fast_ops =
365
{
366
        NULL,
367
        NULL,
368
        "pfifo_fast",
369
        3 * sizeof(struct sk_buff_head),
370
 
371
        pfifo_fast_enqueue,
372
        pfifo_fast_dequeue,
373
        pfifo_fast_requeue,
374
        NULL,
375
 
376
        pfifo_fast_init,
377
        pfifo_fast_reset,
378
        NULL,
379
        NULL,
380
        pfifo_fast_dump,
381
 
382
};
383
 
384
struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
385
{
386
        struct Qdisc *sch;
387
        int size = sizeof(*sch) + ops->priv_size;
388
 
389
        sch = kmalloc(size, GFP_KERNEL);
390
        if (!sch)
391
                return NULL;
392
        memset(sch, 0, size);
393
 
394
        skb_queue_head_init(&sch->q);
395
        sch->ops = ops;
396
        sch->enqueue = ops->enqueue;
397
        sch->dequeue = ops->dequeue;
398
        sch->dev = dev;
399
        sch->stats.lock = &dev->queue_lock;
400
        atomic_set(&sch->refcnt, 1);
401
        if (!ops->init || ops->init(sch, NULL) == 0)
402
                return sch;
403
 
404
        kfree(sch);
405
        return NULL;
406
}
407
 
408
/* Under dev->queue_lock and BH! */
409
 
410
void qdisc_reset(struct Qdisc *qdisc)
411
{
412
        struct Qdisc_ops *ops = qdisc->ops;
413
 
414
        if (ops->reset)
415
                ops->reset(qdisc);
416
}
417
 
418
/* Under dev->queue_lock and BH! */
419
 
420
void qdisc_destroy(struct Qdisc *qdisc)
421
{
422
        struct Qdisc_ops *ops = qdisc->ops;
423
        struct net_device *dev;
424
 
425
        if (!atomic_dec_and_test(&qdisc->refcnt))
426
                return;
427
 
428
        dev = qdisc->dev;
429
 
430
        if (dev) {
431
                struct Qdisc *q, **qp;
432
                for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
433
                        if (q == qdisc) {
434
                                *qp = q->next;
435
                                break;
436
                        }
437
                }
438
        }
439
#ifdef CONFIG_NET_ESTIMATOR
440
        qdisc_kill_estimator(&qdisc->stats);
441
#endif
442
        if (ops->reset)
443
                ops->reset(qdisc);
444
        if (ops->destroy)
445
                ops->destroy(qdisc);
446
        if (!(qdisc->flags&TCQ_F_BUILTIN))
447
                kfree(qdisc);
448
}
449
 
450
 
451
void dev_activate(struct net_device *dev)
452
{
453
        /* No queueing discipline is attached to device;
454
           create default one i.e. pfifo_fast for devices,
455
           which need queueing and noqueue_qdisc for
456
           virtual interfaces
457
         */
458
 
459
        if (dev->qdisc_sleeping == &noop_qdisc) {
460
                struct Qdisc *qdisc;
461
                if (dev->tx_queue_len) {
462
                        qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops);
463
                        if (qdisc == NULL) {
464
                                printk(KERN_INFO "%s: activation failed\n", dev->name);
465
                                return;
466
                        }
467
 
468
                        write_lock(&qdisc_tree_lock);
469
                        qdisc->next = dev->qdisc_list;
470
                        dev->qdisc_list = qdisc;
471
                        write_unlock(&qdisc_tree_lock);
472
 
473
                } else {
474
                        qdisc =  &noqueue_qdisc;
475
                }
476
                write_lock(&qdisc_tree_lock);
477
                dev->qdisc_sleeping = qdisc;
478
                write_unlock(&qdisc_tree_lock);
479
        }
480
 
481
        spin_lock_bh(&dev->queue_lock);
482
        if ((dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc) {
483
                dev->trans_start = jiffies;
484
                dev_watchdog_up(dev);
485
        }
486
        spin_unlock_bh(&dev->queue_lock);
487
}
488
 
489
void dev_deactivate(struct net_device *dev)
490
{
491
        struct Qdisc *qdisc;
492
 
493
        spin_lock_bh(&dev->queue_lock);
494
        qdisc = dev->qdisc;
495
        dev->qdisc = &noop_qdisc;
496
 
497
        qdisc_reset(qdisc);
498
 
499
        spin_unlock_bh(&dev->queue_lock);
500
 
501
        dev_watchdog_down(dev);
502
 
503
        while (test_bit(__LINK_STATE_SCHED, &dev->state))
504
                yield();
505
 
506
        spin_unlock_wait(&dev->xmit_lock);
507
}
508
 
509
void dev_init_scheduler(struct net_device *dev)
510
{
511
        write_lock(&qdisc_tree_lock);
512
        spin_lock_bh(&dev->queue_lock);
513
        dev->qdisc = &noop_qdisc;
514
        spin_unlock_bh(&dev->queue_lock);
515
        dev->qdisc_sleeping = &noop_qdisc;
516
        dev->qdisc_list = NULL;
517
        write_unlock(&qdisc_tree_lock);
518
 
519
        dev_watchdog_init(dev);
520
}
521
 
522
void dev_shutdown(struct net_device *dev)
523
{
524
        struct Qdisc *qdisc;
525
 
526
        write_lock(&qdisc_tree_lock);
527
        spin_lock_bh(&dev->queue_lock);
528
        qdisc = dev->qdisc_sleeping;
529
        dev->qdisc = &noop_qdisc;
530
        dev->qdisc_sleeping = &noop_qdisc;
531
        qdisc_destroy(qdisc);
532
#if defined(CONFIG_NET_SCH_INGRESS) || defined(CONFIG_NET_SCH_INGRESS_MODULE)
533
        if ((qdisc = dev->qdisc_ingress) != NULL) {
534
                dev->qdisc_ingress = NULL;
535
                qdisc_destroy(qdisc);
536
        }
537
#endif
538
        BUG_TRAP(dev->qdisc_list == NULL);
539
        BUG_TRAP(!timer_pending(&dev->watchdog_timer));
540
        dev->qdisc_list = NULL;
541
        spin_unlock_bh(&dev->queue_lock);
542
        write_unlock(&qdisc_tree_lock);
543
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.