Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ethernet: ti: cpsw: fix min eth packet size for non-switch use-cases

The CPSW switchdev driver inherited fix from commit 9421c9015047 ("net:
ethernet: ti: cpsw: fix min eth packet size") which changes min TX packet
size to 64bytes (VLAN_ETH_ZLEN, excluding ETH_FCS). It was done to fix HW
packed drop issue when packets are sent from Host to the port with PVID and
un-tagging enabled. Unfortunately this breaks some other non-switch
specific use-cases, like:
- [1] CPSW port as DSA CPU port with DSA-tag applied at the end of the
packet
- [2] Some industrial protocols, which expects min TX packet size 60Bytes
(excluding FCS).

Fix it by configuring min TX packet size depending on driver mode
- 60Bytes (ETH_ZLEN) for multi mac (dual-mac) mode
- 64Bytes (VLAN_ETH_ZLEN) for switch mode
and update it during driver mode change and annotate with
READ_ONCE()/WRITE_ONCE() as it can be read by napi while writing.

[1] https://lore.kernel.org/netdev/20210531124051.GA15218@cephalopod/
[2] https://e2e.ti.com/support/arm/sitara_arm/f/791/t/701669

Cc: stable@vger.kernel.org
Fixes: ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
Reported-by: Ben Hutchings <ben.hutchings@essensium.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Grygorii Strashko and committed by
David S. Miller
acc68b8d 0fa32ca4

+8 -3
+5 -2
drivers/net/ethernet/ti/cpsw_new.c
··· 920 920 struct cpdma_chan *txch; 921 921 int ret, q_idx; 922 922 923 - if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) { 923 + if (skb_put_padto(skb, READ_ONCE(priv->tx_packet_min))) { 924 924 cpsw_err(priv, tx_err, "packet pad failed\n"); 925 925 ndev->stats.tx_dropped++; 926 926 return NET_XMIT_DROP; ··· 1100 1100 1101 1101 for (i = 0; i < n; i++) { 1102 1102 xdpf = frames[i]; 1103 - if (xdpf->len < CPSW_MIN_PACKET_SIZE) 1103 + if (xdpf->len < READ_ONCE(priv->tx_packet_min)) 1104 1104 break; 1105 1105 1106 1106 if (cpsw_xdp_tx_frame(priv, xdpf, NULL, priv->emac_port)) ··· 1389 1389 priv->dev = dev; 1390 1390 priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 1391 1391 priv->emac_port = i + 1; 1392 + priv->tx_packet_min = CPSW_MIN_PACKET_SIZE; 1392 1393 1393 1394 if (is_valid_ether_addr(slave_data->mac_addr)) { 1394 1395 ether_addr_copy(priv->mac_addr, slave_data->mac_addr); ··· 1687 1686 1688 1687 priv = netdev_priv(sl_ndev); 1689 1688 slave->port_vlan = vlan; 1689 + WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE_VLAN); 1690 1690 if (netif_running(sl_ndev)) 1691 1691 cpsw_port_add_switch_def_ale_entries(priv, 1692 1692 slave); ··· 1716 1714 1717 1715 priv = netdev_priv(slave->ndev); 1718 1716 slave->port_vlan = slave->data->dual_emac_res_vlan; 1717 + WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE); 1719 1718 cpsw_port_add_dual_emac_def_ale_entries(priv, slave); 1720 1719 } 1721 1720
+3 -1
drivers/net/ethernet/ti/cpsw_priv.h
··· 89 89 90 90 #define CPSW_POLL_WEIGHT 64 91 91 #define CPSW_RX_VLAN_ENCAP_HDR_SIZE 4 92 - #define CPSW_MIN_PACKET_SIZE (VLAN_ETH_ZLEN) 92 + #define CPSW_MIN_PACKET_SIZE_VLAN (VLAN_ETH_ZLEN) 93 + #define CPSW_MIN_PACKET_SIZE (ETH_ZLEN) 93 94 #define CPSW_MAX_PACKET_SIZE (VLAN_ETH_FRAME_LEN +\ 94 95 ETH_FCS_LEN +\ 95 96 CPSW_RX_VLAN_ENCAP_HDR_SIZE) ··· 381 380 u32 emac_port; 382 381 struct cpsw_common *cpsw; 383 382 int offload_fwd_mark; 383 + u32 tx_packet_min; 384 384 }; 385 385 386 386 #define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)