net: stmmac: replace priv->speed with the portTransmitRate from the tc-cbs parameters
authorXiaolei Wang <xiaolei.wang@windriver.com>
Sat, 8 Jun 2024 14:35:24 +0000 (22:35 +0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 12 Jun 2024 02:58:18 +0000 (19:58 -0700)
The current cbs parameter depends on speed after uplinking,
which is not needed and will report a configuration error
if the port is not initially connected. The UAPI exposed by
tc-cbs requires userspace to recalculate the send slope anyway,
because the formula depends on port_transmit_rate (see man tc-cbs),
which is not an invariant from tc's perspective. Therefore, we
use offload->sendslope and offload->idleslope to derive the
original port_transmit_rate from the CBS formula.

Fixes: 1f705bc61aee ("net: stmmac: Add support for CBS QDISC")
Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Link: https://lore.kernel.org/r/20240608143524.2065736-1-xiaolei.wang@windriver.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c

index 222540b..1562fbd 100644 (file)
@@ -343,10 +343,11 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
                        struct tc_cbs_qopt_offload *qopt)
 {
        u32 tx_queues_count = priv->plat->tx_queues_to_use;
+       s64 port_transmit_rate_kbps;
        u32 queue = qopt->queue;
-       u32 ptr, speed_div;
        u32 mode_to_use;
        u64 value;
+       u32 ptr;
        int ret;
 
        /* Queue 0 is not AVB capable */
@@ -355,30 +356,26 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
        if (!priv->dma_cap.av)
                return -EOPNOTSUPP;
 
+       port_transmit_rate_kbps = qopt->idleslope - qopt->sendslope;
+
        /* Port Transmit Rate and Speed Divider */
-       switch (priv->speed) {
+       switch (div_s64(port_transmit_rate_kbps, 1000)) {
        case SPEED_10000:
-               ptr = 32;
-               speed_div = 10000000;
-               break;
        case SPEED_5000:
                ptr = 32;
-               speed_div = 5000000;
                break;
        case SPEED_2500:
-               ptr = 8;
-               speed_div = 2500000;
-               break;
        case SPEED_1000:
                ptr = 8;
-               speed_div = 1000000;
                break;
        case SPEED_100:
                ptr = 4;
-               speed_div = 100000;
                break;
        default:
-               return -EOPNOTSUPP;
+               netdev_err(priv->dev,
+                          "Invalid portTransmitRate %lld (idleSlope - sendSlope)\n",
+                          port_transmit_rate_kbps);
+               return -EINVAL;
        }
 
        mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
@@ -398,10 +395,10 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
        }
 
        /* Final adjustments for HW */
-       value = div_s64(qopt->idleslope * 1024ll * ptr, speed_div);
+       value = div_s64(qopt->idleslope * 1024ll * ptr, port_transmit_rate_kbps);
        priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0);
 
-       value = div_s64(-qopt->sendslope * 1024ll * ptr, speed_div);
+       value = div_s64(-qopt->sendslope * 1024ll * ptr, port_transmit_rate_kbps);
        priv->plat->tx_queues_cfg[queue].send_slope = value & GENMASK(31, 0);
 
        value = qopt->hicredit * 1024ll * 8;