summaryrefslogtreecommitdiff
path: root/net/sched
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
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')
-rw-r--r--net/sched/sch_drr.c91
-rw-r--r--net/sched/sch_tbf.c75
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,