cxgb4: reject overlapped queues in TC-MQPRIO offload
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Fri, 17 Jan 2020 12:51:47 +0000 (18:21 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sun, 19 Jan 2020 15:12:53 +0000 (16:12 +0100)
A queue can't belong to multiple traffic classes. So, reject
any such configuration that results in overlapped queues for a
traffic class.

Fixes: b1396c2bd675 ("cxgb4: parse and configure TC-MQPRIO offload")
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c

index 8971ddd..ec3eb45 100644 (file)
@@ -12,8 +12,9 @@ static int cxgb4_mqprio_validate(struct net_device *dev,
        struct port_info *pi = netdev2pinfo(dev);
        struct adapter *adap = netdev2adap(dev);
        u32 speed, qcount = 0, qoffset = 0;
+       u32 start_a, start_b, end_a, end_b;
        int ret;
-       u8 i;
+       u8 i, j;
 
        if (!mqprio->qopt.num_tc)
                return 0;
@@ -47,6 +48,31 @@ static int cxgb4_mqprio_validate(struct net_device *dev,
                qoffset = max_t(u16, mqprio->qopt.offset[i], qoffset);
                qcount += mqprio->qopt.count[i];
 
+               start_a = mqprio->qopt.offset[i];
+               end_a = start_a + mqprio->qopt.count[i] - 1;
+               for (j = i + 1; j < mqprio->qopt.num_tc; j++) {
+                       start_b = mqprio->qopt.offset[j];
+                       end_b = start_b + mqprio->qopt.count[j] - 1;
+
+                       /* If queue count is 0, then the traffic
+                        * belonging to this class will not use
+                        * ETHOFLD queues. So, no need to validate
+                        * further.
+                        */
+                       if (!mqprio->qopt.count[i])
+                               break;
+
+                       if (!mqprio->qopt.count[j])
+                               continue;
+
+                       if (max_t(u32, start_a, start_b) <=
+                           min_t(u32, end_a, end_b)) {
+                               netdev_err(dev,
+                                          "Queues can't overlap across tc\n");
+                               return -EINVAL;
+                       }
+               }
+
                /* Convert byte per second to bits per second */
                min_rate += (mqprio->min_rate[i] * 8);
                max_rate += (mqprio->max_rate[i] * 8);