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 | |
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')
-rw-r--r-- | net/sched/sch_drr.c | 91 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 75 |
2 files changed, 165 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, diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 4b056c15..4fe4ec1 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -97,6 +97,19 @@ changed the limit is not effective anymore. */ +#if defined(CONFIG_ASF_EGRESS_SHAPER) || defined(CONFIG_ASF_HW_SHAPER) +static inline void _tbf_add_hook(struct Qdisc *sch, + uint32_t rate, + uint32_t limit, + uint32_t buffer, + uint16_t mpu); +static inline void _tbf_del_hook(struct Qdisc *sch); + +/* Define ADD/DELETE Hooks */ +static tbf_add_hook *tbf_add_fn; +static tbf_del_hook *tbf_del_fn; +#endif + struct tbf_sched_data { /* Parameters */ u32 limit; /* Maximal length of backlog: bytes */ @@ -304,6 +317,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) sch_tree_unlock(sch); err = 0; +#if defined(CONFIG_ASF_EGRESS_SHAPER) || defined(CONFIG_ASF_HW_SHAPER) + _tbf_add_hook(sch, qopt->rate.rate, qopt->limit, + qopt->buffer, qopt->rate.mpu); +#endif + done: if (rtab) qdisc_put_rtab(rtab); @@ -338,6 +356,9 @@ static void tbf_destroy(struct Qdisc *sch) qdisc_put_rtab(q->R_tab); qdisc_destroy(q->qdisc); +#if defined(CONFIG_ASF_EGRESS_SHAPER) || defined(CONFIG_ASF_HW_SHAPER) + _tbf_del_hook(sch); +#endif } static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) @@ -426,6 +447,60 @@ static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker) } } +#if defined(CONFIG_ASF_EGRESS_SHAPER) || defined(CONFIG_ASF_HW_SHAPER) +static inline void _tbf_add_hook(struct Qdisc *sch, + uint32_t rate, + uint32_t limit, + uint32_t buffer, + uint16_t mpu +) +{ + if (tbf_add_fn) { + struct tbf_opt opt; + + opt.dev = qdisc_dev(sch); + opt.handle = sch->handle; + opt.parent = sch->parent; + opt.rate = rate; + opt.limit = limit; + opt.buffer = buffer; + opt.mpu = mpu; + + if (tbf_add_fn(&opt) < 0) { + printk(KERN_DEBUG "%s: TBF Creation on %s: fail: handle 0x%X\n", + __func__, opt.dev->name, sch->handle); + } + } +} + +static inline void _tbf_del_hook(struct Qdisc *sch) +{ + + if (tbf_del_fn) { + struct net_device *dev = qdisc_dev(sch); + + if (tbf_del_fn(dev, sch->handle, sch->parent) < 0) { + printk(KERN_DEBUG "%s: TBF Qdisc DEL on %s: fail: handle 0x%X\n", + __func__, dev->name, sch->handle); + } + } +} +struct Qdisc *tbf_get_inner_qdisc(struct Qdisc *sch) +{ + struct tbf_sched_data *q = qdisc_priv(sch); + return q->qdisc; +} +EXPORT_SYMBOL(tbf_get_inner_qdisc); + +void tbf_hook_fn_register(tbf_add_hook *add, + tbf_del_hook *del) +{ + tbf_add_fn = add; + tbf_del_fn = del; +} +EXPORT_SYMBOL(tbf_hook_fn_register); +#endif + static const struct Qdisc_class_ops tbf_class_ops = { .graft = tbf_graft, .leaf = tbf_leaf, |