X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=net%2Fsched%2Fsch_fifo.c;h=23d258bfe8ace223e07d0c23dc62fbe7e0ae9faa;hb=80bba1290ab5122c60cdb73332b26d288dc8aedd;hp=c264308f17c1f66f6f7e6c61ca309fa5378f5645;hpb=2d896c780db9cda5dc102bf7a0a2cd4394c1342e;p=linux-2.6-omap-h63xx.git diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index c264308f17c..23d258bfe8a 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -27,7 +27,7 @@ static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct fifo_sched_data *q = qdisc_priv(sch); - if (likely(sch->qstats.backlog + skb->len <= q->limit)) + if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= q->limit)) return qdisc_enqueue_tail(skb, sch); return qdisc_reshape_fail(skb, sch); @@ -43,21 +43,21 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_reshape_fail(skb, sch); } -static int fifo_init(struct Qdisc *sch, struct rtattr *opt) +static int fifo_init(struct Qdisc *sch, struct nlattr *opt) { struct fifo_sched_data *q = qdisc_priv(sch); if (opt == NULL) { - u32 limit = sch->dev->tx_queue_len ? : 1; + u32 limit = qdisc_dev(sch)->tx_queue_len ? : 1; if (sch->ops == &bfifo_qdisc_ops) - limit *= sch->dev->mtu; + limit *= qdisc_dev(sch)->mtu; q->limit = limit; } else { - struct tc_fifo_qopt *ctl = RTA_DATA(opt); + struct tc_fifo_qopt *ctl = nla_data(opt); - if (RTA_PAYLOAD(opt) < sizeof(*ctl)) + if (nla_len(opt) < sizeof(*ctl)) return -EINVAL; q->limit = ctl->limit; @@ -71,14 +71,14 @@ static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) struct fifo_sched_data *q = qdisc_priv(sch); struct tc_fifo_qopt opt = { .limit = q->limit }; - RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); return skb->len; -rtattr_failure: +nla_put_failure: return -1; } -struct Qdisc_ops pfifo_qdisc_ops = { +struct Qdisc_ops pfifo_qdisc_ops __read_mostly = { .id = "pfifo", .priv_size = sizeof(struct fifo_sched_data), .enqueue = pfifo_enqueue, @@ -91,8 +91,9 @@ struct Qdisc_ops pfifo_qdisc_ops = { .dump = fifo_dump, .owner = THIS_MODULE, }; +EXPORT_SYMBOL(pfifo_qdisc_ops); -struct Qdisc_ops bfifo_qdisc_ops = { +struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { .id = "bfifo", .priv_size = sizeof(struct fifo_sched_data), .enqueue = bfifo_enqueue, @@ -105,6 +106,47 @@ struct Qdisc_ops bfifo_qdisc_ops = { .dump = fifo_dump, .owner = THIS_MODULE, }; - EXPORT_SYMBOL(bfifo_qdisc_ops); -EXPORT_SYMBOL(pfifo_qdisc_ops); + +/* Pass size change message down to embedded FIFO */ +int fifo_set_limit(struct Qdisc *q, unsigned int limit) +{ + struct nlattr *nla; + int ret = -ENOMEM; + + /* Hack to avoid sending change message to non-FIFO */ + if (strncmp(q->ops->id + 1, "fifo", 4) != 0) + return 0; + + nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); + if (nla) { + nla->nla_type = RTM_NEWQDISC; + nla->nla_len = nla_attr_size(sizeof(struct tc_fifo_qopt)); + ((struct tc_fifo_qopt *)nla_data(nla))->limit = limit; + + ret = q->ops->change(q, nla); + kfree(nla); + } + return ret; +} +EXPORT_SYMBOL(fifo_set_limit); + +struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, + unsigned int limit) +{ + struct Qdisc *q; + int err = -ENOMEM; + + q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, + ops, TC_H_MAKE(sch->handle, 1)); + if (q) { + err = fifo_set_limit(q, limit); + if (err < 0) { + qdisc_destroy(q); + q = NULL; + } + } + + return q ? : ERR_PTR(err); +} +EXPORT_SYMBOL(fifo_create_dflt);