@@ -2115,11 +2115,36 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
21152115}
21162116
21172117#define BYTES_PER_KBIT (1000LL / 8)
2118+ /* Port 0 (the uC port) does not have CBS shapers */
2119+ #define SJA1110_FIXED_CBS (port , prio ) ((((port) - 1) * SJA1105_NUM_TC) + (prio))
2120+
2121+ static int sja1105_find_cbs_shaper (struct sja1105_private * priv ,
2122+ int port , int prio )
2123+ {
2124+ int i ;
2125+
2126+ if (priv -> info -> fixed_cbs_mapping ) {
2127+ i = SJA1110_FIXED_CBS (port , prio );
2128+ if (i >= 0 && i < priv -> info -> num_cbs_shapers )
2129+ return i ;
2130+
2131+ return -1 ;
2132+ }
2133+
2134+ for (i = 0 ; i < priv -> info -> num_cbs_shapers ; i ++ )
2135+ if (priv -> cbs [i ].port == port && priv -> cbs [i ].prio == prio )
2136+ return i ;
2137+
2138+ return -1 ;
2139+ }
21182140
21192141static int sja1105_find_unused_cbs_shaper (struct sja1105_private * priv )
21202142{
21212143 int i ;
21222144
2145+ if (priv -> info -> fixed_cbs_mapping )
2146+ return -1 ;
2147+
21232148 for (i = 0 ; i < priv -> info -> num_cbs_shapers ; i ++ )
21242149 if (!priv -> cbs [i ].idle_slope && !priv -> cbs [i ].send_slope )
21252150 return i ;
@@ -2150,14 +2175,20 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
21502175{
21512176 struct sja1105_private * priv = ds -> priv ;
21522177 struct sja1105_cbs_entry * cbs ;
2178+ s64 port_transmit_rate_kbps ;
21532179 int index ;
21542180
21552181 if (!offload -> enable )
21562182 return sja1105_delete_cbs_shaper (priv , port , offload -> queue );
21572183
2158- index = sja1105_find_unused_cbs_shaper (priv );
2159- if (index < 0 )
2160- return - ENOSPC ;
2184+ /* The user may be replacing an existing shaper */
2185+ index = sja1105_find_cbs_shaper (priv , port , offload -> queue );
2186+ if (index < 0 ) {
2187+ /* That isn't the case - see if we can allocate a new one */
2188+ index = sja1105_find_unused_cbs_shaper (priv );
2189+ if (index < 0 )
2190+ return - ENOSPC ;
2191+ }
21612192
21622193 cbs = & priv -> cbs [index ];
21632194 cbs -> port = port ;
@@ -2167,9 +2198,17 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
21672198 */
21682199 cbs -> credit_hi = offload -> hicredit ;
21692200 cbs -> credit_lo = abs (offload -> locredit );
2170- /* User space is in kbits/sec, hardware in bytes/sec */
2171- cbs -> idle_slope = offload -> idleslope * BYTES_PER_KBIT ;
2172- cbs -> send_slope = abs (offload -> sendslope * BYTES_PER_KBIT );
2201+ /* User space is in kbits/sec, while the hardware in bytes/sec times
2202+ * link speed. Since the given offload->sendslope is good only for the
2203+ * current link speed anyway, and user space is likely to reprogram it
2204+ * when that changes, don't even bother to track the port's link speed,
2205+ * but deduce the port transmit rate from idleslope - sendslope.
2206+ */
2207+ port_transmit_rate_kbps = offload -> idleslope - offload -> sendslope ;
2208+ cbs -> idle_slope = div_s64 (offload -> idleslope * BYTES_PER_KBIT ,
2209+ port_transmit_rate_kbps );
2210+ cbs -> send_slope = div_s64 (abs (offload -> sendslope * BYTES_PER_KBIT ),
2211+ port_transmit_rate_kbps );
21732212 /* Convert the negative values from 64-bit 2's complement
21742213 * to 32-bit 2's complement (for the case of 0x80000000 whose
21752214 * negative is still negative).
0 commit comments