Merge branch 'for-linus-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / net / sched / sch_api.c
index ad9eed70bc8f8e16c3118c6527374a952823e2c0..f06aa01d60fd344bc853c9363dcff1dcec27fab3 100644 (file)
@@ -815,10 +815,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                if (dev->flags & IFF_UP)
                        dev_deactivate(dev);
 
-               if (new && new->ops->attach) {
-                       new->ops->attach(new);
-                       num_q = 0;
-               }
+               if (new && new->ops->attach)
+                       goto skip;
 
                for (i = 0; i < num_q; i++) {
                        struct netdev_queue *dev_queue = dev_ingress_queue(dev);
@@ -834,12 +832,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
                                qdisc_destroy(old);
                }
 
+skip:
                if (!ingress) {
                        notify_and_destroy(net, skb, n, classid,
                                           dev->qdisc, new);
                        if (new && !new->ops->attach)
                                atomic_inc(&new->refcnt);
                        dev->qdisc = new ? : &noop_qdisc;
+
+                       if (new && new->ops->attach)
+                               new->ops->attach(new);
                } else {
                        notify_and_destroy(net, skb, n, classid, old, new);
                }
@@ -1816,13 +1818,8 @@ int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
                        continue;
                err = tp->classify(skb, tp, res);
 
-               if (err >= 0) {
-#ifdef CONFIG_NET_CLS_ACT
-                       if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
-                               skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
-#endif
+               if (err >= 0)
                        return err;
-               }
        }
        return -1;
 }
@@ -1834,23 +1831,22 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        int err = 0;
 #ifdef CONFIG_NET_CLS_ACT
        const struct tcf_proto *otp = tp;
+       int limit = 0;
 reclassify:
 #endif
 
        err = tc_classify_compat(skb, tp, res);
 #ifdef CONFIG_NET_CLS_ACT
        if (err == TC_ACT_RECLASSIFY) {
-               u32 verd = G_TC_VERD(skb->tc_verd);
                tp = otp;
 
-               if (verd++ >= MAX_REC_LOOP) {
+               if (unlikely(limit++ >= MAX_REC_LOOP)) {
                        net_notice_ratelimited("%s: packet reclassify loop rule prio %u protocol %02x\n",
                                               tp->q->ops->id,
                                               tp->prio & 0xffff,
                                               ntohs(tp->protocol));
                        return TC_ACT_SHOT;
                }
-               skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
                goto reclassify;
        }
 #endif
@@ -1883,13 +1879,10 @@ EXPORT_SYMBOL(tcf_destroy_chain);
 #ifdef CONFIG_PROC_FS
 static int psched_show(struct seq_file *seq, void *v)
 {
-       struct timespec ts;
-
-       hrtimer_get_res(CLOCK_MONOTONIC, &ts);
        seq_printf(seq, "%08x %08x %08x %08x\n",
                   (u32)NSEC_PER_USEC, (u32)PSCHED_TICKS2NS(1),
                   1000000,
-                  (u32)NSEC_PER_SEC/(u32)ktime_to_ns(timespec_to_ktime(ts)));
+                  (u32)NSEC_PER_SEC / hrtimer_resolution);
 
        return 0;
 }