diff options
author | Sachin Saxena <sachin.saxena@freescale.com> | 2013-04-12 09:38:48 (GMT) |
---|---|---|
committer | Fleming Andrew-AFLEMING <AFLEMING@freescale.com> | 2013-04-16 22:41:04 (GMT) |
commit | 8507cb00e53316b71d6acc2bc1616c190c487e36 (patch) | |
tree | 7b7589638a295f0c4f5af3023a17210726968988 /net/sched/sch_drr.c | |
parent | 2559f18bc5045d73e120556d4127496407125a25 (diff) | |
download | linux-fsl-qoriq-8507cb00e53316b71d6acc2bc1616c190c487e36.tar.xz |
ASF QoS Configuration intergrated with TC module.
Signed-off-by: Sachin Saxena <sachin.saxena@freescale.com>
CQ ID : ENGR00253307
Change-Id: I7441da8faab12440b51604e6c1d00bccc17a37e5
Reviewed-on: http://git.am.freescale.net:8181/1347
Reviewed-by: Gupta Rajan-B15745 <rajan.gupta@freescale.com>
Tested-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Reviewed-by: Fleming Andrew-AFLEMING <AFLEMING@freescale.com>
Diffstat (limited to 'net/sched/sch_drr.c')
-rw-r--r-- | net/sched/sch_drr.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 71e50c8..31e86c0 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -18,6 +18,18 @@ #include <net/pkt_sched.h> #include <net/pkt_cls.h> +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) +static inline void _drr_add_hook(struct Qdisc *sch, + uint32_t classid, + uint32_t quantum); +static inline void _drr_flush_hook(struct Qdisc *sch); + +/* Define ADD/DELETE Hooks */ +static drr_add_hook *drr_add_fn; +static drr_flush_hook *drr_flush_fn; +static invalidate_flows *drr_invalidate; +#endif + struct drr_class { struct Qdisc_class_common common; unsigned int refcnt; @@ -201,7 +213,10 @@ static unsigned long drr_bind_tcf(struct Qdisc *sch, unsigned long parent, if (cl != NULL) cl->filter_cnt++; - +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) + if (drr_invalidate) + drr_invalidate(); +#endif return (unsigned long)cl; } @@ -210,6 +225,10 @@ static void drr_unbind_tcf(struct Qdisc *sch, unsigned long arg) struct drr_class *cl = (struct drr_class *)arg; cl->filter_cnt--; +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) + if (drr_invalidate) + drr_invalidate(); +#endif } static int drr_graft_class(struct Qdisc *sch, unsigned long arg, @@ -262,6 +281,9 @@ static int drr_dump_class(struct Qdisc *sch, unsigned long arg, goto nla_put_failure; if (nla_put_u32(skb, TCA_DRR_QUANTUM, cl->quantum)) goto nla_put_failure; +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) + _drr_add_hook(sch, cl->common.classid, cl->quantum); +#endif return nla_nest_end(skb, nest); nla_put_failure: @@ -443,6 +465,9 @@ static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt) err = qdisc_class_hash_init(&q->clhash); if (err < 0) return err; +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) + _drr_add_hook(sch, 0, 0); +#endif INIT_LIST_HEAD(&q->active); return 0; } @@ -479,7 +504,71 @@ static void drr_destroy_qdisc(struct Qdisc *sch) drr_destroy_class(sch, cl); } qdisc_class_hash_destroy(&q->clhash); +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) + _drr_flush_hook(sch); +#endif +} + +#if defined(CONFIG_ASF_EGRESS_SCH) || defined(CONFIG_ASF_HW_SCH) +static inline void _drr_add_hook( + struct Qdisc *sch, + uint32_t classid, + uint32_t quantum) +{ + int ret; + + if (drr_add_fn) { + struct net_device *dev = qdisc_dev(sch); + + if (classid) + ret = drr_add_fn(dev, classid, sch->handle, quantum); + else + ret = drr_add_fn(dev, sch->handle, sch->parent, 0); + + if (ret < 0) + printk(KERN_DEBUG "%s: DRR Creation on %s:" + " fail: handle 0x%X\n", + __func__, dev->name, sch->handle); + } +} + +static inline void _drr_flush_hook(struct Qdisc *sch) +{ + + if (drr_flush_fn) { + struct net_device *dev = qdisc_dev(sch); + + if (drr_flush_fn(dev, sch->handle, sch->parent) < 0) { + printk(KERN_DEBUG "%s: DRR Fush on %s: fail: handle 0x%X\n", + __func__, dev->name, sch->handle); + } + } +} + +u32 drr_filter_lookup(struct sk_buff *skb, struct Qdisc *sch) +{ + struct drr_class *cl; + int err; + + cl = drr_classify(skb, sch, &err); + if (cl == NULL) { + /* Rule not found, must DROP */ + return 0; + } + return cl->common.classid; } +EXPORT_SYMBOL(drr_filter_lookup); + +void drr_hook_fn_register(drr_add_hook *add, + drr_flush_hook *flush, + invalidate_flows *invalidate) +{ + drr_add_fn = add; + drr_flush_fn = flush; + drr_invalidate = invalidate; +} +EXPORT_SYMBOL(drr_hook_fn_register); +#endif static const struct Qdisc_class_ops drr_class_ops = { .change = drr_change_class, |