[NET_SCHED]: Use ktime as clocksource
[deliverable/linux.git] / net / sched / sch_hfsc.c
index 6a6735a2ed355b9640e654b28a5ecb96f69906e8..f85cfba647f85ec2b12b2519dae8d87011543001 100644 (file)
@@ -71,8 +71,6 @@
 #include <asm/system.h>
 #include <asm/div64.h>
 
-#define HFSC_DEBUG 1
-
 /*
  * kernel internal service curve representation:
  *   coordinates are given by 64 bit unsigned integers.
@@ -197,31 +195,6 @@ struct hfsc_sched
        struct timer_list wd_timer;             /* watchdog timer */
 };
 
-/*
- * macros
- */
-#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
-#include <linux/time.h>
-#undef PSCHED_GET_TIME
-#define PSCHED_GET_TIME(stamp)                                         \
-do {                                                                   \
-       struct timeval tv;                                              \
-       do_gettimeofday(&tv);                                           \
-       (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec;         \
-} while (0)
-#endif
-
-#if HFSC_DEBUG
-#define ASSERT(cond)                                                   \
-do {                                                                   \
-       if (unlikely(!(cond)))                                          \
-               printk("assertion %s failed at %s:%i (%s)\n",           \
-                      #cond, __FILE__, __LINE__, __FUNCTION__);        \
-} while (0)
-#else
-#define ASSERT(cond)
-#endif /* HFSC_DEBUG */
-
 #define        HT_INFINITY     0xffffffffffffffffULL   /* infinite time value */
 
 
@@ -284,7 +257,7 @@ static inline struct hfsc_class *
 eltree_get_minel(struct hfsc_sched *q)
 {
        struct rb_node *n;
-       
+
        n = rb_first(&q->eligible);
        if (n == NULL)
                return NULL;
@@ -407,28 +380,17 @@ cftree_update(struct hfsc_class *cl)
  *     ism: (psched_us/byte) << ISM_SHIFT
  *     dx: psched_us
  *
- * Clock source resolution (CONFIG_NET_SCH_CLK_*)
- *  JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us.
- *  CPU: resolution is between 0.5us and 1us.
- *  GETTIMEOFDAY: resolution is exactly 1us.
+ * The clock source resolution with ktime is 1.024us.
  *
  * sm and ism are scaled in order to keep effective digits.
  * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective
  * digits in decimal using the following table.
  *
- * Note: We can afford the additional accuracy (altq hfsc keeps at most
- * 3 effective digits) thanks to the fact that linux clock is bounded
- * much more tightly.
- *
  *  bits/sec      100Kbps     1Mbps     10Mbps     100Mbps    1Gbps
  *  ------------+-------------------------------------------------------
- *  bytes/0.5us   6.25e-3    62.5e-3    625e-3     6250e-e    62500e-3
- *  bytes/us      12.5e-3    125e-3     1250e-3    12500e-3   125000e-3
- *  bytes/1.27us  15.875e-3  158.75e-3  1587.5e-3  15875e-3   158750e-3
+ *  bytes/1.024us 12.8e-3    128e-3     1280e-3    12800e-3   128000e-3
  *
- *  0.5us/byte    160        16         1.6        0.16       0.016
- *  us/byte       80         8          0.8        0.08       0.008
- *  1.27us/byte   63         6.3        0.63       0.063      0.0063
+ *  1.024us/byte  78.125     7.8125     0.78125    0.078125   0.0078125
  */
 #define        SM_SHIFT        20
 #define        ISM_SHIFT       18
@@ -773,7 +735,7 @@ init_vf(struct hfsc_class *cl, unsigned int len)
                        /* update the virtual curve */
                        vt = cl->cl_vt + cl->cl_vtoff;
                        rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
-                                                     cl->cl_total);
+                                                     cl->cl_total);
                        if (cl->cl_virtual.x == vt) {
                                cl->cl_virtual.x -= cl->cl_vtoff;
                                cl->cl_vtoff = 0;
@@ -796,10 +758,10 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 
                                /* update the ulimit curve */
                                rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
-                                        cl->cl_total);
+                                        cl->cl_total);
                                /* compute myf */
                                cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
-                                                     cl->cl_total);
+                                                     cl->cl_total);
                                cl->cl_myfadj = 0;
                        }
                }
@@ -853,7 +815,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
                 * update vt and f
                 */
                cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
