net: enetc: offload per-tc max SDU from tc-taprio
authorVladimir Oltean <vladimir.oltean@nxp.com>
Wed, 28 Sep 2022 09:52:04 +0000 (12:52 +0300)
committerJakub Kicinski <kuba@kernel.org>
Fri, 30 Sep 2022 01:52:06 +0000 (18:52 -0700)
The driver currently sets the PTCMSDUR register statically to the max
MTU supported by the interface. Keep this logic if tc-taprio is absent
or if the max_sdu for a traffic class is 0, and follow the requested max
SDU size otherwise.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/freescale/enetc/enetc.h
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/freescale/enetc/enetc_qos.c

index 748677b2ce1fa6e6289d5fc72f1c1ab817a3a078..161930a65f61441f7407ae987ac0b5aaa8daa5d0 100644 (file)
@@ -453,7 +453,11 @@ static inline void enetc_cbd_free_data_mem(struct enetc_si *si, int size,
                          data, *dma);
 }
 
+void enetc_reset_ptcmsdur(struct enetc_hw *hw);
+void enetc_set_ptcmsdur(struct enetc_hw *hw, u32 *queue_max_sdu);
+
 #ifdef CONFIG_FSL_ENETC_QOS
+int enetc_qos_query_caps(struct net_device *ndev, void *type_data);
 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
 void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed);
 int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
@@ -521,6 +525,7 @@ static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
 }
 
 #else
+#define enetc_qos_query_caps(ndev, type_data) -EOPNOTSUPP
 #define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
 #define enetc_sched_speed_set(priv, speed) (void)0
 #define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
index bb7750222691dae9608cfc1c0196d22e5f8dd537..bdf94335ee99ccb1b62055694b6a29f939a6f378 100644 (file)
@@ -516,15 +516,34 @@ static void enetc_port_si_configure(struct enetc_si *si)
        enetc_port_wr(hw, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS);
 }
 
-static void enetc_configure_port_mac(struct enetc_hw *hw)
+void enetc_set_ptcmsdur(struct enetc_hw *hw, u32 *max_sdu)
 {
        int tc;
 
-       enetc_port_wr(hw, ENETC_PM0_MAXFRM,
-                     ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE));
+       for (tc = 0; tc < 8; tc++) {
+               u32 val = ENETC_MAC_MAXFRM_SIZE;
+
+               if (max_sdu[tc])
+                       val = max_sdu[tc] + VLAN_ETH_HLEN;
+
+               enetc_port_wr(hw, ENETC_PTCMSDUR(tc), val);
+       }
+}
+
+void enetc_reset_ptcmsdur(struct enetc_hw *hw)
+{
+       int tc;
 
        for (tc = 0; tc < 8; tc++)
                enetc_port_wr(hw, ENETC_PTCMSDUR(tc), ENETC_MAC_MAXFRM_SIZE);
+}
+
+static void enetc_configure_port_mac(struct enetc_hw *hw)
+{
+       enetc_port_wr(hw, ENETC_PM0_MAXFRM,
+                     ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE));
+
+       enetc_reset_ptcmsdur(hw);
 
        enetc_port_wr(hw, ENETC_PM0_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
                      ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC);
@@ -738,6 +757,8 @@ static int enetc_pf_setup_tc(struct net_device *ndev, enum tc_setup_type type,
                             void *type_data)
 {
        switch (type) {
+       case TC_QUERY_CAPS:
+               return enetc_qos_query_caps(ndev, type_data);
        case TC_SETUP_QDISC_MQPRIO:
                return enetc_setup_tc_mqprio(ndev, type_data);
        case TC_SETUP_QDISC_TAPRIO:
index ee28cb62afe8d969eaf722a4ff76670700bfe87d..e6416332ec79658b6c3b38607dadf3a1c314ce51 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/math64.h>
 #include <linux/refcount.h>
 #include <net/pkt_cls.h>
+#include <net/pkt_sched.h>
 #include <net/tc_act/tc_gate.h>
 
 static u16 enetc_get_max_gcl_len(struct enetc_hw *hw)
@@ -67,6 +68,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
        tge = enetc_rd(hw, ENETC_PTGCR);
        if (!admin_conf->enable) {
                enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE);
+               enetc_reset_ptcmsdur(hw);
 
                priv->active_offloads &= ~ENETC_F_QBV;
 
@@ -122,10 +124,13 @@ static int enetc_setup_taprio(struct net_device *ndev,
 
        enetc_cbd_free_data_mem(priv->si, data_size, tmp, &dma);
 
-       if (!err)
-               priv->active_offloads |= ENETC_F_QBV;
+       if (err)
+               return err;
 
-       return err;
+       enetc_set_ptcmsdur(hw, admin_conf->max_sdu);
+       priv->active_offloads |= ENETC_F_QBV;
+
+       return 0;
 }
 
 int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
@@ -1594,3 +1599,23 @@ int enetc_setup_tc_psfp(struct net_device *ndev, void *type_data)
 
        return 0;
 }
+
+int enetc_qos_query_caps(struct net_device *ndev, void *type_data)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       struct tc_query_caps_base *base = type_data;
+       struct enetc_si *si = priv->si;
+
+       switch (base->type) {
+       case TC_SETUP_QDISC_TAPRIO: {
+               struct tc_taprio_caps *caps = base->caps;
+
+               if (si->hw_features & ENETC_SI_F_QBV)
+                       caps->supports_queue_max_sdu = true;
+
+               return 0;
+       }
+       default:
+               return -EOPNOTSUPP;
+       }
+}