Patch "net: dsa: sja1105: fix bandwidth discrepancy between tc-cbs software and offload" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net: dsa: sja1105: fix bandwidth discrepancy between tc-cbs software and offload

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-dsa-sja1105-fix-bandwidth-discrepancy-between-tc.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit b5233eb3d9c9effc3afcfc8eac1f178287190775
Author: Vladimir Oltean <vladimir.oltean@xxxxxxx>
Date:   Wed Sep 6 00:53:36 2023 +0300

    net: dsa: sja1105: fix bandwidth discrepancy between tc-cbs software and offload
    
    [ Upstream commit 954ad9bf13c4f95a4958b5f8433301f2ab99e1f5 ]
    
    More careful measurement of the tc-cbs bandwidth shows that the stream
    bandwidth (effectively idleslope) increases, there is a larger and
    larger discrepancy between the rate limit obtained by the software
    Qdisc, and the rate limit obtained by its offloaded counterpart.
    
    The discrepancy becomes so large, that e.g. at an idleslope of 40000
    (40Mbps), the offloaded cbs does not actually rate limit anything, and
    traffic will pass at line rate through a 100 Mbps port.
    
    The reason for the discrepancy is that the hardware documentation I've
    been following is incorrect. UM11040.pdf (for SJA1105P/Q/R/S) states
    about IDLE_SLOPE that it is "the rate (in unit of bytes/sec) at which
    the credit counter is increased".
    
    Cross-checking with UM10944.pdf (for SJA1105E/T) and UM11107.pdf
    (for SJA1110), the wording is different: "This field specifies the
    value, in bytes per second times link speed, by which the credit counter
    is increased".
    
    So there's an extra scaling for link speed that the driver is currently
    not accounting for, and apparently (empirically), that link speed is
    expressed in Kbps.
    
    I've pondered whether to pollute the sja1105_mac_link_up()
    implementation with CBS shaper reprogramming, but I don't think it is
    worth it. IMO, the UAPI exposed by tc-cbs requires user space to
    recalculate the sendslope anyway, since the formula for that depends on
    port_transmit_rate (see man tc-cbs), which is not an invariant from tc's
    perspective.
    
    So we use the offload->sendslope and offload->idleslope to deduce the
    original port_transmit_rate from the CBS formula, and use that value to
    scale the offload->sendslope and offload->idleslope to values that the
    hardware understands.
    
    Some numerical data points:
    
     40Mbps stream, max interfering frame size 1500, port speed 100M
     ---------------------------------------------------------------
    
     tc-cbs parameters:
     idleslope 40000 sendslope -60000 locredit -900 hicredit 600
    
     which result in hardware values:
    
     Before (doesn't work)           After (works)
     credit_hi    600                600
     credit_lo    900                900
     send_slope   7500000            75
     idle_slope   5000000            50
    
     40Mbps stream, max interfering frame size 1500, port speed 1G
     -------------------------------------------------------------
    
     tc-cbs parameters:
     idleslope 40000 sendslope -960000 locredit -1440 hicredit 60
    
     which result in hardware values:
    
     Before (doesn't work)           After (works)
     credit_hi    60                 60
     credit_lo    1440               1440
     send_slope   120000000          120
     idle_slope   5000000            5
    
     5.12Mbps stream, max interfering frame size 1522, port speed 100M
     -----------------------------------------------------------------
    
     tc-cbs parameters:
     idleslope 5120 sendslope -94880 locredit -1444 hicredit 77
    
     which result in hardware values:
    
     Before (doesn't work)           After (works)
     credit_hi    77                 77
     credit_lo    1444               1444
     send_slope   11860000           118
     idle_slope   640000             6
    
    Tested on SJA1105T, SJA1105S and SJA1110A, at 1Gbps and 100Mbps.
    
    Fixes: 4d7525085a9b ("net: dsa: sja1105: offload the Credit-Based Shaper qdisc")
    Reported-by: Yanan Yang <yanan.yang@xxxxxxx>
    Signed-off-by: Vladimir Oltean <vladimir.oltean@xxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index ef4d8d6c2bd7a..5f70773fa8201 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2049,6 +2049,7 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
 {
 	struct sja1105_private *priv = ds->priv;
 	struct sja1105_cbs_entry *cbs;
+	s64 port_transmit_rate_kbps;
 	int index;
 
 	if (!offload->enable)
@@ -2066,9 +2067,17 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
 	 */
 	cbs->credit_hi = offload->hicredit;
 	cbs->credit_lo = abs(offload->locredit);
-	/* User space is in kbits/sec, hardware in bytes/sec */
-	cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT;
-	cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT);
+	/* User space is in kbits/sec, while the hardware in bytes/sec times
+	 * link speed. Since the given offload->sendslope is good only for the
+	 * current link speed anyway, and user space is likely to reprogram it
+	 * when that changes, don't even bother to track the port's link speed,
+	 * but deduce the port transmit rate from idleslope - sendslope.
+	 */
+	port_transmit_rate_kbps = offload->idleslope - offload->sendslope;
+	cbs->idle_slope = div_s64(offload->idleslope * BYTES_PER_KBIT,
+				  port_transmit_rate_kbps);
+	cbs->send_slope = div_s64(abs(offload->sendslope * BYTES_PER_KBIT),
+				  port_transmit_rate_kbps);
 	/* Convert the negative values from 64-bit 2's complement
 	 * to 32-bit 2's complement (for the case of 0x80000000 whose
 	 * negative is still negative).



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux