@@ -2115,11 +2115,36 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
2115
2115
}
2116
2116
2117
2117
#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
+ }
2118
2140
2119
2141
static int sja1105_find_unused_cbs_shaper (struct sja1105_private * priv )
2120
2142
{
2121
2143
int i ;
2122
2144
2145
+ if (priv -> info -> fixed_cbs_mapping )
2146
+ return -1 ;
2147
+
2123
2148
for (i = 0 ; i < priv -> info -> num_cbs_shapers ; i ++ )
2124
2149
if (!priv -> cbs [i ].idle_slope && !priv -> cbs [i ].send_slope )
2125
2150
return i ;
@@ -2150,14 +2175,20 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
2150
2175
{
2151
2176
struct sja1105_private * priv = ds -> priv ;
2152
2177
struct sja1105_cbs_entry * cbs ;
2178
+ s64 port_transmit_rate_kbps ;
2153
2179
int index ;
2154
2180
2155
2181
if (!offload -> enable )
2156
2182
return sja1105_delete_cbs_shaper (priv , port , offload -> queue );
2157
2183
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
+ }
2161
2192
2162
2193
cbs = & priv -> cbs [index ];
2163
2194
cbs -> port = port ;
@@ -2167,9 +2198,17 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
2167
2198
*/
2168
2199
cbs -> credit_hi = offload -> hicredit ;
2169
2200
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 );
2173
2212
/* Convert the negative values from 64-bit 2's complement
2174
2213
* to 32-bit 2's complement (for the case of 0x80000000 whose
2175
2214
* negative is still negative).
0 commit comments