-                           - cl->cl_vtoff + cl->cl_vtadj;
+                           - cl->cl_vtoff + cl->cl_vtadj;
 
                /*
                 * if vt of the class is smaller than cvtmin,
@@ -870,7 +832,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
 
                if (cl->cl_flags & HFSC_USC) {
                        cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
-                                                             cl->cl_total);
+                                                             cl->cl_total);
 #if 0
                        /*
                         * This code causes classes to stay way under their
@@ -946,6 +908,7 @@ qdisc_peek_len(struct Qdisc *sch)
        if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
                if (net_ratelimit())
                        printk("qdisc_peek_len: failed to requeue\n");
+               qdisc_tree_decrease_qlen(sch, 1);
                return 0;
        }
        return len;
@@ -957,11 +920,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
        unsigned int len = cl->qdisc->q.qlen;
 
        qdisc_reset(cl->qdisc);
-       if (len > 0) {
-               update_vf(cl, 0, 0);
-               set_passive(cl);
-               sch->q.qlen -= len;
-       }
+       qdisc_tree_decrease_qlen(cl->qdisc, len);
 }
 
 static void
@@ -1004,7 +963,7 @@ hfsc_find_class(u32 classid, struct Qdisc *sch)
 
 static void
 hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc,
-                u64 cur_time)
+               u64 cur_time)
 {
        sc2isc(rsc, &cl->cl_rsc);
        rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
@@ -1026,7 +985,7 @@ hfsc_change_fsc(struct hfsc_class *cl, struct tc_service_curve *fsc)
 
 static void
 hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
-                u64 cur_time)
+               u64 cur_time)
 {
        sc2isc(usc, &cl->cl_usc);
        rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total);
@@ -1035,7 +994,7 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
 
 static int
 hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
-                  struct rtattr **tca, unsigned long *arg)
+                 struct rtattr **tca, unsigned long *arg)
 {
        struct hfsc_sched *q = qdisc_priv(sch);
        struct hfsc_class *cl = (struct hfsc_class *)*arg;
@@ -1138,7 +1097,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        cl->classid   = classid;
        cl->sched     = q;
        cl->cl_parent = parent;
-       cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
        cl->stats_lock = &sch->dev->queue_lock;
@@ -1200,10 +1159,12 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
 
        sch_tree_lock(sch);
 
-       list_del(&cl->hlist);
        list_del(&cl->siblings);
        hfsc_adjust_levels(cl->cl_parent);
+
        hfsc_purge_queue(sch, cl);
+       list_del(&cl->hlist);
+
        if (--cl->refcnt == 0)
                hfsc_destroy_class(sch, cl);
 
@@ -1231,9 +1192,9 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
                case TC_ACT_QUEUED:
-               case TC_ACT_STOLEN: 
+               case TC_ACT_STOLEN:
                        *qerr = NET_XMIT_SUCCESS;
-               case TC_ACT_SHOT: 
+               case TC_ACT_SHOT:
                        return NULL;
                }
 #elif defined(CONFIG_NET_CLS_POLICE)
@@ -1262,7 +1223,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 
 static int
 hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
-                 struct Qdisc **old)
+                struct Qdisc **old)
 {
        struct hfsc_class *cl = (struct hfsc_class *)arg;
 
@@ -1271,7 +1232,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
        if (cl->level > 0)
                return -EINVAL;
        if (new == NULL) {
-               new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+               new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                                       cl->classid);
                if (new == NULL)
                        new = &noop_qdisc;
        }
@@ -1294,6 +1256,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
        return NULL;
 }
 
+static void
+hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+       struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+       if (cl->qdisc->q.qlen == 0) {
+               update_vf(cl, 0, 0);
+               set_passive(cl);
+       }
+}
+
 static unsigned long
 hfsc_get_class(struct Qdisc *sch, u32 classid)
 {
@@ -1388,7 +1361,7 @@ hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
 
 static int
 hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
-                struct tcmsg *tcm)
+               struct tcmsg *tcm)
 {
        struct hfsc_class *cl = (struct hfsc_class *)arg;
        unsigned char *b = skb->tail;
@@ -1483,7 +1456,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
                if (next_time == 0 || next_time > q->root.cl_cfmin)
                        next_time = q->root.cl_cfmin;
        }
-       ASSERT(next_time != 0);
+       WARN_ON(next_time == 0);
        delay = next_time - cur_time;
        delay = PSCHED_US2JIFFIE(delay);
 
@@ -1514,7 +1487,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
        q->root.refcnt  = 1;
        q->root.classid = sch->handle;
        q->root.sched   = q;
-       q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                                         sch->handle);
        if (q->root.qdisc == NULL)
                q->root.qdisc = &noop_qdisc;
        q->root.stats_lock = &sch->dev->queue_lock;
@@ -1777,6 +1751,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
        .delete         = hfsc_delete_class,
        .graft          = hfsc_graft_class,
        .leaf           = hfsc_class_leaf,
+       .qlen_notify    = hfsc_qlen_notify,
        .get            = hfsc_get_class,
        .put            = hfsc_put_class,
        .bind_tcf       = hfsc_bind_tcf,
This page took 0.031533 seconds and 5 git commands to generate.