@@ -245,6 +245,16 @@ static int mlxsw_sx_port_swid_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 swid)
245245 return mlxsw_reg_write (mlxsw_sx -> core , MLXSW_REG (pspa ), pspa_pl );
246246}
247247
248+ static int
249+ mlxsw_sx_port_system_port_mapping_set (struct mlxsw_sx_port * mlxsw_sx_port )
250+ {
251+ struct mlxsw_sx * mlxsw_sx = mlxsw_sx_port -> mlxsw_sx ;
252+ char sspr_pl [MLXSW_REG_SSPR_LEN ];
253+
254+ mlxsw_reg_sspr_pack (sspr_pl , mlxsw_sx_port -> local_port );
255+ return mlxsw_reg_write (mlxsw_sx -> core , MLXSW_REG (sspr ), sspr_pl );
256+ }
257+
248258static int mlxsw_sx_port_module_check (struct mlxsw_sx_port * mlxsw_sx_port ,
249259 bool * p_usable )
250260{
@@ -290,37 +300,34 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
290300 .local_port = mlxsw_sx_port -> local_port ,
291301 .is_emad = false,
292302 };
293- struct sk_buff * skb_old = NULL ;
303+ u64 len ;
294304 int err ;
295305
306+ if (mlxsw_core_skb_transmit_busy (mlxsw_sx , & tx_info ))
307+ return NETDEV_TX_BUSY ;
308+
296309 if (unlikely (skb_headroom (skb ) < MLXSW_TXHDR_LEN )) {
297- struct sk_buff * skb_new ;
310+ struct sk_buff * skb_orig = skb ;
298311
299- skb_old = skb ;
300- skb_new = skb_realloc_headroom (skb , MLXSW_TXHDR_LEN );
301- if (!skb_new ) {
312+ skb = skb_realloc_headroom (skb , MLXSW_TXHDR_LEN );
313+ if (!skb ) {
302314 this_cpu_inc (mlxsw_sx_port -> pcpu_stats -> tx_dropped );
303- dev_kfree_skb_any (skb_old );
315+ dev_kfree_skb_any (skb_orig );
304316 return NETDEV_TX_OK ;
305317 }
306- skb = skb_new ;
307318 }
308319 mlxsw_sx_txhdr_construct (skb , & tx_info );
320+ len = skb -> len ;
321+ /* Due to a race we might fail here because of a full queue. In that
322+ * unlikely case we simply drop the packet.
323+ */
309324 err = mlxsw_core_skb_transmit (mlxsw_sx , skb , & tx_info );
310- if (err == - EAGAIN ) {
311- if (skb_old )
312- dev_kfree_skb_any (skb );
313- return NETDEV_TX_BUSY ;
314- }
315-
316- if (skb_old )
317- dev_kfree_skb_any (skb_old );
318325
319326 if (!err ) {
320327 pcpu_stats = this_cpu_ptr (mlxsw_sx_port -> pcpu_stats );
321328 u64_stats_update_begin (& pcpu_stats -> syncp );
322329 pcpu_stats -> tx_packets ++ ;
323- pcpu_stats -> tx_bytes += skb -> len ;
330+ pcpu_stats -> tx_bytes += len ;
324331 u64_stats_update_end (& pcpu_stats -> syncp );
325332 } else {
326333 this_cpu_inc (mlxsw_sx_port -> pcpu_stats -> tx_dropped );
@@ -1001,6 +1008,13 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
10011008 goto port_not_usable ;
10021009 }
10031010
1011+ err = mlxsw_sx_port_system_port_mapping_set (mlxsw_sx_port );
1012+ if (err ) {
1013+ dev_err (mlxsw_sx -> bus_info -> dev , "Port %d: Failed to set system port mapping\n" ,
1014+ mlxsw_sx_port -> local_port );
1015+ goto err_port_system_port_mapping_set ;
1016+ }
1017+
10041018 err = mlxsw_sx_port_swid_set (mlxsw_sx_port , 0 );
10051019 if (err ) {
10061020 dev_err (mlxsw_sx -> bus_info -> dev , "Port %d: Failed to set SWID\n" ,
@@ -1061,6 +1075,7 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
10611075err_port_mtu_set :
10621076err_port_speed_set :
10631077err_port_swid_set :
1078+ err_port_system_port_mapping_set :
10641079port_not_usable :
10651080err_port_module_check :
10661081err_dev_addr_get :
@@ -1079,6 +1094,7 @@ static void mlxsw_sx_port_remove(struct mlxsw_sx *mlxsw_sx, u8 local_port)
10791094 unregister_netdev (mlxsw_sx_port -> dev ); /* This calls ndo_stop */
10801095 mlxsw_sx_port_swid_set (mlxsw_sx_port , MLXSW_PORT_SWID_DISABLED_PORT );
10811096 free_percpu (mlxsw_sx_port -> pcpu_stats );
1097+ free_netdev (mlxsw_sx_port -> dev );
10821098}
10831099
10841100static void mlxsw_sx_ports_remove (struct mlxsw_sx * mlxsw_sx )
0 commit comments