taprio: Fix enabling offload with wrong number of traffic classes
authorVinicius Costa Gomes <vinicius.gomes@intel.com>
Thu, 6 Feb 2020 21:46:06 +0000 (13:46 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Feb 2020 10:30:03 +0000 (11:30 +0100)
If the driver implementing taprio offloading depends on the value of
the network device number of traffic classes (dev->num_tc) for
whatever reason, it was going to receive the value zero. The value was
only set after the offloading function is called.

So, moving setting the number of traffic classes to before the
offloading function is called fixes this issue. This is safe because
this only happens when taprio is instantiated (we don't allow this
configuration to be changed without first removing taprio).

Fixes: 9c66d1564676 ("taprio: Add support for hardware offloading")
Reported-by: Po Liu <po.liu@nxp.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Acked-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/sch_taprio.c

index c609373c8661816fea3fd242ce8680dfb306f83f..ad0dadcfcdba8fcb8c9ea801cf3c65e827043468 100644 (file)
@@ -1444,6 +1444,19 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
 
        taprio_set_picos_per_byte(dev, q);
 
+       if (mqprio) {
+               netdev_set_num_tc(dev, mqprio->num_tc);
+               for (i = 0; i < mqprio->num_tc; i++)
+                       netdev_set_tc_queue(dev, i,
+                                           mqprio->count[i],
+                                           mqprio->offset[i]);
+
+               /* Always use supplied priority mappings */
+               for (i = 0; i <= TC_BITMASK; i++)
+                       netdev_set_prio_tc_map(dev, i,
+                                              mqprio->prio_tc_map[i]);
+       }
+
        if (FULL_OFFLOAD_IS_ENABLED(taprio_flags))
                err = taprio_enable_offload(dev, mqprio, q, new_admin, extack);
        else
@@ -1471,19 +1484,6 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
                q->advance_timer.function = advance_sched;
        }
 
-       if (mqprio) {
-               netdev_set_num_tc(dev, mqprio->num_tc);
-               for (i = 0; i < mqprio->num_tc; i++)
-                       netdev_set_tc_queue(dev, i,
-                                           mqprio->count[i],
-                                           mqprio->offset[i]);
-
-               /* Always use supplied priority mappings */
-               for (i = 0; i <= TC_BITMASK; i++)
-                       netdev_set_prio_tc_map(dev, i,
-                                              mqprio->prio_tc_map[i]);
-       }
-
        if (FULL_OFFLOAD_IS_ENABLED(taprio_flags)) {
                q->dequeue = taprio_dequeue_offload;
                q->peek = taprio_peek_offload;