summaryrefslogtreecommitdiff
path: root/net/sched/sch_drr.c
diff options
context:
space:
mode:
authorSachin Saxena <sachin.saxena@freescale.com>2013-04-12 09:38:48 (GMT)
committerFleming Andrew-AFLEMING <AFLEMING@freescale.com>2013-04-16 22:41:04 (GMT)
commit8507cb00e53316b71d6acc2bc1616c190c487e36 (patch)
tree7b7589638a295f0c4f5af3023a17210726968988 /net/sched/sch_drr.c
parent2559f18bc5045d73e120556d4127496407125a25 (diff)
downloadlinux-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.c91
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,