net: lan966x: Add offload support for mqprio
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Wed, 21 Sep 2022 12:25:36 +0000 (14:25 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 Sep 2022 11:31:27 +0000 (12:31 +0100)
Implement mqprio qdisc support using tc command.
The HW supports 8 priority queues from highest (7) to lowest (0).

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/lan966x/Makefile
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c [new file with mode: 0644]
drivers/net/ethernet/microchip/lan966x/lan966x_tc.c [new file with mode: 0644]

index 0c22c86..2ea66b9 100644 (file)
@@ -8,4 +8,5 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
 lan966x-switch-objs  := lan966x_main.o lan966x_phylink.o lan966x_port.o \
                        lan966x_mac.o lan966x_ethtool.o lan966x_switchdev.o \
                        lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \
-                       lan966x_ptp.o lan966x_fdma.o lan966x_lag.o
+                       lan966x_ptp.o lan966x_fdma.o lan966x_lag.o \
+                       lan966x_tc.o lan966x_mqprio.o
index ee9b8eb..033120a 100644 (file)
@@ -466,6 +466,7 @@ static const struct net_device_ops lan966x_port_netdev_ops = {
        .ndo_set_mac_address            = lan966x_port_set_mac_address,
        .ndo_get_port_parent_id         = lan966x_port_get_parent_id,
        .ndo_eth_ioctl                  = lan966x_port_ioctl,
+       .ndo_setup_tc                   = lan966x_tc_setup,
 };
 
 bool lan966x_netdevice_check(const struct net_device *dev)
@@ -755,7 +756,9 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
        dev->netdev_ops = &lan966x_port_netdev_ops;
        dev->ethtool_ops = &lan966x_ethtool_ops;
        dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
-                        NETIF_F_HW_VLAN_STAG_TX;
+                        NETIF_F_HW_VLAN_STAG_TX |
+                        NETIF_F_HW_TC;
+       dev->hw_features |= NETIF_F_HW_TC;
        dev->needed_headroom = IFH_LEN * sizeof(u32);
 
        eth_hw_addr_gen(dev, lan966x->base_mac, p + 1);
index a5d5987..b037b1f 100644 (file)
@@ -446,6 +446,12 @@ void lan966x_port_ageing_set(struct lan966x_port *port,
                             unsigned long ageing_clock_t);
 void lan966x_update_fwd_mask(struct lan966x *lan966x);
 
+int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
+                    void *type_data);
+
+int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc);
+int lan966x_mqprio_del(struct lan966x_port *port);
+
 static inline void __iomem *lan_addr(void __iomem *base[],
                                     int id, int tinst, int tcnt,
                                     int gbase, int ginst,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c b/drivers/net/ethernet/microchip/lan966x/lan966x_mqprio.c
new file mode 100644 (file)
index 0000000..950ea48
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "lan966x_main.h"
+
+int lan966x_mqprio_add(struct lan966x_port *port, u8 num_tc)
+{
+       u8 i;
+
+       if (num_tc != NUM_PRIO_QUEUES) {
+               netdev_err(port->dev, "Only %d tarffic classes supported\n",
+                          NUM_PRIO_QUEUES);
+               return -EINVAL;
+       }
+
+       netdev_set_num_tc(port->dev, num_tc);
+
+       for (i = 0; i < num_tc; ++i)
+               netdev_set_tc_queue(port->dev, i, 1, i);
+
+       return 0;
+}
+
+int lan966x_mqprio_del(struct lan966x_port *port)
+{
+       netdev_reset_tc(port->dev);
+
+       return 0;
+}
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
new file mode 100644 (file)
index 0000000..3fea093
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <net/pkt_cls.h>
+
+#include "lan966x_main.h"
+
+static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
+                                        struct tc_mqprio_qopt_offload *mqprio)
+{
+       u8 num_tc = mqprio->qopt.num_tc;
+
+       mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS;
+
+       return num_tc ? lan966x_mqprio_add(port, num_tc) :
+                       lan966x_mqprio_del(port);
+}
+
+int lan966x_tc_setup(struct net_device *dev, enum tc_setup_type type,
+                    void *type_data)
+{
+       struct lan966x_port *port = netdev_priv(dev);
+
+       switch (type) {
+       case TC_SETUP_QDISC_MQPRIO:
+               return lan966x_tc_setup_qdisc_mqprio(port, type_data);
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}