hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/drivers/net/dsa/sja1105/sja1105_main.c
....@@ -1691,6 +1691,18 @@
16911691
16921692 #define BYTES_PER_KBIT (1000LL / 8)
16931693
1694
+static int sja1105_find_cbs_shaper(struct sja1105_private *priv,
1695
+ int port, int prio)
1696
+{
1697
+ int i;
1698
+
1699
+ for (i = 0; i < priv->info->num_cbs_shapers; i++)
1700
+ if (priv->cbs[i].port == port && priv->cbs[i].prio == prio)
1701
+ return i;
1702
+
1703
+ return -1;
1704
+}
1705
+
16941706 static int sja1105_find_unused_cbs_shaper(struct sja1105_private *priv)
16951707 {
16961708 int i;
....@@ -1725,14 +1737,20 @@
17251737 {
17261738 struct sja1105_private *priv = ds->priv;
17271739 struct sja1105_cbs_entry *cbs;
1740
+ s64 port_transmit_rate_kbps;
17281741 int index;
17291742
17301743 if (!offload->enable)
17311744 return sja1105_delete_cbs_shaper(priv, port, offload->queue);
17321745
1733
- index = sja1105_find_unused_cbs_shaper(priv);
1734
- if (index < 0)
1735
- return -ENOSPC;
1746
+ /* The user may be replacing an existing shaper */
1747
+ index = sja1105_find_cbs_shaper(priv, port, offload->queue);
1748
+ if (index < 0) {
1749
+ /* That isn't the case - see if we can allocate a new one */
1750
+ index = sja1105_find_unused_cbs_shaper(priv);
1751
+ if (index < 0)
1752
+ return -ENOSPC;
1753
+ }
17361754
17371755 cbs = &priv->cbs[index];
17381756 cbs->port = port;
....@@ -1742,9 +1760,17 @@
17421760 */
17431761 cbs->credit_hi = offload->hicredit;
17441762 cbs->credit_lo = abs(offload->locredit);
1745
- /* User space is in kbits/sec, hardware in bytes/sec */
1746
- cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT;
1747
- cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT);
1763
+ /* User space is in kbits/sec, while the hardware in bytes/sec times
1764
+ * link speed. Since the given offload->sendslope is good only for the
1765
+ * current link speed anyway, and user space is likely to reprogram it
1766
+ * when that changes, don't even bother to track the port's link speed,
1767
+ * but deduce the port transmit rate from idleslope - sendslope.
1768
+ */
1769
+ port_transmit_rate_kbps = offload->idleslope - offload->sendslope;
1770
+ cbs->idle_slope = div_s64(offload->idleslope * BYTES_PER_KBIT,
1771
+ port_transmit_rate_kbps);
1772
+ cbs->send_slope = div_s64(abs(offload->sendslope * BYTES_PER_KBIT),
1773
+ port_transmit_rate_kbps);
17481774 /* Convert the negative values from 64-bit 2's complement
17491775 * to 32-bit 2's complement (for the case of 0x80000000 whose
17501776 * negative is still negative).