History

net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU registers

The PPE enforces output frame size limits via per-tag-layer VLAN_MTU registers that the driver never initializes. The hardware defaults do not account for PPPoE overhead, causing the PPE to punt encapsulated frames back to the CPU instead of forwarding them. Initialize the registers at PPE start and on MTU changes using the maximum GMAC MTU. This is a conservative approximation -- the actual per-PPE requirement depends on egress path, but using the global maximum ensures the limits are never too small.

Daniel Golle committed 7 months ago

Commit 2dddb341 parent 5e700c73 files · +52 −1Browse files

Unified · Split

3 files
  1. drivers/net/ethernet/mediatek/mtk_eth_soc.c +21 −1
  2. drivers/net/ethernet/mediatek/mtk_ppe.c +30 −0
  3. drivers/net/ethernet/mediatek/mtk_ppe.h +1 −0
drivers/net/ethernet/mediatek/mtk_eth_soc.c+21−1
@@ -3566,12 +3566,23 @@ found: · 3565 unmodified lines
35663566 return NOTIFY_DONE;
35673567 }
35683568
3569+static int mtk_max_gmac_mtu(struct mtk_eth *eth)
3570+{
3571+ int i, max_mtu = ETH_DATA_LEN;
3572+
3573+ for (i = 0; i < ARRAY_SIZE(eth->netdev); i++)
3574+ if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu)
3575+ max_mtu = eth->netdev[i]->mtu;
3576+
3577+ return max_mtu;
3578+}
3579+
35693580 static int mtk_open(struct net_device *dev)
35703581 {
35713582 struct mtk_mac *mac = netdev_priv(dev);
35723583 struct mtk_eth *eth = mac->hw;
35733584 struct mtk_mac *target_mac;
3574− int i, err, ppe_num;
3585+ int i, err, ppe_num, mtu;
35753586
35763587 ppe_num = eth->soc->ppe_num;
35773588
@@ -3618,6 +3629,10 @@ static int mtk_open(struct net_device *dev) · 40 unmodified lines
36183629 mtk_gdm_config(eth, target_mac->id, gdm_config);
36193630 }
36203631
3632+ mtu = mtk_max_gmac_mtu(eth);
3633+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
3634+ mtk_ppe_update_mtu(eth->ppe[i], mtu);
3635+
36213636 napi_enable(&eth->tx_napi);
36223637 napi_enable(&eth->rx_napi);
36233638 mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
@@ -4311,6 +4326,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) · 687 unmodified lines
43114326 int length = new_mtu + MTK_RX_ETH_HLEN;
43124327 struct mtk_mac *mac = netdev_priv(dev);
43134328 struct mtk_eth *eth = mac->hw;
4329+ int max_mtu, i;
43144330
43154331 if (rcu_access_pointer(eth->prog) &&
43164332 length > MTK_PP_MAX_BUF_SIZE) {
@@ -4321,6 +4337,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu) · 4 unmodified lines
43214337 mtk_set_mcr_max_rx(mac, length);
43224338 WRITE_ONCE(dev->mtu, new_mtu);
43234339
4340+ max_mtu = mtk_max_gmac_mtu(eth);
4341+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
4342+ mtk_ppe_update_mtu(eth->ppe[i], max_mtu);
4343+
43244344 return 0;
43254345 }
43264346
drivers/net/ethernet/mediatek/mtk_ppe.c+30−0
@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe) · 972 unmodified lines
973973 }
974974 }
975975
976+void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu)
977+{
978+ int base;
979+ u32 val;
980+
981+ if (!ppe)
982+ return;
983+
984+ /* The PPE checks output frame size against per-tag-layer MTU limits,
985+ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux
986+ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag
987+ * overhead, but 802.1Q VLAN tags are handled transparently without
988+ * being reflected by the lower device MTU being increased by 4.
989+ * Use the maximum MTU across all GMAC interfaces so that PPE output
990+ * frame limits are sufficiently high regardless of which port a flow
991+ * egresses through.
992+ */
993+ base = ETH_HLEN + mtu;
994+
995+ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) |
996+ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN);
997+ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val);
998+
999+ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG,
1000+ base + 2 * VLAN_HLEN) |
1001+ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG,
1002+ base + 3 * VLAN_HLEN);
1003+ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val);
1004+}
1005+
9761006 void mtk_ppe_start(struct mtk_ppe *ppe)
9771007 {
9781008 u32 val;
drivers/net/ethernet/mediatek/mtk_ppe.h+1−0
@@ -346,6 +346,7 @@ struct mtk_ppe { · 345 unmodified lines
346346 struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index);
347347
348348 void mtk_ppe_deinit(struct mtk_eth *eth);
349+void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu);
349350 void mtk_ppe_start(struct mtk_ppe *ppe);
350351 int mtk_ppe_stop(struct mtk_ppe *ppe);
351352 int mtk_ppe_prepare_reset(struct mtk_ppe *ppe);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t