From: Christian Marangi Date: Wed, 17 Jun 2026 17:47:16 +0000 (+0200) Subject: airoha: replace multi serdes patch with upstream kernel version X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F23849%2Fhead;p=thirdparty%2Fopenwrt.git airoha: replace multi serdes patch with upstream kernel version Now that multi serdes patch are accepted upstream, reorder the current patch in the 1xx numbering and add the kernel version tag. Also replace the downstream patch with the exact version merged upstream. Downstream PCS implementation is updated with a new revision for the ethernet code. Update any patch affected by these changes. Link: https://github.com/openwrt/openwrt/pull/23849 Signed-off-by: Christian Marangi --- diff --git a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch index 7e078d08653..6be83a301b0 100644 --- a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch +++ b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch @@ -28,7 +28,7 @@ Signed-off-by: Jakub Kicinski - FC_ID_OF_SRC_PORT24_MASK, - FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -+ u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); ++ u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, + __field_prep(mask, AIROHA_GDM2_IDX)); diff --git a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch index 417adfd7db5..56ac9729563 100644 --- a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch +++ b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni + airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); @@ -1873,7 +1876,8 @@ static int airoha_dev_init(struct net_de } diff --git a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch similarity index 63% rename from target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch index f92593c504a..f6c5f766f21 100644 --- a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch @@ -1,8 +1,7 @@ -From e15783f7c987e199ecf80b3d858ed5a86d33c508 Mon Sep 17 00:00:00 2001 -Message-ID: +From ec6c391bcca748bca041d5db92ff3bc4c99b3572 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:25:52 +0100 -Subject: [PATCH 01/13] net: airoha: Introduce airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:15 +0200 +Subject: [PATCH 1/6] net: airoha: Introduce airoha_gdm_dev struct EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3 or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner. @@ -17,6 +16,8 @@ connected to the same GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-1-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 312 ++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 13 +- @@ -25,18 +26,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -483,8 +483,9 @@ static bool airoha_fe_lro_is_enabled(str - LRO_RXQ_EN_MASK); - } - --static void airoha_dev_lro_enable(struct airoha_gdm_port *port) -+static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) - { -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -843,6 +844,7 @@ static int airoha_qdma_rx_process(struct +@@ -600,6 +600,7 @@ static int airoha_qdma_rx_process(struct struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; struct airoha_gdm_port *port; @@ -44,21 +34,29 @@ Signed-off-by: Lorenzo Bianconi int data_len, len, p; struct page *page; -@@ -869,8 +871,12 @@ static int airoha_qdma_rx_process(struct +@@ -626,6 +627,10 @@ static int airoha_qdma_rx_process(struct goto free_frag; port = eth->ports[p]; + if (!port->dev) + goto free_frag; + -+ netdev = netdev_from_priv(port->dev); ++ netdev = port->dev->dev; if (!q->skb) { /* first buffer */ -- q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); -+ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); - if (!q->skb) - goto free_frag; + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -635,8 +640,8 @@ static int airoha_qdma_rx_process(struct + skb_reserve(q->skb, AIROHA_RX_HEADROOM); + __skb_put(q->skb, len); + skb_mark_for_recycle(q->skb); +- q->skb->dev = port->dev; +- q->skb->protocol = eth_type_trans(q->skb, port->dev); ++ q->skb->dev = netdev; ++ q->skb->protocol = eth_type_trans(q->skb, netdev); + q->skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(q->skb, qid); } else { /* scattered frame */ -@@ -888,7 +894,7 @@ static int airoha_qdma_rx_process(struct +@@ -654,7 +659,7 @@ static int airoha_qdma_rx_process(struct if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) continue; @@ -67,55 +65,33 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -1091,6 +1097,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -848,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; -+ struct net_device *netdev; ++ struct airoha_gdm_dev *dev; int j; if (!port) -@@ -1099,11 +1106,12 @@ static void airoha_qdma_wake_netdev_txqs +@@ -856,11 +862,12 @@ static void airoha_qdma_wake_netdev_txqs if (port->qdma != qdma) continue; - for (j = 0; j < port->dev->num_tx_queues; j++) { -+ netdev = netdev_from_priv(port->dev); -+ for (j = 0; j < netdev->num_tx_queues; j++) { ++ dev = port->dev; ++ for (j = 0; j < dev->dev->num_tx_queues; j++) { if (airoha_qdma_get_txq(qdma, j) != qid) continue; - netif_wake_subqueue(port->dev, j); -+ netif_wake_subqueue(netdev, j); ++ netif_wake_subqueue(dev->dev, j); } } q->txq_stopped = false; -@@ -1947,9 +1955,10 @@ static void airoha_update_hw_stats(struc +@@ -1700,19 +1707,20 @@ static void airoha_update_hw_stats(struc spin_unlock(&port->stats.lock); } --static void airoha_update_netdev_features(struct airoha_gdm_port *port) -+static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) - { -- struct airoha_eth *eth = port->eth; -+ struct airoha_gdm_port *port = dev->port; -+ struct airoha_eth *eth = dev->eth; - int i; - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -@@ -1959,7 +1968,7 @@ static void airoha_update_netdev_feature - if (!p) - continue; - -- netdev = p->dev; -+ netdev = netdev_from_priv(p->dev); - if (netdev->reg_state != NETREG_REGISTERED) - continue; - -@@ -1967,10 +1976,11 @@ static void airoha_update_netdev_feature - } - } - -static int airoha_dev_open(struct net_device *dev) +static int airoha_dev_open(struct net_device *netdev) { @@ -125,35 +101,7 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -1981,31 +1991,32 @@ static int airoha_dev_open(struct net_de - * the same QDMA if LRO is enabled on any device sharing it. - */ - if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { -- netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", -+ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", - qdma_id); - return -EBUSY; - } - - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ err = phylink_of_phy_connect(dev->phylink, -+ netdev->dev.of_node, 0); - if (err) { -- netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -- err); -+ netdev_err(netdev, "%s: could not attach PHY: %d\n", -+ __func__, err); - return err; - } - -- phylink_start(port->phylink); -+ phylink_start(dev->phylink); - } - #endif + u32 pse_port = FE_PSE_PORT_PPE1; - netif_tx_start_all_queues(dev); + netif_tx_start_all_queues(netdev); @@ -161,24 +109,12 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; - /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -- if (netdev_uses_dsa(dev) || port->id > 2) -+ if (netdev_uses_dsa(netdev) || port->id > 2) - airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), +- if (netdev_uses_dsa(dev)) ++ if (netdev_uses_dsa(netdev)) + airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else -@@ -2029,25 +2040,26 @@ static int airoha_dev_open(struct net_de - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), - pse_port); - -- if (dev->features & NETIF_F_GRO_HW) -- airoha_dev_lro_enable(port); -+ if (netdev->features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(dev); - -- airoha_update_netdev_features(port); -+ airoha_update_netdev_features(dev); - +@@ -1740,16 +1748,17 @@ static int airoha_dev_open(struct net_de return 0; } @@ -189,7 +125,6 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; int i; - netif_tx_disable(dev); @@ -200,24 +135,9 @@ Signed-off-by: Lorenzo Bianconi + for (i = 0; i < netdev->num_tx_queues; i++) + netdev_tx_reset_subqueue(netdev, i); - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); -@@ -2065,28 +2077,29 @@ static int airoha_dev_stop(struct net_de - } - } - -- airoha_update_netdev_features(port); -+ airoha_update_netdev_features(dev); - - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- phylink_stop(port->phylink); -- phylink_disconnect_phy(port->phylink); -+ phylink_stop(dev->phylink); -+ phylink_disconnect_phy(dev->phylink); - } - #endif - +@@ -1770,16 +1779,17 @@ static int airoha_dev_stop(struct net_de return 0; } @@ -239,7 +159,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2152,16 +2165,17 @@ static int airoha_set_gdm2_loopback(stru +@@ -1845,16 +1855,17 @@ static int airoha_set_gdm2_loopback(stru return 0; } @@ -257,12 +177,12 @@ Signed-off-by: Lorenzo Bianconi port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; - port->dev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, dev->dev_addr); -+ netdev->irq = port->qdma->irq_banks[0].irq; ++ dev->dev->irq = port->qdma->irq_banks[0].irq; + airoha_set_macaddr(port, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2186,10 +2200,11 @@ static int airoha_dev_init(struct net_de +@@ -1879,10 +1890,11 @@ static int airoha_dev_init(struct net_de return 0; } @@ -276,7 +196,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2208,36 +2223,39 @@ static void airoha_dev_get_stats64(struc +@@ -1901,36 +1913,39 @@ static void airoha_dev_get_stats64(struc } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -323,46 +243,7 @@ Signed-off-by: Lorenzo Bianconi } static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) -@@ -2300,10 +2318,11 @@ int airoha_get_fe_port(struct airoha_gdm - } - } - --static netdev_features_t airoha_dev_fix_features(struct net_device *dev, -+static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, - netdev_features_t features) - { -- struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - - if (qdma->users > 1) -@@ -2312,11 +2331,12 @@ static netdev_features_t airoha_dev_fix_ - return features; - } - --static int airoha_dev_set_features(struct net_device *dev, -+static int airoha_dev_set_features(struct net_device *netdev, - netdev_features_t features) - { -- netdev_features_t diff = dev->features ^ features; -- struct airoha_gdm_port *port = netdev_priv(dev); -+ netdev_features_t diff = netdev->features ^ features; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -2325,7 +2345,7 @@ static int airoha_dev_set_features(struc - return 0; - - if (features & NETIF_F_GRO_HW) -- airoha_dev_lro_enable(port); -+ airoha_dev_lro_enable(dev); - else - airoha_fe_lro_disable(eth, qdma_id); - -@@ -2333,9 +2353,10 @@ static int airoha_dev_set_features(struc +@@ -1994,9 +2009,10 @@ int airoha_get_fe_port(struct airoha_gdm } static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, @@ -375,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; -@@ -2348,7 +2369,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2009,7 +2025,7 @@ static netdev_tx_t airoha_dev_xmit(struc u8 fport; qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); @@ -384,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, qid / AIROHA_NUM_QOS_QUEUES) | -@@ -2384,7 +2405,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2045,7 +2061,7 @@ static netdev_tx_t airoha_dev_xmit(struc spin_lock_bh(&q->lock); @@ -393,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi nr_frags = 1 + skb_shinfo(skb)->nr_frags; if (q->queued + nr_frags >= q->ndesc) { -@@ -2408,9 +2429,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2069,9 +2085,9 @@ static netdev_tx_t airoha_dev_xmit(struc dma_addr_t addr; u32 val; @@ -405,7 +286,7 @@ Signed-off-by: Lorenzo Bianconi goto error_unmap; list_move_tail(&e->list, &tx_list); -@@ -2459,7 +2480,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2120,7 +2136,7 @@ static netdev_tx_t airoha_dev_xmit(struc error_unmap: list_for_each_entry(e, &tx_list, list) { @@ -414,7 +295,7 @@ Signed-off-by: Lorenzo Bianconi DMA_TO_DEVICE); e->dma_addr = 0; } -@@ -2468,25 +2489,27 @@ error_unmap: +@@ -2129,25 +2145,27 @@ error_unmap: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -447,7 +328,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2514,11 +2537,12 @@ static const struct ethtool_rmon_hist_ra +@@ -2175,11 +2193,12 @@ static const struct ethtool_rmon_hist_ra }; static void @@ -462,7 +343,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats *hw_stats = &port->stats; unsigned int start; -@@ -2543,11 +2567,12 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2204,11 +2223,12 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -477,7 +358,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2632,10 +2657,12 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2293,10 +2313,12 @@ static int airoha_qdma_set_tx_ets_sched( ARRAY_SIZE(w)); } @@ -492,7 +373,7 @@ Signed-off-by: Lorenzo Bianconi u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, REG_CNTR_VAL(channel << 1)); u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, -@@ -2897,11 +2924,12 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2558,11 +2580,12 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -507,7 +388,7 @@ Signed-off-by: Lorenzo Bianconi int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2921,20 +2949,22 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2582,20 +2605,22 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -534,7 +415,7 @@ Signed-off-by: Lorenzo Bianconi if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2944,9 +2974,10 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2605,9 +2630,10 @@ static int airoha_tc_htb_alloc_leaf_queu if (opt->command == TC_HTB_NODE_MODIFY) return 0; @@ -547,7 +428,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -3036,11 +3067,12 @@ static int airoha_tc_matchall_act_valida +@@ -2697,11 +2723,12 @@ static int airoha_tc_matchall_act_valida return 0; } @@ -562,7 +443,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -3075,18 +3107,19 @@ static int airoha_dev_tc_matchall(struct +@@ -2736,18 +2763,19 @@ static int airoha_dev_tc_matchall(struct static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -586,7 +467,7 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3133,47 +3166,51 @@ static int airoha_dev_setup_tc_block(str +@@ -2794,47 +2822,51 @@ static int airoha_dev_setup_tc_block(str } } @@ -650,7 +531,7 @@ Signed-off-by: Lorenzo Bianconi if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -3209,8 +3246,8 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2870,8 +2902,8 @@ static int airoha_tc_setup_qdisc_htb(str return 0; } @@ -661,7 +542,7 @@ Signed-off-by: Lorenzo Bianconi { switch (type) { case TC_SETUP_QDISC_ETS: -@@ -3283,13 +3320,18 @@ static void airoha_metadata_dst_free(str +@@ -2937,25 +2969,81 @@ static void airoha_metadata_dst_free(str } } @@ -683,95 +564,8 @@ Signed-off-by: Lorenzo Bianconi return true; } -@@ -3301,8 +3343,9 @@ static void airoha_mac_link_up(struct ph - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) - { -- struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -- phylink_config); -+ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, -+ phylink_config); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; -@@ -3358,65 +3401,121 @@ static int airoha_fill_available_pcs(str - &num_available_pcs); - } - --static int airoha_setup_phylink(struct net_device *dev) -+static int airoha_setup_phylink(struct net_device *netdev) - { -- struct airoha_gdm_port *port = netdev_priv(dev); -- struct device_node *np = dev->dev.of_node; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct device_node *np = netdev->dev.of_node; - phy_interface_t phy_mode; - struct phylink *phylink; - int err; - - err = of_get_phy_mode(np, &phy_mode); - if (err) { -- dev_err(&dev->dev, "incorrect phy-mode\n"); -+ dev_err(&netdev->dev, "incorrect phy-mode\n"); - return err; - } - -- port->phylink_config.dev = &dev->dev; -- port->phylink_config.type = PHYLINK_NETDEV; -- port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -- MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -- MAC_5000FD | MAC_10000FD; -+ dev->phylink_config.dev = &netdev->dev; -+ dev->phylink_config.type = PHYLINK_NETDEV; -+ dev->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; - -- err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -- &port->phylink_config.num_available_pcs); -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&netdev->dev), NULL, -+ &dev->phylink_config.num_available_pcs); - if (err) - return err; - -- port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ dev->phylink_config.fill_available_pcs = airoha_fill_available_pcs; - - __set_bit(PHY_INTERFACE_MODE_SGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_1000BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_2500BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_10GBASER, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_USXGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - -- phy_interface_copy(port->phylink_config.pcs_interfaces, -- port->phylink_config.supported_interfaces); -+ phy_interface_copy(dev->phylink_config.pcs_interfaces, -+ dev->phylink_config.supported_interfaces); - -- phylink = phylink_create(&port->phylink_config, -+ phylink = phylink_create(&dev->phylink_config, - of_fwnode_handle(np), - phy_mode, &airoha_phylink_ops); - if (IS_ERR(phylink)) - return PTR_ERR(phylink); - -- port->phylink = phylink; -+ dev->phylink = phylink; - - return err; + return false; } - #endif +static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, @@ -793,9 +587,11 @@ Signed-off-by: Lorenzo Bianconi + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; -+ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -+ netdev->features |= AIROHA_HW_FEATURES; -+ netdev->vlan_features = AIROHA_HW_FEATURES; ++ netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | ++ NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | ++ NETIF_F_HW_TC; ++ netdev->features |= netdev->hw_features; ++ netdev->vlan_features = netdev->hw_features; + netdev->dev.of_node = np; + SET_NETDEV_DEV(netdev, eth->dev); + @@ -815,18 +611,11 @@ Signed-off-by: Lorenzo Bianconi + } + + dev = netdev_priv(netdev); ++ dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; + -+#if defined(CONFIG_PCS_AIROHA) -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(netdev); -+ if (err) -+ return err; -+ } -+#endif -+ + return 0; +} + @@ -839,7 +628,7 @@ Signed-off-by: Lorenzo Bianconi int err, p; u32 id; -@@ -3438,58 +3537,22 @@ static int airoha_alloc_gdm_port(struct +@@ -2977,53 +3065,22 @@ static int airoha_alloc_gdm_port(struct return -EINVAL; } @@ -857,17 +646,20 @@ Signed-off-by: Lorenzo Bianconi - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -- dev->features |= AIROHA_HW_FEATURES; -- dev->vlan_features = AIROHA_HW_FEATURES; +- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- dev->features |= dev->hw_features; +- dev->vlan_features = dev->hw_features; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); -- + - /* reserve hw queues for HTB offloading */ - err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); - if (err) - return err; - +- - err = of_get_ethdev_address(np, dev); - if (err) { - if (err == -EPROBE_DEFER) @@ -888,32 +680,25 @@ Signed-off-by: Lorenzo Bianconi port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; eth->ports[p] = port; --#if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) { -- err = airoha_setup_phylink(dev); -- if (err) -- return err; -- } --#endif +- return airoha_metadata_dst_alloc(port); + err = airoha_metadata_dst_alloc(port); + if (err) + return err; - -- return airoha_metadata_dst_alloc(port); ++ + return airoha_alloc_gdm_device(eth, port, np); } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3503,7 +3566,7 @@ static int airoha_register_gdm_devices(s +@@ -3037,7 +3094,7 @@ static int airoha_register_gdm_devices(s if (!port) continue; - err = register_netdev(port->dev); -+ err = register_netdev(netdev_from_priv(port->dev)); ++ err = register_netdev(port->dev->dev); if (err) return err; } -@@ -3612,16 +3675,22 @@ error_napi_stop: +@@ -3146,12 +3203,14 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -922,25 +707,15 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; -- if (port->dev->reg_state == NETREG_REGISTERED) { -+ dev = port->dev; -+ if (dev) { -+ struct net_device *netdev = netdev_from_priv(dev); -+ -+ if (netdev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); - #endif +- if (port->dev->reg_state == NETREG_REGISTERED) - unregister_netdev(port->dev); -+ unregister_netdev(netdev); -+ } - } ++ dev = port->dev; ++ if (dev && dev->dev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(dev->dev); airoha_metadata_dst_free(port); } -@@ -3643,15 +3712,19 @@ static void airoha_remove(struct platfor + airoha_hw_cleanup(eth); +@@ -3172,11 +3231,14 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -949,49 +724,34 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ phylink_destroy(dev->phylink); - #endif - unregister_netdev(port->dev); -+ + dev = port->dev; + if (dev) -+ unregister_netdev(netdev_from_priv(dev)); ++ unregister_netdev(dev->dev); airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -547,17 +547,21 @@ struct airoha_qdma { +@@ -535,10 +535,15 @@ struct airoha_qdma { struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; }; --struct airoha_gdm_port { -- struct airoha_qdma *qdma; +struct airoha_gdm_dev { + struct airoha_gdm_port *port; - struct airoha_eth *eth; -- struct net_device *dev; -- int id; -- int nbq; - - #if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; - #endif ++ struct net_device *dev; ++ struct airoha_eth *eth; +}; + -+struct airoha_gdm_port { -+ struct airoha_qdma *qdma; + struct airoha_gdm_port { + struct airoha_qdma *qdma; +- struct airoha_eth *eth; +- struct net_device *dev; + struct airoha_gdm_dev *dev; -+ int id; -+ int nbq; - - struct airoha_hw_stats stats; + int id; + int nbq; -@@ -691,8 +695,8 @@ static inline bool airoha_qdma_is_lro_qu +@@ -662,8 +667,8 @@ static inline bool airoha_is_7583(struct } int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -1004,14 +764,14 @@ Signed-off-by: Lorenzo Bianconi u8 fport); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -299,12 +299,12 @@ static void airoha_ppe_foe_set_bridge_ad +@@ -298,12 +298,12 @@ static void airoha_ppe_foe_set_bridge_ad static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto, u8 dsfield) + int l4proto) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); @@ -1019,7 +779,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_foe_mac_info_common *l2; u8 smac_id = 0xf; -@@ -320,10 +320,11 @@ static int airoha_ppe_foe_entry_prepare( +@@ -319,10 +319,11 @@ static int airoha_ppe_foe_entry_prepare( hwe->ib1 = val; val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); @@ -1033,14 +793,14 @@ Signed-off-by: Lorenzo Bianconi val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) | FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, FE_PSE_PORT_CDM4); -@@ -333,12 +334,14 @@ static int airoha_ppe_foe_entry_prepare( +@@ -332,12 +333,14 @@ static int airoha_ppe_foe_entry_prepare( FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID, info.wcid); } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); - u8 pse_port, channel, priority; + struct airoha_gdm_port *port; + u8 pse_port, channel; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) @@ -1050,33 +810,12 @@ Signed-off-by: Lorenzo Bianconi if (dsa_port >= 0 || eth->ports[1]) pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; -@@ -1484,8 +1487,8 @@ void airoha_ppe_check_skb(struct airoha_ - +@@ -1473,7 +1476,7 @@ void airoha_ppe_check_skb(struct airoha_ void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) { -+ struct net_device *dev = netdev_from_priv(port->dev); struct airoha_eth *eth = port->qdma->eth; - struct net_device *dev = port->dev; ++ struct net_device *dev = port->dev->dev; const u8 *addr = dev->dev_addr; u32 val; ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -2760,6 +2760,17 @@ static inline void *netdev_priv(const st - return (void *)dev->priv; - } - -+/** -+ * netdev_from_priv() - get network device from priv -+ * @priv: network device private data -+ * -+ * Returns: net_device to which @priv belongs -+ */ -+static inline struct net_device *netdev_from_priv(const void *priv) -+{ -+ return container_of(priv, struct net_device, priv); -+} -+ - /* Set the sysfs physical device reference for the network logical device - * if set prior to registration will cause a symlink during initialization. - */ diff --git a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch similarity index 72% rename from target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch index b95371056fc..78388f5c630 100644 --- a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch @@ -1,10 +1,7 @@ -From f62cea6483cc55360863d66300790a5fb9de5f7c Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 528c5153a557f69482d91609a2a002ded22a3441 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Tue, 24 Feb 2026 18:43:05 +0100 -Subject: [PATCH 02/13] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev +Date: Wed, 27 May 2026 12:21:16 +0200 +Subject: [PATCH 2/6] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct Move airoha_qdma pointer from airoha_gdm_port struct to airoha_gdm_dev @@ -16,6 +13,8 @@ to the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-2-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 105 +++++++++++------------ drivers/net/ethernet/airoha/airoha_eth.h | 9 +- @@ -24,9 +23,9 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -81,9 +81,10 @@ static bool airhoa_is_phy_external(struc +@@ -71,9 +71,10 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) +static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -37,7 +36,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, reg; reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H -@@ -95,7 +96,7 @@ static void airoha_set_macaddr(struct ai +@@ -85,7 +86,7 @@ static void airoha_set_macaddr(struct ai airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); @@ -46,7 +45,7 @@ Signed-off-by: Lorenzo Bianconi } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -111,10 +112,10 @@ static void airoha_set_gdm_port_fwd_cfg( +@@ -101,10 +102,10 @@ static void airoha_set_gdm_port_fwd_cfg( FIELD_PREP(GDM_UCFQ_MASK, val)); } @@ -60,24 +59,7 @@ Signed-off-by: Lorenzo Bianconi u32 vip_port; vip_port = eth->soc->ops.get_vip_port(port, port->nbq); -@@ -485,8 +486,7 @@ static bool airoha_fe_lro_is_enabled(str - - static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - int i, lro_queue_index = 0; -@@ -1097,13 +1097,18 @@ static void airoha_qdma_wake_netdev_txqs - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *port = eth->ports[i]; -+ struct airoha_gdm_dev *dev; - struct net_device *netdev; - int j; - +@@ -859,10 +860,13 @@ static void airoha_qdma_wake_netdev_txqs if (!port) continue; @@ -89,8 +71,11 @@ Signed-off-by: Lorenzo Bianconi + if (dev->qdma != qdma) continue; - netdev = netdev_from_priv(port->dev); -@@ -1811,9 +1816,10 @@ static void airoha_qdma_stop_napi(struct +- dev = port->dev; + for (j = 0; j < dev->dev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; +@@ -1563,9 +1567,10 @@ static void airoha_qdma_stop_napi(struct } } @@ -103,17 +88,13 @@ Signed-off-by: Lorenzo Bianconi u32 val, i = 0; spin_lock(&port->stats.lock); -@@ -1981,7 +1987,7 @@ static int airoha_dev_open(struct net_de +@@ -1712,11 +1717,11 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; u32 pse_port = FE_PSE_PORT_PPE1; -@@ -2011,7 +2017,7 @@ static int airoha_dev_open(struct net_de - #endif netif_tx_start_all_queues(netdev); - err = airoha_set_vip_for_gdm_port(port, true); @@ -121,13 +102,12 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; -@@ -2052,12 +2058,12 @@ static int airoha_dev_stop(struct net_de +@@ -1752,11 +1757,11 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; int i; netif_tx_disable(netdev); @@ -136,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -@@ -2092,21 +2098,21 @@ static int airoha_dev_stop(struct net_de +@@ -1782,21 +1787,21 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -162,7 +142,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, pse_port, chan; int i, src_port; -@@ -2153,7 +2159,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1843,7 +1848,7 @@ static int airoha_set_gdm2_loopback(stru __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); for (i = 0; i < eth->soc->num_ppe; i++) @@ -170,21 +150,21 @@ Signed-off-by: Lorenzo Bianconi + airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); -@@ -2173,9 +2179,9 @@ static int airoha_dev_init(struct net_de + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); +@@ -1863,9 +1868,9 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -- netdev->irq = port->qdma->irq_banks[0].irq; +- dev->dev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, netdev->dev_addr); + dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -+ netdev->irq = dev->qdma->irq_banks[0].irq; ++ dev->dev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2184,7 +2190,7 @@ static int airoha_dev_init(struct net_de +@@ -1874,7 +1879,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; @@ -193,7 +173,7 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; } -@@ -2194,8 +2200,7 @@ static int airoha_dev_init(struct net_de +@@ -1884,8 +1889,7 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) @@ -203,7 +183,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2207,7 +2212,7 @@ static void airoha_dev_get_stats64(struc +@@ -1897,7 +1901,7 @@ static void airoha_dev_get_stats64(struc struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -212,7 +192,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); storage->rx_packets = port->stats.rx_ok_pkts; -@@ -2227,8 +2232,8 @@ static int airoha_dev_change_mtu(struct +@@ -1917,8 +1921,8 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -222,7 +202,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), GDM_LONG_LEN_MASK, -@@ -2302,10 +2307,10 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1992,10 +1996,10 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } @@ -236,27 +216,7 @@ Signed-off-by: Lorenzo Bianconi switch (eth->soc->version) { case 0x7583: -@@ -2322,8 +2327,7 @@ static netdev_features_t airoha_dev_fix_ - netdev_features_t features) - { - struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - - if (qdma->users > 1) - features &= ~NETIF_F_GRO_HW; -@@ -2336,8 +2340,7 @@ static int airoha_dev_set_features(struc - { - netdev_features_t diff = netdev->features ^ features; - struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - -@@ -2356,8 +2359,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2012,8 +2016,7 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -266,7 +226,7 @@ Signed-off-by: Lorenzo Bianconi u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; struct netdev_queue *txq; -@@ -2395,7 +2397,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2051,7 +2054,7 @@ static netdev_tx_t airoha_dev_xmit(struc } } @@ -275,7 +235,7 @@ Signed-off-by: Lorenzo Bianconi msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); -@@ -2498,8 +2500,7 @@ static void airoha_ethtool_get_drvinfo(s +@@ -2154,8 +2157,7 @@ static void airoha_ethtool_get_drvinfo(s struct ethtool_drvinfo *info) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -285,7 +245,7 @@ Signed-off-by: Lorenzo Bianconi strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -@@ -2512,7 +2513,7 @@ static void airoha_ethtool_get_mac_stats +@@ -2168,7 +2170,7 @@ static void airoha_ethtool_get_mac_stats struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -294,7 +254,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); stats->FramesTransmittedOK = port->stats.tx_ok_pkts; -@@ -2552,7 +2553,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2208,7 +2210,7 @@ airoha_ethtool_get_rmon_stats(struct net ARRAY_SIZE(hw_stats->rx_len) + 1); *ranges = airoha_ethtool_rmon_ranges; @@ -303,7 +263,7 @@ Signed-off-by: Lorenzo Bianconi do { int i; -@@ -2572,18 +2573,17 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2228,18 +2230,17 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -324,7 +284,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2591,13 +2591,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2247,13 +2248,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -340,7 +300,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2663,9 +2662,9 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2319,9 +2319,9 @@ static int airoha_qdma_get_tx_ets_stats( struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -352,7 +312,7 @@ Signed-off-by: Lorenzo Bianconi REG_CNTR_VAL((channel << 1) + 1)); u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + (fwd_tx_packets - port->fwd_tx_packets); -@@ -2929,17 +2928,16 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2585,17 +2585,16 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -372,7 +332,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -2989,11 +2987,11 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2645,11 +2644,11 @@ static int airoha_tc_htb_alloc_leaf_queu return 0; } @@ -386,7 +346,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -3072,7 +3070,6 @@ static int airoha_dev_tc_matchall(struct +@@ -2728,7 +2727,6 @@ static int airoha_dev_tc_matchall(struct { enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -394,7 +354,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -3097,7 +3094,7 @@ static int airoha_dev_tc_matchall(struct +@@ -2753,7 +2751,7 @@ static int airoha_dev_tc_matchall(struct fallthrough; } case TC_CLSMATCHALL_DESTROY: @@ -403,7 +363,7 @@ Signed-off-by: Lorenzo Bianconi unit_type); default: return -EOPNOTSUPP; -@@ -3109,8 +3106,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2765,8 +2763,7 @@ static int airoha_dev_setup_tc_block_cb( { struct net_device *netdev = cb_priv; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -413,26 +373,15 @@ Signed-off-by: Lorenzo Bianconi if (!tc_can_offload(netdev)) return -EOPNOTSUPP; -@@ -3346,7 +3342,7 @@ static void airoha_mac_link_up(struct ph - struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, - phylink_config); - struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; - --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -549,6 +549,7 @@ struct airoha_qdma { +@@ -537,12 +537,12 @@ struct airoha_qdma { struct airoha_gdm_dev { struct airoha_gdm_port *port; + struct airoha_qdma *qdma; + struct net_device *dev; struct airoha_eth *eth; - - #if defined(CONFIG_PCS_AIROHA) -@@ -558,7 +559,6 @@ struct airoha_gdm_dev { }; struct airoha_gdm_port { @@ -440,8 +389,8 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev; int id; int nbq; -@@ -694,19 +694,18 @@ static inline bool airoha_qdma_is_lro_qu - return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); +@@ -666,19 +666,18 @@ static inline bool airoha_is_7583(struct + return eth->soc->version == 0x7583; } -int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -465,7 +414,7 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -85,9 +85,9 @@ static u32 airoha_ppe_get_timestamp(stru +@@ -84,9 +84,9 @@ static u32 airoha_ppe_get_timestamp(stru AIROHA_FOE_IB1_BIND_TIMESTAMP); } @@ -477,7 +426,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_eth *eth = qdma->eth; u8 qdma_id = qdma - ð->qdma[0]; u32 fe_cpu_port; -@@ -181,8 +181,8 @@ static void airoha_ppe_hw_init(struct ai +@@ -180,8 +180,8 @@ static void airoha_ppe_hw_init(struct ai if (!port) continue; @@ -488,18 +437,18 @@ Signed-off-by: Lorenzo Bianconi } } } -@@ -1485,11 +1485,12 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1473,11 +1473,12 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } -void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) { -- struct net_device *dev = netdev_from_priv(port->dev); - struct airoha_eth *eth = port->qdma->eth; +- struct net_device *dev = port->dev->dev; - const u8 *addr = dev->dev_addr; -+ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; ++ struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; u32 val; diff --git a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch similarity index 75% rename from target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch rename to target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch index 64ed102d3a6..072089fe8b9 100644 --- a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch +++ b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch @@ -1,10 +1,7 @@ -From 32bfd008c19f9ad55514181d8cd02e14bf384475 Mon Sep 17 00:00:00 2001 -Message-ID: <32bfd008c19f9ad55514181d8cd02e14bf384475.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From eca4f59b536780a56bd22db03fe5465e8e978f36 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 13 Dec 2025 10:06:45 +0100 -Subject: [PATCH 03/13] net: airoha: Rely on airoha_gdm_dev pointer in +Date: Wed, 27 May 2026 12:21:17 +0200 +Subject: [PATCH 3/6] net: airoha: Rely on airoha_gdm_dev pointer in airoha_is_lan_gdm_port() Rename airoha_is_lan_gdm_port in airoha_is_lan_gdm_dev. Moreover, rely @@ -15,6 +12,8 @@ the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-3-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 6 ++---- drivers/net/ethernet/airoha/airoha_eth.h | 4 +++- @@ -23,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -83,12 +83,10 @@ static bool airhoa_is_phy_external(struc +@@ -73,12 +73,10 @@ static void airoha_qdma_irq_disable(stru static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) { @@ -37,18 +36,18 @@ Signed-off-by: Lorenzo Bianconi val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); -@@ -2179,7 +2177,7 @@ static int airoha_dev_init(struct net_de +@@ -1868,7 +1866,7 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; - netdev->irq = dev->qdma->irq_banks[0].irq; + dev->dev->irq = dev->qdma->irq_banks[0].irq; airoha_set_macaddr(dev, netdev->dev_addr); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -663,8 +663,10 @@ static inline u16 airoha_qdma_get_txq(st +@@ -647,8 +647,10 @@ static inline u16 airoha_qdma_get_txq(st return qid % ARRAY_SIZE(qdma->q_tx); } @@ -62,7 +61,7 @@ Signed-off-by: Lorenzo Bianconi * phy module. --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -367,7 +367,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -362,7 +362,7 @@ static int airoha_ppe_foe_entry_prepare( /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. */ diff --git a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch similarity index 80% rename from target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch index 3bbcaab9366..b35b1b0a698 100644 --- a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch @@ -1,10 +1,7 @@ -From 634d75285db77f3385aa85a1bf2b185396225100 Mon Sep 17 00:00:00 2001 -Message-ID: <634d75285db77f3385aa85a1bf2b185396225100.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 069626af6dfaa26b82119900f4aff1fec38d5983 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:35:32 +0200 -Subject: [PATCH 04/13] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:18 +0200 +Subject: [PATCH 4/6] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, qos_sq_bmap field can be overwritten with the @@ -14,7 +11,10 @@ airoha_gdm_port struct to airoha_gdm_dev one. Add qos_channel_map bitmap in airoha_qdma struct to track if a shared QDMA channel is already in use by another net_device. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-4-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 58 +++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 6 ++- @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2945,30 +2945,46 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2602,30 +2602,40 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -36,7 +36,6 @@ Signed-off-by: Lorenzo Bianconi - int err, num_tx_queues = netdev->real_num_tx_queues; - struct airoha_gdm_dev *dev = netdev_priv(netdev); - struct airoha_gdm_port *port = dev->port; -+ int err; if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); @@ -46,13 +45,7 @@ Signed-off-by: Lorenzo Bianconi - err = airoha_qdma_set_tx_rate_limit(netdev, channel, rate, - opt->quantum); - if (err) { -+ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); -+ if (err) - NL_SET_ERR_MSG_MOD(opt->extack, - "failed configuring htb offload"); -- return err; -+ -+ return err; ++ return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); +} + +static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, @@ -67,7 +60,9 @@ Signed-off-by: Lorenzo Bianconi + * in use by another net_device running on the same QDMA block. + */ + if (test_and_set_bit(channel, qdma->qos_channel_map)) { -+ NL_SET_ERR_MSG_MOD(opt->extack, + NL_SET_ERR_MSG_MOD(opt->extack, +- "failed configuring htb offload"); +- return err; + "qdma qos channel already in use"); + return -EBUSY; } @@ -80,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); if (err) { -@@ -2976,13 +2992,17 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2633,13 +2643,17 @@ static int airoha_tc_htb_alloc_leaf_queu opt->quantum); NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); @@ -100,7 +95,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev, -@@ -3163,11 +3183,13 @@ static int airoha_dev_setup_tc_block(str +@@ -2820,11 +2834,13 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -116,7 +111,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, -@@ -3175,9 +3197,8 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2832,9 +2848,8 @@ static int airoha_tc_htb_delete_leaf_que { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -127,7 +122,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3190,10 +3211,9 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2847,10 +2862,9 @@ static int airoha_tc_htb_delete_leaf_que static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -139,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi airoha_tc_remove_htb_queue(netdev, q); return 0; -@@ -3204,9 +3224,8 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2861,9 +2875,8 @@ static int airoha_tc_get_htb_get_leaf_qu { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -150,7 +145,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3225,6 +3244,7 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2882,6 +2895,7 @@ static int airoha_tc_setup_qdisc_htb(str case TC_HTB_DESTROY: return airoha_tc_htb_destroy(dev); case TC_HTB_NODE_MODIFY: @@ -160,7 +155,7 @@ Signed-off-by: Lorenzo Bianconi case TC_HTB_LEAF_DEL: --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -545,6 +545,8 @@ struct airoha_qdma { +@@ -533,6 +533,8 @@ struct airoha_qdma { struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; @@ -169,16 +164,16 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_dev { -@@ -556,6 +558,8 @@ struct airoha_gdm_dev { - struct phylink *phylink; - struct phylink_config phylink_config; - #endif +@@ -540,6 +542,8 @@ struct airoha_gdm_dev { + struct airoha_qdma *qdma; + struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); }; struct airoha_gdm_port { -@@ -565,8 +569,6 @@ struct airoha_gdm_port { +@@ -549,8 +553,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch similarity index 76% rename from target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch index dfe8662b563..cb62a387b61 100644 --- a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch @@ -1,11 +1,8 @@ -From 00272dbf6a52241a21145631f22dc5f03891078b Mon Sep 17 00:00:00 2001 -Message-ID: <00272dbf6a52241a21145631f22dc5f03891078b.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 962c17dd287887aa87a6f30d64239d7e1e4e05fa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:47:08 +0200 -Subject: [PATCH 05/13] net: airoha: Move {cpu,fwd}_tx_packets in - airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:19 +0200 +Subject: [PATCH 5/6] net: airoha: Move {cpu,fwd}_tx_packets in airoha_gdm_dev + struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, cpu_tx_packets and fwd_tx_packets fields can @@ -13,7 +10,10 @@ be overwritten with the value from a different QDMA block. In order to fix the issue move cpu_tx_packets and fwd_tx_packets fields from airoha_gdm_port struct to airoha_gdm_dev one. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-5-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +++---- @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2658,19 +2658,17 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2315,19 +2315,17 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -50,8 +50,8 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -560,6 +560,9 @@ struct airoha_gdm_dev { - #endif +@@ -544,6 +544,9 @@ struct airoha_gdm_dev { + struct airoha_eth *eth; DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); + /* qos stats counters */ @@ -60,7 +60,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_port { -@@ -569,10 +572,6 @@ struct airoha_gdm_port { +@@ -553,10 +556,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch new file mode 100644 index 00000000000..eaf4d8e426e --- /dev/null +++ b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch @@ -0,0 +1,38 @@ +From 842a7ee50d68d66afef4536bf3abdaaed2e0e5f5 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 27 May 2026 12:21:20 +0200 +Subject: [PATCH 6/6] net: airoha: Rename airoha_set_gdm2_loopback in + airoha_enable_gdm2_loopback + +This is a preliminary patch in order to allow the user to select if the +configured device will be used as hw lan or wan. +Please not this patch does not introduce any logical changes, just +cosmetic ones. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-6-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1796,7 +1796,7 @@ static int airoha_dev_set_macaddr(struct + return 0; + } + +-static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) ++static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) + { + struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; +@@ -1877,7 +1877,7 @@ static int airoha_dev_init(struct net_de + if (!eth->ports[1]) { + int err; + +- err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } diff --git a/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch b/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch new file mode 100644 index 00000000000..7ea6058ac48 --- /dev/null +++ b/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch @@ -0,0 +1,37 @@ +From b38cae85d1c45ff189d7ecb6ac36f41cdc3d84d0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 2 Jun 2026 11:21:04 +0200 +Subject: [PATCH] net: airoha: Fix use-after-free in metadata dst teardown + +airoha_metadata_dst_free() runs metadata_dst_free() which frees the +metadata_dst with kfree() immediately, bypassing the RCU grace period. +In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from +the skb to the metadata_dst. This function requires RCU read-side +protection and the dst must remain valid until all RCU readers complete. +Since metadata_dst_free() calls kfree() directly, an use-after-free can +occur if any skb still holds a noref pointer to the dst when the driver +tears it down. +Replace metadata_dst_free() with dst_release() which properly goes +through the refcount path: when the refcount drops to zero, it schedules +the actual free via call_rcu_hurry(), ensuring all RCU readers have +completed before the memory is freed. + +Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-1-3aaa99d83351@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2972,7 +2972,7 @@ static void airoha_metadata_dst_free(str + if (!port->dsa_meta[i]) + continue; + +- metadata_dst_free(port->dsa_meta[i]); ++ dst_release(&port->dsa_meta[i]->dst); + } + } + diff --git a/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch new file mode 100644 index 00000000000..6e4807b0e38 --- /dev/null +++ b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch @@ -0,0 +1,40 @@ +From 144969cd80c5227c2b19fe5f644d6eebd61be586 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 12:30:01 +0200 +Subject: [PATCH] net: airoha: Report extack error to the user if + airoha_tc_htb_modify_queue() fails + +Report an extack error message in airoha_tc_htb_modify_queue routine if +airoha_qdma_set_tx_rate_limit() fails. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260603-airoha_tc_htb_modify_queue-err-message-v1-1-33ec3ab997d9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2605,13 +2605,19 @@ static int airoha_tc_htb_modify_queue(st + { + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; + u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ ++ int err; + + if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { + NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); + return -EINVAL; + } + +- return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ if (err) ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed configuring htb offload"); ++ ++ return err; + } + + static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch b/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch new file mode 100644 index 00000000000..830198151c8 --- /dev/null +++ b/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch @@ -0,0 +1,41 @@ +From f9f25118faa4dd2b6e3d14a03d123bbdbd59925d Mon Sep 17 00:00:00 2001 +From: ZhaoJinming +Date: Thu, 4 Jun 2026 15:03:52 +0800 +Subject: [PATCH] net: airoha: Add NULL check for of_reserved_mem_lookup() in + airoha_qdma_init_hfwd_queues() + +of_reserved_mem_lookup() may return NULL if the reserved memory region +referenced by the "memory-region" phandle is not found in the reserved +memory table (e.g. due to a misconfigured DTS or a removed +memory-region node). The current code dereferences the returned +pointer without checking for NULL, leading to a kernel NULL pointer +dereference at the following lines: + + dma_addr = rmem->base; // line 1156 + num_desc = div_u64(rmem->size, buf_size); // line 1160 + +Add a NULL check after of_reserved_mem_lookup() and return -ENODEV if +the lookup fails, which is consistent with the existing error handling +for of_parse_phandle() failure in the same code block. + +Fixes: 3a1ce9e3d01b ("net: airoha: Add the capability to allocate hwfd buffers via reserved-memory") +Cc: stable@vger.kernel.org +Signed-off-by: ZhaoJinming +Acked-by: Lorenzo Bianconi +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1159,6 +1159,9 @@ static int airoha_qdma_init_hfwd_queues( + + rmem = of_reserved_mem_lookup(np); + of_node_put(np); ++ if (!rmem) ++ return -ENODEV; ++ + dma_addr = rmem->base; + /* Compute the number of hw descriptors according to the + * reserved memory size and the payload buffer size diff --git a/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch new file mode 100644 index 00000000000..f4da9bf7425 --- /dev/null +++ b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch @@ -0,0 +1,125 @@ +From 4408f520680990042a1e6bfdf3cef217a1abf152 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 08:00:16 +0200 +Subject: [PATCH 1/5] net: airoha: Remove private net_device pointer in + airoha_gdm_dev struct + +Remove redundant net_device pointer inside airoha_gdm_dev struct and +rely on netdev_from_priv routine instead. Please note this patch does +not introduce any logical change, just code refactoring. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-2-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 23 ++++++++++++++--------- + drivers/net/ethernet/airoha/airoha_eth.h | 1 - + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + 3 files changed, 15 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -629,7 +629,7 @@ static int airoha_qdma_rx_process(struct + if (!port->dev) + goto free_frag; + +- netdev = port->dev->dev; ++ netdev = netdev_from_priv(port->dev); + if (!q->skb) { /* first buffer */ + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -853,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; + struct airoha_gdm_dev *dev; ++ struct net_device *netdev; + int j; + + if (!port) +@@ -865,11 +866,12 @@ static void airoha_qdma_wake_netdev_txqs + if (dev->qdma != qdma) + continue; + +- for (j = 0; j < dev->dev->num_tx_queues; j++) { ++ netdev = netdev_from_priv(dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; + +- netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); + } + } + q->txq_stopped = false; +@@ -1870,7 +1872,7 @@ static int airoha_dev_init(struct net_de + + /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; +- dev->dev->irq = dev->qdma->irq_banks[0].irq; ++ netdev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); + + switch (port->id) { +@@ -3047,7 +3049,6 @@ static int airoha_alloc_gdm_device(struc + } + + dev = netdev_priv(netdev); +- dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; +@@ -3110,7 +3111,7 @@ static int airoha_register_gdm_devices(s + if (!port) + continue; + +- err = register_netdev(port->dev->dev); ++ err = register_netdev(netdev_from_priv(port->dev)); + if (err) + return err; + } +@@ -3225,8 +3226,12 @@ error_napi_stop: + continue; + + dev = port->dev; +- if (dev && dev->dev->reg_state == NETREG_REGISTERED) +- unregister_netdev(dev->dev); ++ if (dev) { ++ struct net_device *netdev = netdev_from_priv(dev); ++ ++ if (netdev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(netdev); ++ } + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +@@ -3254,7 +3259,7 @@ static void airoha_remove(struct platfor + + dev = port->dev; + if (dev) +- unregister_netdev(dev->dev); ++ unregister_netdev(netdev_from_priv(dev)); + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -540,7 +540,6 @@ struct airoha_qdma { + struct airoha_gdm_dev { + struct airoha_gdm_port *port; + struct airoha_qdma *qdma; +- struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1475,8 +1475,8 @@ void airoha_ppe_check_skb(struct airoha_ + + void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) + { ++ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; +- struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; + u32 val; diff --git a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch similarity index 77% rename from target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch rename to target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch index 870b24371b5..922d1057f5b 100644 --- a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch +++ b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch @@ -1,11 +1,8 @@ -From 8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad Mon Sep 17 00:00:00 2001 -Message-ID: <8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From a9c2ca61fec7706574c009d8f1898ca392368f89 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:27:48 +0100 -Subject: [PATCH 06/13] net: airoha: Support multiple net_devices for a single - FE GDM port +Date: Wed, 3 Jun 2026 08:00:17 +0200 +Subject: [PATCH 2/5] net: airoha: Support multiple net_devices for a single FE + GDM port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -48,15 +45,17 @@ logics for the net_device type connected to GDM3 or GDM4. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-3-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 274 +++++++++++++++++------ - drivers/net/ethernet/airoha/airoha_eth.h | 10 +- - drivers/net/ethernet/airoha/airoha_ppe.c | 13 +- - 3 files changed, 228 insertions(+), 69 deletions(-) + drivers/net/ethernet/airoha/airoha_eth.c | 280 +++++++++++++++++------ + drivers/net/ethernet/airoha/airoha_eth.h | 8 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 26 ++- + 3 files changed, 237 insertions(+), 77 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -116,7 +116,7 @@ static int airoha_set_vip_for_gdm_port(s +@@ -106,7 +106,7 @@ static int airoha_set_vip_for_gdm_port(s struct airoha_eth *eth = dev->eth; u32 vip_port; @@ -65,7 +64,7 @@ Signed-off-by: Lorenzo Bianconi if (enable) { airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); -@@ -646,30 +646,26 @@ static int airoha_qdma_fill_rx_queue(str +@@ -566,24 +566,26 @@ static int airoha_qdma_fill_rx_queue(str return nframes; } @@ -80,14 +79,8 @@ Signed-off-by: Lorenzo Bianconi - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -- case 0x18: -- port = 3; /* GDM4 */ -- break; -- case 0x16: -- port = 2; /* GDM3 */ -- break; - case 0x10 ... 0x14: -- port = 0; /* GDM1 */ +- port = 0; - break; - case 0x2 ... 0x4: - port = sport - 1; @@ -97,11 +90,11 @@ Signed-off-by: Lorenzo Bianconi - } + if (eth->soc->ops.get_dev_from_sport(desc, &p, &d)) + return ERR_PTR(-ENODEV); -+ -+ if (p >= ARRAY_SIZE(eth->ports)) -+ return ERR_PTR(-ENODEV); - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; ++ if (p >= ARRAY_SIZE(eth->ports)) ++ return ERR_PTR(-ENODEV); ++ + port = eth->ports[p]; + if (!port) + return ERR_PTR(-ENODEV); @@ -112,8 +105,8 @@ Signed-off-by: Lorenzo Bianconi + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } - static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, -@@ -841,9 +837,9 @@ static int airoha_qdma_rx_process(struct + static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) +@@ -598,9 +600,9 @@ static int airoha_qdma_rx_process(struct struct airoha_queue_entry *e = &q->entry[q->tail]; struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; @@ -125,7 +118,7 @@ Signed-off-by: Lorenzo Bianconi struct page *page; desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -@@ -864,15 +860,11 @@ static int airoha_qdma_rx_process(struct +@@ -621,15 +623,11 @@ static int airoha_qdma_rx_process(struct if (!len || data_len < len) goto free_frag; @@ -142,9 +135,9 @@ Signed-off-by: Lorenzo Bianconi - netdev = netdev_from_priv(port->dev); + netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ - q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); - if (!q->skb) -@@ -893,6 +885,8 @@ static int airoha_qdma_rx_process(struct + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -659,6 +657,8 @@ static int airoha_qdma_rx_process(struct continue; if (netdev_uses_dsa(netdev)) { @@ -153,7 +146,7 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -1095,26 +1089,29 @@ static void airoha_qdma_wake_netdev_txqs +@@ -852,26 +852,29 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -178,7 +171,7 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; -- netdev = netdev_from_priv(port->dev); +- netdev = netdev_from_priv(dev); - for (j = 0; j < netdev->num_tx_queues; j++) { - if (airoha_qdma_get_txq(qdma, j) != qid) + if (dev->qdma != qdma) @@ -195,58 +188,21 @@ Signed-off-by: Lorenzo Bianconi } } q->txq_stopped = false; -@@ -1961,22 +1958,32 @@ static void airoha_update_hw_stats(struc - - static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_port *port = dev->port; - struct airoha_eth *eth = dev->eth; - int i; - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -- struct airoha_gdm_port *p = eth->ports[i]; -- struct net_device *netdev; -+ struct airoha_gdm_port *port = eth->ports[i]; -+ int j; - -- if (!p) -+ if (!port) - continue; - -- netdev = netdev_from_priv(p->dev); -- if (netdev->reg_state != NETREG_REGISTERED) -- continue; -+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { -+ struct airoha_gdm_dev *iter_dev = port->devs[j]; -+ struct net_device *netdev; -+ -+ if (!iter_dev || iter_dev == dev) -+ continue; -+ -+ if (iter_dev->qdma != dev->qdma) -+ continue; -+ -+ netdev = netdev_from_priv(iter_dev); -+ if (netdev->reg_state != NETREG_REGISTERED) -+ continue; - -- netdev_update_features(netdev); -+ netdev_update_features(netdev); -+ } - } - } - -@@ -2037,7 +2044,8 @@ static int airoha_dev_open(struct net_de +@@ -1745,11 +1748,9 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); - qdma->users++; + atomic_inc(&qdma->users); -- if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { +- if (port->id == AIROHA_GDM2_IDX && +- airoha_ppe_is_enabled(qdma->eth, 1)) { +- /* For PPE2 always use secondary cpu port. */ + if (!airoha_is_lan_gdm_dev(dev) && -+ airoha_ppe_is_enabled(eth, 1)) { - /* For PPE2 always use secondary cpu port. */ ++ airoha_ppe_is_enabled(qdma->eth, 1)) pse_port = FE_PSE_PORT_PPE2; - } -@@ -2143,7 +2151,7 @@ static int airoha_set_gdm2_loopback(stru +- } + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + pse_port); + +@@ -1837,7 +1838,7 @@ static int airoha_enable_gdm2_loopback(s airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -255,16 +211,16 @@ Signed-off-by: Lorenzo Bianconi if (src_port < 0) return src_port; -@@ -2160,7 +2168,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1854,7 +1855,7 @@ static int airoha_enable_gdm2_loopback(s airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -- u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); +- u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq); airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, __field_prep(mask, AIROHA_GDM2_IDX)); -@@ -2174,7 +2182,7 @@ static int airoha_dev_init(struct net_de +@@ -1868,7 +1869,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; @@ -273,7 +229,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; -@@ -2197,8 +2205,8 @@ static int airoha_dev_init(struct net_de +@@ -1891,8 +1892,8 @@ static int airoha_dev_init(struct net_de break; } @@ -284,7 +240,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2396,7 +2404,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2058,7 +2059,8 @@ static netdev_tx_t airoha_dev_xmit(struc } fport = airoha_get_fe_port(dev); @@ -294,7 +250,7 @@ Signed-off-by: Lorenzo Bianconi FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); q = &qdma->q_tx[qid]; -@@ -3339,12 +3348,15 @@ bool airoha_is_valid_gdm_dev(struct airo +@@ -2994,12 +2996,15 @@ bool airoha_is_valid_gdm_dev(struct airo for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -312,7 +268,7 @@ Signed-off-by: Lorenzo Bianconi } return false; -@@ -3468,10 +3480,11 @@ static int airoha_setup_phylink(struct n +@@ -3007,10 +3012,11 @@ bool airoha_is_valid_gdm_dev(struct airo static int airoha_alloc_gdm_device(struct airoha_eth *eth, struct airoha_gdm_port *port, @@ -326,15 +282,15 @@ Signed-off-by: Lorenzo Bianconi int err; netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev), -@@ -3489,7 +3502,6 @@ static int airoha_alloc_gdm_device(struc - netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; - netdev->features |= AIROHA_HW_FEATURES; - netdev->vlan_features = AIROHA_HW_FEATURES; +@@ -3030,7 +3036,6 @@ static int airoha_alloc_gdm_device(struc + NETIF_F_HW_TC; + netdev->features |= netdev->hw_features; + netdev->vlan_features = netdev->hw_features; - netdev->dev.of_node = np; SET_NETDEV_DEV(netdev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3507,10 +3519,24 @@ static int airoha_alloc_gdm_device(struc +@@ -3048,10 +3053,24 @@ static int airoha_alloc_gdm_device(struc netdev->dev_addr); } @@ -358,9 +314,9 @@ Signed-off-by: Lorenzo Bianconi + dev->nbq = nbq; + port->devs[index] = dev; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -@@ -3528,7 +3554,8 @@ static int airoha_alloc_gdm_port(struct + return 0; + } +@@ -3061,7 +3080,8 @@ static int airoha_alloc_gdm_port(struct { const __be32 *id_ptr = of_get_property(np, "reg", NULL); struct airoha_gdm_port *port; @@ -370,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi u32 id; if (!id_ptr) { -@@ -3556,15 +3583,51 @@ static int airoha_alloc_gdm_port(struct +@@ -3089,15 +3109,51 @@ static int airoha_alloc_gdm_port(struct u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); port->id = id; @@ -425,7 +381,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3573,14 +3636,22 @@ static int airoha_register_gdm_devices(s +@@ -3106,14 +3162,22 @@ static int airoha_register_gdm_devices(s for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -452,7 +408,7 @@ Signed-off-by: Lorenzo Bianconi } set_bit(DEV_STATE_REGISTERED, ð->state); -@@ -3687,15 +3758,19 @@ error_napi_stop: +@@ -3220,17 +3284,22 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -473,18 +429,13 @@ Signed-off-by: Lorenzo Bianconi + continue; + netdev = netdev_from_priv(dev); - if (netdev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -@@ -3703,6 +3778,7 @@ error_napi_stop: - #endif + if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); - } + of_node_put(netdev->dev.of_node); } airoha_metadata_dst_free(port); } -@@ -3724,19 +3800,27 @@ static void airoha_remove(struct platfor +@@ -3252,14 +3321,22 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -494,6 +445,9 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; +- dev = port->dev; +- if (dev) +- unregister_netdev(netdev_from_priv(dev)); + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { + struct airoha_gdm_dev *dev = port->devs[j]; + struct net_device *netdev; @@ -501,16 +455,6 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + - #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(dev->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); - #endif - -- dev = port->dev; -- if (dev) -- unregister_netdev(netdev_from_priv(dev)); + netdev = netdev_from_priv(dev); + unregister_netdev(netdev); + of_node_put(netdev->dev.of_node); @@ -518,7 +462,7 @@ Signed-off-by: Lorenzo Bianconi airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3798,6 +3882,39 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3322,6 +3399,39 @@ static u32 airoha_en7581_get_vip_port(st return 0; } @@ -556,9 +500,9 @@ Signed-off-by: Lorenzo Bianconi +} + static const char * const an7583_xsi_rsts_names[] = { + "xsi-mac", "hsi0-mac", - "hsi1-mac", -@@ -3846,6 +3963,36 @@ static u32 airoha_an7583_get_vip_port(st +@@ -3371,6 +3481,36 @@ static u32 airoha_an7583_get_vip_port(st return 0; } @@ -595,7 +539,7 @@ Signed-off-by: Lorenzo Bianconi static const struct airoha_eth_soc_data en7581_soc_data = { .version = 0x7581, .xsi_rsts_names = en7581_xsi_rsts_names, -@@ -3854,6 +4001,7 @@ static const struct airoha_eth_soc_data +@@ -3379,6 +3519,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_en7581_get_sport, .get_vip_port = airoha_en7581_get_vip_port, @@ -603,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi }, }; -@@ -3865,6 +4013,7 @@ static const struct airoha_eth_soc_data +@@ -3390,6 +3531,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_an7583_get_sport, .get_vip_port = airoha_an7583_get_vip_port, @@ -621,7 +565,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_NUM_QDMA 2 #define AIROHA_MAX_NUM_IRQ_BANKS 4 #define AIROHA_MAX_DSA_PORTS 7 -@@ -563,12 +564,13 @@ struct airoha_gdm_dev { +@@ -546,12 +547,13 @@ struct airoha_gdm_dev { /* qos stats counters */ u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -637,7 +581,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats stats; -@@ -604,6 +606,8 @@ struct airoha_eth_soc_data { +@@ -587,6 +589,8 @@ struct airoha_eth_soc_data { struct { int (*get_sport)(struct airoha_gdm_port *port, int nbq); u32 (*get_vip_port)(struct airoha_gdm_port *port, int nbq); @@ -648,7 +592,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -168,9 +168,7 @@ static void airoha_ppe_hw_init(struct ai +@@ -167,9 +167,7 @@ static void airoha_ppe_hw_init(struct ai airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i), PPE_FLOW_CFG_IP6_6RD_MASK); @@ -659,7 +603,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_PPE_MTU(i, p), FP0_EGRESS_MTU_MASK | FP1_EGRESS_MTU_MASK, -@@ -178,11 +176,27 @@ static void airoha_ppe_hw_init(struct ai +@@ -177,11 +175,27 @@ static void airoha_ppe_hw_init(struct ai AIROHA_MAX_MTU) | FIELD_PREP(FP1_EGRESS_MTU_MASK, AIROHA_MAX_MTU)); diff --git a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch similarity index 70% rename from target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch rename to target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch index 7dc33792bd8..cc8627fe541 100644 --- a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch +++ b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch @@ -1,10 +1,7 @@ -From de856a5b802cf030c8e242e98df3bc88446a4ea1 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 99b9d095d71e5cb84121dacce2ac217aad9b174f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 20 Mar 2026 11:09:40 +0100 -Subject: [PATCH 07/13] net: airoha: Do not stop GDM port if it is shared +Date: Wed, 3 Jun 2026 08:00:18 +0200 +Subject: [PATCH 3/5] net: airoha: Do not stop GDM port if it is shared Theoretically, in the current codebase, two independent net_devices can be connected to the same GDM port so we need to check the GDM port is not @@ -16,6 +13,8 @@ GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-4-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 59 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 1 + @@ -23,27 +22,25 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1992,10 +1992,10 @@ static int airoha_dev_open(struct net_de +@@ -1723,8 +1723,8 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - u32 pse_port = FE_PSE_PORT_PPE1; - /* HW LRO is configured on the QDMA and it is shared between - * all the devices using it. Refuse to open a second device on -@@ -2034,10 +2034,20 @@ static int airoha_dev_open(struct net_de - airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); +@@ -1738,10 +1738,20 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); -+ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the @@ -51,7 +48,7 @@ Signed-off-by: Lorenzo Bianconi + * multiple net_devices with different MTUs to share the same + * GDM port. + */ -+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); @@ -60,7 +57,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -2060,6 +2070,30 @@ static int airoha_dev_open(struct net_de +@@ -1757,6 +1767,30 @@ static int airoha_dev_open(struct net_de return 0; } @@ -91,21 +88,22 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2073,8 +2107,11 @@ static int airoha_dev_stop(struct net_de +@@ -1769,8 +1803,12 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), +- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (--port->users) -+ airoha_set_port_mtu(eth, port); ++ airoha_set_port_mtu(dev->eth, port); + else -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (!--qdma->users) { + if (atomic_dec_and_test(&qdma->users)) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, -@@ -2238,13 +2275,10 @@ static int airoha_dev_change_mtu(struct +@@ -1925,13 +1963,10 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -123,7 +121,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -571,6 +571,7 @@ struct airoha_gdm_dev { +@@ -554,6 +554,7 @@ struct airoha_gdm_dev { struct airoha_gdm_port { struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS]; int id; diff --git a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch similarity index 83% rename from target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch rename to target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch index a21fa3f05bd..35e864e30d5 100644 --- a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch +++ b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch @@ -1,10 +1,7 @@ -From c4f3077948eda05a6b9d1a11304d82c3e0300151 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 7758cb462ff72b10d71e72bca8cf65179a1264e8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 3 Apr 2026 12:07:27 +0200 -Subject: [PATCH 08/13] net: airoha: Introduce WAN device flag +Date: Wed, 3 Jun 2026 08:00:19 +0200 +Subject: [PATCH 4/5] net: airoha: Introduce WAN device flag Introduce WAN flag to specify if a given device is used to transmit/receive WAN or LAN traffic. Current codebase supports specifying LAN/WAN device @@ -21,15 +18,17 @@ officially supported since PCS/external phy is not merged mainline yet Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-5-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 72 +++++++++++++++++++----- + drivers/net/ethernet/airoha/airoha_eth.c | 73 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 13 ++--- drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- - 3 files changed, 65 insertions(+), 22 deletions(-) + 3 files changed, 66 insertions(+), 22 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2214,36 +2214,81 @@ static int airoha_set_gdm2_loopback(stru +@@ -1902,36 +1902,81 @@ static int airoha_enable_gdm2_loopback(s return 0; } @@ -86,7 +85,7 @@ Signed-off-by: Lorenzo Bianconi - if (!eth->ports[1]) { - int err; - -- err = airoha_set_gdm2_loopback(dev); +- err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } @@ -119,7 +118,7 @@ Signed-off-by: Lorenzo Bianconi + (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { + int err; + -+ err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } @@ -128,7 +127,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -550,6 +550,10 @@ struct airoha_qdma { +@@ -538,6 +538,10 @@ struct airoha_qdma { DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS); }; @@ -139,7 +138,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev { struct airoha_gdm_port *port; struct airoha_qdma *qdma; -@@ -565,6 +569,7 @@ struct airoha_gdm_dev { +@@ -548,6 +552,7 @@ struct airoha_gdm_dev { u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -147,7 +146,7 @@ Signed-off-by: Lorenzo Bianconi int nbq; }; -@@ -671,13 +676,7 @@ static inline u16 airoha_qdma_get_txq(st +@@ -654,13 +659,7 @@ static inline u16 airoha_qdma_get_txq(st static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev) { @@ -164,7 +163,7 @@ Signed-off-by: Lorenzo Bianconi static inline bool airoha_is_7581(struct airoha_eth *eth) --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -356,7 +356,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -355,7 +355,7 @@ static int airoha_ppe_foe_entry_prepare( return -EINVAL; port = dev->port; diff --git a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch similarity index 75% rename from target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch rename to target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch index 553bd3cbf57..a4041bb3dbd 100644 --- a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch +++ b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch @@ -1,38 +1,42 @@ -From 144f0e6e55896625e3411aad02399a5ebb48d8f9 Mon Sep 17 00:00:00 2001 -Message-ID: <144f0e6e55896625e3411aad02399a5ebb48d8f9.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From ef2aee987174b51573645b4bdacedf610e89ce1a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Mon, 13 Apr 2026 17:38:51 +0200 -Subject: [PATCH 09/13] net: airoha: Support multiple LAN/WAN interfaces for hw +Date: Wed, 3 Jun 2026 08:00:20 +0200 +Subject: [PATCH 5/5] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN -MAC addresses, used to determine whether received traffic is destined for -this host or should be forwarded to another device. +MAC addresses. These registers are used during FE hw acceleration to +determine whether received traffic is destined to this host (L3 traffic) +or should be switched to another device (L2 traffic). The SoC hardware design assumes all interfaces configured as LAN (or WAN) -share a common upper MAC address, which is programmed into the -REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can -be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX -registers. +share the MAC address MSBs, which are programmed into the +REG_FE_{LAN,WAN}_MAC_H register. The LSBs of 'local' mac addresses can be +expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX +registers. In order to properly accelerate the traffic, FE module requires +the user to configure the REG_FE_{LAN,WAN}_MAC_H register respecting this +limitation. Please note a misconfiguration in REG_FE_{LAN,WAN}_MAC_H +will still allow the user to log into the device for debugging. Previously, only a single interface was considered when programming these registers. Extend the logic to derive the correct minimum and maximum values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are -configured as LAN or WAN. +configured as LAN or WAN. Since this functionality was not available +before this series, no regression is introduced. Tested-by: Madhur Agrawal Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-6-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 77 ++++++++++++++++++++---- + drivers/net/ethernet/airoha/airoha_eth.c | 77 +++++++++++++++++++++--- drivers/net/ethernet/airoha/airoha_eth.h | 2 +- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- - 3 files changed, 68 insertions(+), 15 deletions(-) + 3 files changed, 71 insertions(+), 12 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -81,20 +81,76 @@ static bool airhoa_is_phy_external(struc +@@ -71,20 +71,76 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -105,15 +109,15 @@ Signed-off-by: Lorenzo Bianconi - airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), lmin); + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), lmax); -+ -+ airoha_ppe_init_upd_mem(dev, addr); - airoha_ppe_init_upd_mem(dev); ++ airoha_ppe_init_upd_mem(dev, addr); ++ + return 0; } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -2141,13 +2197,18 @@ static int airoha_dev_stop(struct net_de +@@ -1829,13 +1885,18 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -136,7 +140,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -712,7 +712,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -683,7 +683,7 @@ void airoha_ppe_check_skb(struct airoha_ int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); @@ -147,7 +151,7 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -1499,12 +1499,10 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1487,12 +1487,10 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } diff --git a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch similarity index 87% rename from target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch rename to target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch index 1aec4e91fcf..474cbe9a1b1 100644 --- a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch +++ b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch @@ -1,29 +1,31 @@ -From 9652322e0b47eacfef497828f6476a2a3169fd13 Mon Sep 17 00:00:00 2001 -Message-ID: <9652322e0b47eacfef497828f6476a2a3169fd13.1779351672.git.lorenzo@kernel.org> -From: Christian Marangi -Date: Sat, 17 Jan 2026 14:46:12 +0100 -Subject: [PATCH] net: airoha: Better handle MIB for GDM with multiple port - attached - -In the context of a GDM that can have multiple port attached (GDM3/4) -the HW counter (MIB) are global for the GDM port. This cause duplicated -stats reported to the kernel for the related interface. +From 8f4695fb67b259b2cae0be1eef55859bfc559058 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 11 Jun 2026 12:43:00 +0200 +Subject: [PATCH] net: airoha: better handle MIBs for GDM ports with multiple + devs attached +In the context of a GDM port that can have multiple net_devices attached +(GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port. +This cause duplicated stats reported to the kernel for the related +net_device. The SoC supports a split MIB feature where each counter is tracked based on the relevant HW channel (NBQ) to account for this scenario and provide a way to select the related counter on accessing the MIB registers. - Enable this feature for GDM3 and GDM4 and configure the relevant HW channel before updating the HW stats to report correct HW counter to the kernel for the related interface. +Move the stats struct from port to dev since HW counter are now specific +to the network device instead of the GDM port. Refactor +airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port +parameters since the function operates on the entire port. -Also move the stats struct from port to dev since HW counter are -now specific to the network interface instead of the GDM port. - -Co-developed-by: Brown Huang -Signed-off-by: Brown Huang +Co-developed-by: Christian Marangi Signed-off-by: Christian Marangi +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 191 +++++++++++++---------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +- @@ -31,9 +33,9 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -640,6 +640,14 @@ static int airoha_fe_init(struct airoha_ - airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), - GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); +@@ -556,6 +556,14 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM3_IDX), GDM_PAD_EN_MASK); + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), GDM_PAD_EN_MASK); + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), @@ -46,7 +48,7 @@ Signed-off-by: Christian Marangi airoha_fe_crsn_qsel_init(eth); airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); -@@ -1872,149 +1880,169 @@ static void airoha_qdma_stop_napi(struct +@@ -1629,149 +1637,169 @@ static void airoha_qdma_stop_napi(struct } } @@ -59,14 +61,14 @@ Signed-off-by: Christian Marangi - spin_lock(&port->stats.lock); - u64_stats_update_begin(&port->stats.syncp); -+ u64_stats_update_begin(&dev->stats.syncp); -+ + /* Read relevant MIB for GDM with multiple port attached */ + if (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX) + airoha_fe_rmw(eth, REG_FE_GDM_MIB_CFG(port->id), + FE_TX_MIB_ID_MASK | FE_RX_MIB_ID_MASK, + FIELD_PREP(FE_TX_MIB_ID_MASK, dev->nbq) | + FIELD_PREP(FE_RX_MIB_ID_MASK, dev->nbq)); ++ ++ u64_stats_update_begin(&dev->stats.syncp); /* TX */ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); @@ -245,7 +247,9 @@ Signed-off-by: Christian Marangi + + u64_stats_update_end(&dev->stats.syncp); +} -+ + +- /* reset mib counters */ +- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev) +{ + struct airoha_gdm_port *port = dev->port; @@ -257,9 +261,7 @@ Signed-off-by: Christian Marangi + if (port->devs[i]) + airoha_dev_get_hw_stats(port->devs[i]); + } - -- /* reset mib counters */ -- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), ++ + /* Reset MIB counters */ + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); @@ -269,8 +271,8 @@ Signed-off-by: Christian Marangi + spin_unlock(&port->stats_lock); } - static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) -@@ -2418,23 +2446,22 @@ static void airoha_dev_get_stats64(struc + static int airoha_dev_open(struct net_device *netdev) +@@ -2046,23 +2074,22 @@ static void airoha_dev_get_stats64(struc struct rtnl_link_stats64 *storage) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -306,7 +308,7 @@ Signed-off-by: Christian Marangi } static int airoha_dev_change_mtu(struct net_device *netdev, int mtu) -@@ -2723,20 +2750,19 @@ static void airoha_ethtool_get_mac_stats +@@ -2313,20 +2340,19 @@ static void airoha_ethtool_get_mac_stats struct ethtool_eth_mac_stats *stats) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -336,7 +338,7 @@ Signed-off-by: Christian Marangi } static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { -@@ -2756,8 +2782,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2346,8 +2372,7 @@ airoha_ethtool_get_rmon_stats(struct net const struct ethtool_rmon_hist_range **ranges) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -346,7 +348,7 @@ Signed-off-by: Christian Marangi unsigned int start; BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != -@@ -2770,7 +2795,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2360,7 +2385,7 @@ airoha_ethtool_get_rmon_stats(struct net do { int i; @@ -355,7 +357,7 @@ Signed-off-by: Christian Marangi stats->fragments = hw_stats->rx_fragment; stats->jabbers = hw_stats->rx_jabber; for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; -@@ -2778,7 +2803,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2368,7 +2393,7 @@ airoha_ethtool_get_rmon_stats(struct net stats->hist[i] = hw_stats->rx_len[i]; stats->hist_tx[i] = hw_stats->tx_len[i]; } @@ -364,7 +366,7 @@ Signed-off-by: Christian Marangi } static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, -@@ -3849,6 +3874,7 @@ static int airoha_alloc_gdm_device(struc +@@ -3208,6 +3233,7 @@ static int airoha_alloc_gdm_device(struc netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); @@ -372,7 +374,7 @@ Signed-off-by: Christian Marangi dev->port = port; dev->eth = eth; dev->nbq = nbq; -@@ -3896,9 +3922,8 @@ static int airoha_alloc_gdm_port(struct +@@ -3247,9 +3273,8 @@ static int airoha_alloc_gdm_port(struct if (!port) return -ENOMEM; @@ -385,7 +387,7 @@ Signed-off-by: Christian Marangi err = airoha_metadata_dst_alloc(port); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -228,8 +228,6 @@ struct airoha_tx_irq_queue { +@@ -215,8 +215,6 @@ struct airoha_tx_irq_queue { }; struct airoha_hw_stats { @@ -394,7 +396,7 @@ Signed-off-by: Christian Marangi struct u64_stats_sync syncp; /* get_stats64 */ -@@ -573,6 +571,8 @@ struct airoha_gdm_dev { +@@ -554,6 +552,8 @@ struct airoha_gdm_dev { u32 flags; int nbq; @@ -403,7 +405,7 @@ Signed-off-by: Christian Marangi }; struct airoha_gdm_port { -@@ -580,7 +580,8 @@ struct airoha_gdm_port { +@@ -561,7 +561,8 @@ struct airoha_gdm_port { int id; int users; diff --git a/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch similarity index 75% rename from target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch rename to target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch index 5d4ecf66069..46c18073e58 100644 --- a/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch +++ b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch @@ -1,5 +1,4 @@ From a459b560e58be327689e9bd8c0a6be9a4f163366 Mon Sep 17 00:00:00 2001 -Message-ID: From: Lorenzo Bianconi Date: Thu, 11 Jun 2026 23:55:51 +0200 Subject: [PATCH] net: airoha: use int instead of atomic_t for qdma users @@ -18,18 +17,18 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1761,7 +1761,7 @@ static int airoha_dev_open(struct net_de +@@ -1840,7 +1840,7 @@ static int airoha_dev_open(struct net_de airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | GLOBAL_CFG_RX_DMA_EN_MASK); - atomic_inc(&qdma->users); + qdma->users++; - if (port->id == AIROHA_GDM2_IDX && - airoha_ppe_is_enabled(qdma->eth, 1)) { -@@ -1788,7 +1788,7 @@ static int airoha_dev_stop(struct net_de - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (!airoha_is_lan_gdm_dev(dev) && + airoha_ppe_is_enabled(qdma->eth, 1)) +@@ -1894,7 +1894,7 @@ static int airoha_dev_stop(struct net_de + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (atomic_dec_and_test(&qdma->users)) { + if (!--qdma->users) { @@ -38,7 +37,7 @@ Signed-off-by: Jakub Kicinski GLOBAL_CFG_RX_DMA_EN_MASK); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -525,7 +525,7 @@ struct airoha_qdma { +@@ -524,7 +524,7 @@ struct airoha_qdma { struct airoha_eth *eth; void __iomem *regs; diff --git a/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch new file mode 100644 index 00000000000..da756981555 --- /dev/null +++ b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch @@ -0,0 +1,50 @@ +From aeb62be4d3b18b76551bf7806e30d72e5c3bbade Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 8 Jun 2026 23:24:15 +0200 +Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of + airoha_enable_gdm2_loopback() + +Move the get_sport() callback invocation at the beginning of +airoha_enable_gdm2_loopback() routine in order to avoid leaving the +hardware in a partially configured state if get_sport() fails. +Previously, get_sport() was called after GDM2 forwarding, loopback, +channel, length, VIP and IFC registers had already been programmed. +A failure at that point would return an error leaving GDM2 with +loopback enabled but WAN port, PPE CPU port and flow control mappings +not configured. +Performing the get_sport() lookup before any register write guarantees +the routine either completes the full configuration sequence or exits +with no side effects on the hardware. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260608-airoha_enable_gdm2_loopback-minor-change-v1-1-1787a0f42b31@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1936,6 +1936,10 @@ static int airoha_enable_gdm2_loopback(s + u32 val, pse_port, chan; + int i, src_port; + ++ src_port = eth->soc->ops.get_sport(port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), + FE_PSE_PORT_DROP); + airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), +@@ -1965,10 +1969,6 @@ static int airoha_enable_gdm2_loopback(s + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); + +- src_port = eth->soc->ops.get_sport(port, dev->nbq); +- if (src_port < 0) +- return src_port; +- + airoha_fe_rmw(eth, REG_FE_WAN_PORT, + WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, + FIELD_PREP(WAN0_MASK, src_port)); diff --git a/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch similarity index 77% rename from target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch rename to target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch index c9e788e3e15..e2ce9978b87 100644 --- a/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch +++ b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch @@ -1,7 +1,6 @@ -From 3d67e4ba79bd4b40f520d26af098f133b5f551d4 Mon Sep 17 00:00:00 2001 -Message-ID: <3d67e4ba79bd4b40f520d26af098f133b5f551d4.1781097105.git.lorenzo@kernel.org> +From 9912dfa2d46aef4cd708246aa6b39b49213f5e62 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 6 Jun 2026 08:53:03 +0200 +Date: Wed, 10 Jun 2026 15:25:13 +0200 Subject: [PATCH] net: airoha: simplify WAN device check in airoha_dev_init() airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's @@ -13,13 +12,16 @@ Remove the redundant check and rely solely on airoha_get_wan_gdm_dev() which handles both the GDM2-present and GDM2-absent cases. Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260610-airoha-eth-simplify-dev-init-v2-1-8f244e69b0d4@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2407,18 +2407,10 @@ static int airoha_dev_init(struct net_de +@@ -2035,18 +2035,10 @@ static int airoha_dev_init(struct net_de switch (port->id) { case AIROHA_GDM3_IDX: diff --git a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch index a75e06f944a..61cd51ca60c 100644 --- a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch +++ b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch @@ -13,7 +13,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1487,6 +1487,10 @@ static int airoha_hw_init(struct platfor +@@ -1568,6 +1568,10 @@ static int airoha_hw_init(struct platfor if (err) return err; diff --git a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch b/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch deleted file mode 100644 index d5a2ba9d1ae..00000000000 --- a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ad29054f9b0e96e30a5d0bb6967d1204b8ea8bd1 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 10:12:02 +0100 -Subject: [PATCH 3/9] net: airoha: add reference for SPORT GDM4 in - qdma_get_gdm_port - -Add SPORT reference in get gdm port as the on receive the SPORT 0x18 is -assigned for the GDM4 port. - -While at it also add comments to better identify GDM1 ports. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -574,8 +574,11 @@ static int airoha_qdma_get_gdm_port(stru - - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -+ case 0x18: -+ port = 3; /* GDM4 */ -+ break; - case 0x10 ... 0x14: -- port = 0; -+ port = 0; /* GDM1 */ - break; - case 0x2 ... 0x4: - port = sport - 1; diff --git a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch index cd774e11eac..2de3c8d1a89 100644 --- a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch +++ b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -498,8 +498,10 @@ static int airoha_fe_init(struct airoha_ +@@ -553,8 +553,10 @@ static int airoha_fe_init(struct airoha_ FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); @@ -26,15 +26,15 @@ Signed-off-by: Christian Marangi + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), + GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); - airoha_fe_crsn_qsel_init(eth); - -@@ -1719,7 +1721,8 @@ static int airoha_dev_open(struct net_de + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), +@@ -1819,7 +1821,8 @@ static int airoha_dev_open(struct net_de if (err) return err; -- if (netdev_uses_dsa(dev)) +- if (netdev_uses_dsa(netdev)) + /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -+ if (netdev_uses_dsa(dev) || port->id > 2) ++ if (netdev_uses_dsa(netdev) || port->id > 2) airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else diff --git a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch index 0ecba241d80..d6560370d28 100644 --- a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch +++ b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3196,7 +3196,6 @@ static void airoha_remove(struct platfor +@@ -3511,7 +3511,6 @@ static void airoha_remove(struct platfor } static const char * const en7581_xsi_rsts_names[] = { @@ -23,7 +23,7 @@ Signed-off-by: Christian Marangi "hsi0-mac", "hsi1-mac", "hsi-mac", -@@ -3250,7 +3249,6 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3598,7 +3597,6 @@ static int airoha_en7581_get_dev_from_sp } static const char * const an7583_xsi_rsts_names[] = { diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch deleted file mode 100644 index 7421c01c06e..00000000000 --- a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch +++ /dev/null @@ -1,281 +0,0 @@ -From ee93671d30d7741a39026c2aaaa6a7729929c347 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 13:23:13 +0100 -Subject: [PATCH 2/2] net: airoha: add phylink support for GDM2/3/4 - -Add phylink support for GDM2/3/4 port that require configuration of the -PCS to make the external PHY or attached SFP cage work. - -These needs to be defined in the GDM port node using the pcs-handle -property. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/Kconfig | 1 + - drivers/net/ethernet/airoha/airoha_eth.c | 146 +++++++++++++++++++++- - drivers/net/ethernet/airoha/airoha_eth.h | 3 + - drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ - 4 files changed, 161 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/Kconfig -+++ b/drivers/net/ethernet/airoha/Kconfig -@@ -20,6 +20,7 @@ config NET_AIROHA - depends on NET_DSA || !NET_DSA - select NET_AIROHA_NPU - select PAGE_POOL -+ select PHYLINK - help - This driver supports the gigabit ethernet MACs in the - Airoha SoC family. ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -71,6 +72,11 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+static bool airhoa_is_phy_external(struct airoha_gdm_port *port) -+{ -+ return port->id != 1; -+} -+ - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { - struct airoha_eth *eth = port->qdma->eth; -@@ -1716,6 +1722,17 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+ if (airhoa_is_phy_external(port)) { -+ err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ if (err) { -+ netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -+ err); -+ return err; -+ } -+ -+ phylink_start(port->phylink); -+ } -+ - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); - if (err) -@@ -1777,6 +1794,11 @@ static int airoha_dev_stop(struct net_de - } - } - -+ if (airhoa_is_phy_external(port)) { -+ phylink_stop(port->phylink); -+ phylink_disconnect_phy(port->phylink); -+ } -+ - return 0; - } - -@@ -2916,6 +2938,11 @@ static const struct ethtool_ops airoha_e - .get_link = ethtool_op_get_link, - }; - -+static void airoha_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ - static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) - { - int i; -@@ -2960,6 +2987,119 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -+ phylink_config); -+ struct airoha_qdma *qdma = port->qdma; -+ struct airoha_eth *eth = qdma->eth; -+ u32 frag_size_tx, frag_size_rx; -+ -+ if (port->id != 4) -+ return; -+ -+ switch (speed) { -+ case SPEED_10000: -+ case SPEED_5000: -+ frag_size_tx = 8; -+ frag_size_rx = 8; -+ break; -+ case SPEED_2500: -+ frag_size_tx = 2; -+ frag_size_rx = 1; -+ break; -+ default: -+ frag_size_tx = 1; -+ frag_size_rx = 0; -+ } -+ -+ /* Configure TX/RX frag based on speed */ -+ airoha_fe_rmw(eth, REG_GDMA4_TMBI_FRAG, -+ GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ frag_size_tx)); -+ -+ airoha_fe_rmw(eth, REG_GDMA4_RMBI_FRAG, -+ GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ frag_size_rx)); -+} -+ -+static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+} -+ -+static const struct phylink_mac_ops airoha_phylink_ops = { -+ .mac_config = airoha_mac_config, -+ .mac_link_up = airoha_mac_link_up, -+ .mac_link_down = airoha_mac_link_down, -+}; -+ -+static int airoha_fill_available_pcs(struct phylink_config *config, -+ struct phylink_pcs **available_pcs, -+ unsigned int num_available_pcs) -+{ -+ struct device *dev = config->dev; -+ -+ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, -+ &num_available_pcs); -+} -+ -+static int airoha_setup_phylink(struct net_device *dev) -+{ -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct device_node *np = dev->dev.of_node; -+ phy_interface_t phy_mode; -+ struct phylink *phylink; -+ int err; -+ -+ err = of_get_phy_mode(np, &phy_mode); -+ if (err) { -+ dev_err(&dev->dev, "incorrect phy-mode\n"); -+ return err; -+ } -+ -+ port->phylink_config.dev = &dev->dev; -+ port->phylink_config.type = PHYLINK_NETDEV; -+ port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; -+ -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -+ &port->phylink_config.num_available_pcs); -+ if (err) -+ return err; -+ -+ port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ port->phylink_config.supported_interfaces); -+ -+ phy_interface_copy(port->phylink_config.pcs_interfaces, -+ port->phylink_config.supported_interfaces); -+ -+ phylink = phylink_create(&port->phylink_config, -+ of_fwnode_handle(np), -+ phy_mode, &airoha_phylink_ops); -+ if (IS_ERR(phylink)) -+ return PTR_ERR(phylink); -+ -+ port->phylink = phylink; -+ -+ return err; -+} -+ - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) - { -@@ -3033,6 +3173,12 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(dev); -+ if (err) -+ return err; -+ } -+ - return airoha_metadata_dst_alloc(port); - } - -@@ -3160,8 +3306,11 @@ error_napi_stop: - if (!port) - continue; - -- if (port->dev->reg_state == NETREG_REGISTERED) -+ if (port->dev->reg_state == NETREG_REGISTERED) { -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); -+ } - airoha_metadata_dst_free(port); - } - airoha_hw_cleanup(eth); -@@ -3186,6 +3335,8 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,6 +542,9 @@ struct airoha_gdm_port { - int id; - int nbq; - -+ struct phylink *phylink; -+ struct phylink_config phylink_config; -+ - struct airoha_hw_stats stats; - - DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -358,6 +358,18 @@ - #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) - #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) - -+#define REG_GDMA4_TMBI_FRAG 0x2028 -+#define GDMA4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) -+ -+#define REG_GDMA4_RMBI_FRAG 0x202c -+#define GDMA4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) -+ - #define REG_MC_VLAN_EN 0x2100 - #define MC_VLAN_EN_MASK BIT(0) - diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch new file mode 100644 index 00000000000..de636badfb6 --- /dev/null +++ b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch @@ -0,0 +1,361 @@ +From beb56181a370b003b12f657239b510435cae2c9d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 13:23:13 +0100 +Subject: [PATCH] net: airoha: add phylink support + +Add phylink support for each GDM port. For GDM1 add the internal interface +mode as the only supported mode. For GDM2/3/4 add the required +configuration of the PCS to make the external PHY or attached SFP cage +work. + +These needs to be defined in the GDM port node using the pcs-handle +property. + +Update and provide a .get/set_link_ksettings function that use phylink +for ethtool OPs now that we fully support phylink. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/Kconfig | 1 + + drivers/net/ethernet/airoha/airoha_eth.c | 193 +++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_eth.h | 7 +- + drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ + 4 files changed, 206 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -20,6 +20,7 @@ config NET_AIROHA + depends on NET_DSA || !NET_DSA + select NET_AIROHA_NPU + select PAGE_POOL ++ select PHYLINK + help + This driver supports the gigabit ethernet MACs in the + Airoha SoC family. +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1794,7 +1795,7 @@ static void airoha_update_hw_stats(struc + struct airoha_gdm_port *port = dev->port; + int i; + +- spin_lock(&port->stats_lock); ++ spin_lock(&port->lock); + + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { + if (port->devs[i]) +@@ -1805,7 +1806,7 @@ static void airoha_update_hw_stats(struc + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), + FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); + +- spin_unlock(&port->stats_lock); ++ spin_unlock(&port->lock); + } + + static int airoha_dev_open(struct net_device *netdev) +@@ -1816,6 +1817,14 @@ static int airoha_dev_open(struct net_de + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; + ++ err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); ++ if (err) { ++ netdev_err(netdev, "could not attach PHY: %d\n", err); ++ return err; ++ } ++ ++ phylink_start(dev->phylink); ++ + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); + if (err) +@@ -1914,6 +1923,9 @@ static int airoha_dev_stop(struct net_de + } + } + ++ phylink_stop(dev->phylink); ++ phylink_disconnect_phy(dev->phylink); ++ + return 0; + } + +@@ -2395,6 +2407,24 @@ airoha_ethtool_get_rmon_stats(struct net + } while (u64_stats_fetch_retry(&dev->stats.syncp, start)); + } + ++static int ++airoha_ethtool_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_get(dev->phylink, cmd); ++} ++ ++static int ++airoha_ethtool_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_set(dev->phylink, cmd); ++} ++ + static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, + int channel, enum tx_sched_mode mode, + const u16 *weights, u8 n_weights) +@@ -3119,7 +3149,8 @@ static const struct ethtool_ops airoha_e + .get_drvinfo = airoha_ethtool_get_drvinfo, + .get_eth_mac_stats = airoha_ethtool_get_mac_stats, + .get_rmon_stats = airoha_ethtool_get_rmon_stats, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .get_link_ksettings = airoha_ethtool_get_link_ksettings, ++ .set_link_ksettings = airoha_ethtool_set_link_ksettings, + .get_link = ethtool_op_get_link, + }; + +@@ -3175,6 +3206,159 @@ bool airoha_is_valid_gdm_dev(struct airo + return false; + } + ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, ++ phylink_config); ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ u32 frag_size_tx, frag_size_rx; ++ u32 mask, val; ++ ++ /* TX/RX frag is configured only for GDM4 */ ++ if (port->id != AIROHA_GDM4_IDX) ++ return; ++ ++ switch (speed) { ++ case SPEED_10000: ++ case SPEED_5000: ++ frag_size_tx = 8; ++ frag_size_rx = 8; ++ break; ++ case SPEED_2500: ++ frag_size_tx = 2; ++ frag_size_rx = 1; ++ break; ++ default: ++ frag_size_tx = 1; ++ frag_size_rx = 0; ++ } ++ ++ spin_lock(&port->lock); ++ ++ /* Configure TX/RX frag based on speed */ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } else { ++ mask = GDM4_SGMII0_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_TMBI_FRAG, mask, val); ++ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } else { ++ mask = GDM4_SGMII0_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_RMBI_FRAG, mask, val); ++ ++ spin_unlock(&port->lock); ++} ++ ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++} ++ ++static const struct phylink_mac_ops airoha_phylink_ops = { ++ .mac_config = airoha_mac_config, ++ .mac_link_up = airoha_mac_link_up, ++ .mac_link_down = airoha_mac_link_down, ++}; ++ ++static int airoha_fill_available_pcs(struct phylink_config *config, ++ struct phylink_pcs **available_pcs, ++ unsigned int num_possible_pcs) ++{ ++ struct device *dev = config->dev; ++ ++ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, ++ &num_possible_pcs); ++} ++ ++static int airoha_setup_phylink(struct net_device *netdev) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct device_node *np = netdev->dev.of_node; ++ struct airoha_gdm_port *port = dev->port; ++ struct phylink_config *config; ++ phy_interface_t phy_mode; ++ struct phylink *phylink; ++ int err; ++ ++ err = of_get_phy_mode(np, &phy_mode); ++ if (err) { ++ dev_err(&netdev->dev, "incorrect phy-mode\n"); ++ return err; ++ } ++ ++ config = &dev->phylink_config; ++ config->dev = &netdev->dev; ++ config->type = PHYLINK_NETDEV; ++ ++ /* ++ * GDM1 only supports internal for Embedded Switch ++ * and doesn't require a PCS. ++ */ ++ if (port->id == AIROHA_GDM1_IDX) { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10000FD; ++ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ } else { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000 | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; ++ ++ err = fwnode_phylink_pcs_parse(dev_fwnode(config->dev), NULL, ++ &dev->phylink_config.num_available_pcs); ++ if (err) ++ return err; ++ ++ config->fill_available_pcs = airoha_fill_available_pcs; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ config->supported_interfaces); ++ ++ phy_interface_copy(config->pcs_interfaces, ++ config->supported_interfaces); ++ } ++ ++ phylink = phylink_create(config, of_fwnode_handle(np), ++ phy_mode, &airoha_phylink_ops); ++ if (IS_ERR(phylink)) ++ return PTR_ERR(phylink); ++ ++ dev->phylink = phylink; ++ ++ return 0; ++} ++ + static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, + int nbq, struct device_node *np) +@@ -3238,7 +3422,7 @@ static int airoha_alloc_gdm_device(struc + dev->nbq = nbq; + port->devs[index] = dev; + +- return 0; ++ return airoha_setup_phylink(netdev); + } + + static int airoha_alloc_gdm_port(struct airoha_eth *eth, +@@ -3273,7 +3457,7 @@ static int airoha_alloc_gdm_port(struct + return -ENOMEM; + + port->id = id; +- spin_lock_init(&port->stats_lock); ++ spin_lock_init(&port->lock); + eth->ports[p] = port; + + err = airoha_metadata_dst_alloc(port); +@@ -3464,6 +3648,8 @@ error_napi_stop: + netdev = netdev_from_priv(dev); + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); ++ if (dev->phylink) ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +@@ -3500,6 +3686,7 @@ static void airoha_remove(struct platfor + + netdev = netdev_from_priv(dev); + unregister_netdev(netdev); ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -554,6 +554,9 @@ struct airoha_gdm_dev { + int nbq; + + struct airoha_hw_stats stats; ++ ++ struct phylink *phylink; ++ struct phylink_config phylink_config; + }; + + struct airoha_gdm_port { +@@ -561,8 +564,8 @@ struct airoha_gdm_port { + int id; + int users; + +- /* protect concurrent hw_stats accesses */ +- spinlock_t stats_lock; ++ /* protect concurrent hw_stats and frag register accesses */ ++ spinlock_t lock; + + struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS]; + }; +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -358,6 +358,18 @@ + #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) + #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) + ++#define REG_FE_GDM4_TMBI_FRAG 0x2028 ++#define GDM4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) ++ ++#define REG_FE_GDM4_RMBI_FRAG 0x202c ++#define GDM4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) ++ + #define REG_MC_VLAN_EN 0x2100 + #define MC_VLAN_EN_MASK BIT(0) + diff --git a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch b/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch deleted file mode 100644 index b78cc3455fe..00000000000 --- a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6548e580509397a622b7c504a79de93414771459 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jun 2025 00:04:36 +0200 -Subject: [PATCH 6/6] net: ethernet: airoha: define sport value for GDM3 - -On Airoha AN7583, the Serdes Ethernet goes through the GDM3 port. -To correctly receive packet for QDMA, add the sport value to identify -packet from GDM3 port. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -585,6 +585,9 @@ static int airoha_qdma_get_gdm_port(stru - case 0x18: - port = 3; /* GDM4 */ - break; -+ case 0x16: -+ port = 2; /* GDM3 */ -+ break; - case 0x10 ... 0x14: - port = 0; /* GDM1 */ - break; diff --git a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch b/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch deleted file mode 100644 index d43d3303a07..00000000000 --- a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 843e2892f2d9353bf039e0dfb5442a600e75009e Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 9 Oct 2025 23:46:08 +0300 -Subject: [PATCH] net: airoha: disable external phy code if PCS_AIROHA is not - enabled - -External phy code breaks building for EN7523, so disable it if -PCS_AIROHA is not selected. - -Signed-off-by: Mikhail Kshevetskiy ---- - drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++ - drivers/net/ethernet/airoha/airoha_eth.h | 2 ++ - 2 files changed, 18 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -72,10 +72,12 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+#if defined(CONFIG_PCS_AIROHA) - static bool airhoa_is_phy_external(struct airoha_gdm_port *port) - { - return port->id != 1; - } -+#endif - - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { -@@ -1725,6 +1727,7 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); - if (err) { -@@ -1735,6 +1738,7 @@ static int airoha_dev_open(struct net_de - - phylink_start(port->phylink); - } -+#endif - - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); -@@ -1797,10 +1801,12 @@ static int airoha_dev_stop(struct net_de - } - } - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - phylink_stop(port->phylink); - phylink_disconnect_phy(port->phylink); - } -+#endif - - return 0; - } -@@ -2990,6 +2996,7 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+#if defined(CONFIG_PCS_AIROHA) - static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) -@@ -3102,6 +3109,7 @@ static int airoha_setup_phylink(struct n - - return err; - } -+#endif - - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) -@@ -3176,11 +3184,13 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = airoha_setup_phylink(dev); - if (err) - return err; - } -+#endif - - return airoha_metadata_dst_alloc(port); - } -@@ -3310,8 +3320,10 @@ error_napi_stop: - continue; - - if (port->dev->reg_state == NETREG_REGISTERED) { -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - } - airoha_metadata_dst_free(port); -@@ -3338,8 +3350,10 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,8 +542,10 @@ struct airoha_gdm_port { - int id; - int nbq; - -+#if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; -+#endif - - struct airoha_hw_stats stats; - diff --git a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch index 6acc99da3e6..7670611c013 100644 --- a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch +++ b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch @@ -25,25 +25,25 @@ Signed-off-by: Lorenzo Bianconi #include "airoha_regs.h" #include "airoha_eth.h" -@@ -300,7 +301,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -314,7 +315,7 @@ static int airoha_ppe_foe_entry_prepare( struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto) + int l4proto, u8 dsfield) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); -@@ -333,7 +334,7 @@ static int airoha_ppe_foe_entry_prepare( - info.wcid); + int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev); +@@ -349,7 +350,7 @@ static int airoha_ppe_foe_entry_prepare( } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port; - u8 pse_port, channel; + u8 pse_port, channel, priority; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) return -EINVAL; -@@ -352,9 +353,13 @@ static int airoha_ppe_foe_entry_prepare( +@@ -369,9 +370,13 @@ static int airoha_ppe_foe_entry_prepare( */ channel = dsa_port >= 0 ? dsa_port : port->id; channel = channel % AIROHA_NUM_QOS_CHANNELS; @@ -58,7 +58,7 @@ Signed-off-by: Lorenzo Bianconi AIROHA_FOE_IB2_PSE_QOS; /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. -@@ -1046,9 +1051,9 @@ static int airoha_ppe_flow_offload_repla +@@ -1063,9 +1068,9 @@ static int airoha_ppe_flow_offload_repla struct net_device *odev = NULL; struct flow_action_entry *act; struct airoha_foe_entry hwe; @@ -69,7 +69,7 @@ Signed-off-by: Lorenzo Bianconi if (rhashtable_lookup(ð->flow_table, &f->cookie, airoha_flow_table_params)) -@@ -1078,6 +1083,13 @@ static int airoha_ppe_flow_offload_repla +@@ -1095,6 +1100,13 @@ static int airoha_ppe_flow_offload_repla return -EOPNOTSUPP; } @@ -83,7 +83,7 @@ Signed-off-by: Lorenzo Bianconi switch (addr_type) { case 0: offload_type = PPE_PKT_TYPE_BRIDGE; -@@ -1143,7 +1155,7 @@ static int airoha_ppe_flow_offload_repla +@@ -1160,7 +1172,7 @@ static int airoha_ppe_flow_offload_repla return -EINVAL; err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, diff --git a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch index 7598a22199c..16513e3c258 100644 --- a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch +++ b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi #include #include "airoha_regs.h" -@@ -439,6 +441,73 @@ static void airoha_fe_crsn_qsel_init(str +@@ -487,6 +489,73 @@ static void airoha_fe_crsn_qsel_init(str CDM_CRSN_QSEL_Q1)); } @@ -70,9 +70,9 @@ Signed-off-by: Lorenzo Bianconi + LRO_RXQ_EN_MASK); +} + -+static void airoha_dev_lro_enable(struct airoha_gdm_port *port) ++static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) +{ -+ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + int i, lro_queue_index = 0; @@ -98,7 +98,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_fe_init(struct airoha_eth *eth) { airoha_fe_maccr_init(eth); -@@ -558,6 +627,7 @@ static int airoha_qdma_fill_rx_queue(str +@@ -614,6 +683,7 @@ static int airoha_qdma_fill_rx_queue(str e->dma_addr = page_pool_get_dma_addr(page) + offset; e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); @@ -106,8 +106,8 @@ Signed-off-by: Lorenzo Bianconi val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); -@@ -603,12 +673,169 @@ static int airoha_qdma_get_gdm_port(stru - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; +@@ -655,12 +725,169 @@ airoha_qdma_get_gdm_dev(struct airoha_et + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } +static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, @@ -279,27 +279,27 @@ Signed-off-by: Lorenzo Bianconi int done = 0; while (done < budget) { -@@ -643,18 +870,9 @@ static int airoha_qdma_rx_process(struct +@@ -696,18 +923,9 @@ static int airoha_qdma_rx_process(struct - port = eth->ports[p]; + netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ - q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, - q->buf_size); -+ q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); ++ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); if (!q->skb) goto free_frag; - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); - skb_mark_for_recycle(q->skb); -- q->skb->dev = port->dev; -- q->skb->protocol = eth_type_trans(q->skb, port->dev); +- q->skb->dev = netdev; +- q->skb->protocol = eth_type_trans(q->skb, netdev); - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); } else { /* scattered frame */ struct skb_shared_info *shinfo = skb_shinfo(q->skb); int nr_frags = shinfo->nr_frags; -@@ -743,12 +961,10 @@ static int airoha_qdma_rx_napi_poll(stru +@@ -798,12 +1016,10 @@ static int airoha_qdma_rx_napi_poll(stru static int airoha_qdma_init_rx_queue(struct airoha_queue *q, struct airoha_qdma *qdma, int ndesc) { @@ -313,7 +313,7 @@ Signed-off-by: Lorenzo Bianconi .nid = NUMA_NO_NODE, .dev = qdma->eth->dev, .napi = &q->napi, -@@ -756,9 +972,10 @@ static int airoha_qdma_init_rx_queue(str +@@ -811,9 +1027,10 @@ static int airoha_qdma_init_rx_queue(str struct airoha_eth *eth = qdma->eth; int qid = q - &qdma->q_rx[0], thr; dma_addr_t dma_addr; @@ -325,7 +325,7 @@ Signed-off-by: Lorenzo Bianconi q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), GFP_KERNEL); -@@ -770,6 +987,9 @@ static int airoha_qdma_init_rx_queue(str +@@ -825,6 +1042,9 @@ static int airoha_qdma_init_rx_queue(str if (!q->desc) return -ENOMEM; @@ -335,7 +335,7 @@ Signed-off-by: Lorenzo Bianconi q->page_pool = page_pool_create(&pp_params); if (IS_ERR(q->page_pool)) { int err = PTR_ERR(q->page_pool); -@@ -778,6 +998,7 @@ static int airoha_qdma_init_rx_queue(str +@@ -833,6 +1053,7 @@ static int airoha_qdma_init_rx_queue(str return err; } @@ -343,7 +343,7 @@ Signed-off-by: Lorenzo Bianconi q->ndesc = ndesc; netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); -@@ -791,7 +1012,12 @@ static int airoha_qdma_init_rx_queue(str +@@ -846,7 +1067,12 @@ static int airoha_qdma_init_rx_queue(str FIELD_PREP(RX_RING_THR_MASK, thr)); airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); @@ -357,7 +357,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_fill_rx_queue(q); -@@ -813,6 +1039,7 @@ static void airoha_qdma_cleanup_rx_queue +@@ -868,6 +1094,7 @@ static void airoha_qdma_cleanup_rx_queue page_pool_get_dma_dir(q->page_pool)); page_pool_put_full_page(q->page_pool, page, false); /* Reset DMA descriptor */ @@ -365,56 +365,67 @@ Signed-off-by: Lorenzo Bianconi WRITE_ONCE(desc->ctrl, 0); WRITE_ONCE(desc->addr, 0); WRITE_ONCE(desc->data, 0); -@@ -1720,13 +1947,45 @@ static void airoha_update_hw_stats(struc - spin_unlock(&port->stats.lock); +@@ -1809,6 +2036,37 @@ static void airoha_update_hw_stats(struc + spin_unlock(&port->lock); } -+static void airoha_update_netdev_features(struct airoha_gdm_port *port) ++static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) +{ -+ struct airoha_eth *eth = port->eth; ++ struct airoha_eth *eth = dev->eth; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -+ struct airoha_gdm_port *p = eth->ports[i]; -+ struct net_device *netdev; ++ struct airoha_gdm_port *port = dev->port; ++ int j; + -+ if (!p) ++ if (!port) + continue; + -+ netdev = p->dev; -+ if (netdev->reg_state != NETREG_REGISTERED) -+ continue; ++ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { ++ struct airoha_gdm_dev *iter_dev = port->devs[j]; ++ struct net_device *netdev; ++ ++ if (!iter_dev || iter_dev == dev) ++ continue; ++ ++ if (iter_dev->qdma != dev->qdma) ++ continue; ++ ++ netdev = netdev_from_priv(iter_dev); ++ if (netdev->reg_state != NETREG_REGISTERED) ++ continue; + -+ netdev_update_features(netdev); ++ netdev_update_features(netdev); ++ } + } +} + - static int airoha_dev_open(struct net_device *dev) + static int airoha_dev_open(struct net_device *netdev) { - int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; - struct airoha_gdm_port *port = netdev_priv(dev); - struct airoha_qdma *qdma = port->qdma; + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; +@@ -1816,6 +2074,18 @@ static int airoha_dev_open(struct net_de + struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; - u32 pse_port = FE_PSE_PORT_PPE1; - ++ + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on + * the same QDMA if LRO is enabled on any device sharing it. + */ + if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { -+ netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", ++ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", + qdma_id); + return -EBUSY; + } -+ - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -@@ -1747,13 +2006,13 @@ static int airoha_dev_open(struct net_de + + err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); + if (err) { +@@ -1832,13 +2102,13 @@ static int airoha_dev_open(struct net_de /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ - if (netdev_uses_dsa(dev) || port->id > 2) + if (netdev_uses_dsa(netdev) || port->id > 2) - airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); @@ -423,68 +434,77 @@ Signed-off-by: Lorenzo Bianconi + airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), -+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); -@@ -1763,14 +2022,18 @@ static int airoha_dev_open(struct net_de - GLOBAL_CFG_RX_DMA_EN_MASK); +- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the +@@ -1846,7 +2116,7 @@ static int airoha_dev_open(struct net_de + * multiple net_devices with different MTUs to share the same + * GDM port. + */ +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); +@@ -1859,11 +2129,16 @@ static int airoha_dev_open(struct net_de qdma->users++; -- if (port->id == AIROHA_GDM2_IDX && -- airoha_ppe_is_enabled(qdma->eth, 1)) { -+ if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { - /* For PPE2 always use secondary cpu port. */ + if (!airoha_is_lan_gdm_dev(dev) && +- airoha_ppe_is_enabled(qdma->eth, 1)) ++ airoha_ppe_is_enabled(eth, 1)) pse_port = FE_PSE_PORT_PPE2; - } - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port); -+ if (dev->features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(port); ++ if (netdev->features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(dev); + -+ airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); + return 0; } -@@ -1778,6 +2041,7 @@ static int airoha_dev_stop(struct net_de - { - struct airoha_gdm_port *port = netdev_priv(dev); - struct airoha_qdma *qdma = port->qdma; +@@ -1896,6 +2171,7 @@ static int airoha_dev_stop(struct net_de + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; int i; - netif_tx_disable(dev); -@@ -1785,7 +2049,7 @@ static int airoha_dev_stop(struct net_de - for (i = 0; i < dev->num_tx_queues; i++) - netdev_tx_reset_subqueue(dev, i); + netif_tx_disable(netdev); +@@ -1904,9 +2180,9 @@ static int airoha_dev_stop(struct net_de + netdev_tx_reset_subqueue(netdev, i); -- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (--port->users) +- airoha_set_port_mtu(dev->eth, port); ++ airoha_set_port_mtu(eth, port); + else +- airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ airoha_set_gdm_port_fwd_cfg(eth, + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (!--qdma->users) { -@@ -1801,6 +2065,8 @@ static int airoha_dev_stop(struct net_de +@@ -1923,6 +2199,8 @@ static int airoha_dev_stop(struct net_de } } -+ airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); + - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - phylink_stop(port->phylink); -@@ -2034,6 +2300,38 @@ int airoha_get_fe_port(struct airoha_gdm + phylink_stop(dev->phylink); + phylink_disconnect_phy(dev->phylink); + +@@ -2195,6 +2473,38 @@ int airoha_get_fe_port(struct airoha_gdm } } -+static netdev_features_t airoha_dev_fix_features(struct net_device *dev, ++static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, + netdev_features_t features) +{ -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; + + if (qdma->users > 1) + features &= ~NETIF_F_GRO_HW; @@ -492,12 +512,12 @@ Signed-off-by: Lorenzo Bianconi + return features; +} + -+static int airoha_dev_set_features(struct net_device *dev, ++static int airoha_dev_set_features(struct net_device *netdev, + netdev_features_t features) +{ -+ netdev_features_t diff = dev->features ^ features; -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; ++ netdev_features_t diff = netdev->features ^ features; ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + @@ -505,7 +525,7 @@ Signed-off-by: Lorenzo Bianconi + return 0; + + if (features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(port); ++ airoha_dev_lro_enable(dev); + else + airoha_fe_lro_disable(eth, qdma_id); + @@ -513,9 +533,9 @@ Signed-off-by: Lorenzo Bianconi +} + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, - struct net_device *dev) + struct net_device *netdev) { -@@ -2933,6 +3231,8 @@ static const struct net_device_ops airoh +@@ -3139,6 +3449,8 @@ static const struct net_device_ops airoh .ndo_stop = airoha_dev_stop, .ndo_change_mtu = airoha_dev_change_mtu, .ndo_select_queue = airoha_dev_select_queue, @@ -524,25 +544,24 @@ Signed-off-by: Lorenzo Bianconi .ndo_start_xmit = airoha_dev_xmit, .ndo_get_stats64 = airoha_dev_get_stats64, .ndo_set_mac_address = airoha_dev_set_macaddr, -@@ -3150,12 +3450,9 @@ static int airoha_alloc_gdm_port(struct - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | -- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | -- NETIF_F_SG | NETIF_F_TSO | -- NETIF_F_HW_TC; -- dev->features |= dev->hw_features; -- dev->vlan_features = dev->hw_features; -+ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -+ dev->features |= AIROHA_HW_FEATURES; -+ dev->vlan_features = AIROHA_HW_FEATURES; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); +@@ -3380,11 +3692,9 @@ static int airoha_alloc_gdm_device(struc + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; +- netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | +- NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- netdev->features |= netdev->hw_features; +- netdev->vlan_features = netdev->hw_features; ++ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; ++ netdev->features |= AIROHA_HW_FEATURES; ++ netdev->vlan_features = AIROHA_HW_FEATURES; + SET_NETDEV_DEV(netdev, eth->dev); + /* reserve hw queues for HTB offloading */ --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -43,6 +43,18 @@ +@@ -44,6 +44,18 @@ (_n) == 15 ? 128 : \ (_n) == 0 ? 1024 : 16) @@ -561,7 +580,7 @@ Signed-off-by: Lorenzo Bianconi #define PSE_RSV_PAGES 128 #define PSE_QUEUE_RSV_PAGES 64 -@@ -666,6 +678,18 @@ static inline bool airoha_is_7583(struct +@@ -676,6 +688,18 @@ static inline bool airoha_is_7583(struct return eth->soc->version == 0x7583; } @@ -577,9 +596,9 @@ Signed-off-by: Lorenzo Bianconi + return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); +} + - int airoha_get_fe_port(struct airoha_gdm_port *port); - bool airoha_is_valid_gdm_port(struct airoha_eth *eth, - struct airoha_gdm_port *port); + int airoha_get_fe_port(struct airoha_gdm_dev *dev); + bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, + struct airoha_gdm_dev *dev); --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -122,6 +122,20 @@ diff --git a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch deleted file mode 100644 index 92ce90e7ca9..00000000000 --- a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 917f959d54efd09719bd5047aa4b9543615e131e Mon Sep 17 00:00:00 2001 -Message-ID: <917f959d54efd09719bd5047aa4b9543615e131e.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Fri, 19 Dec 2025 23:12:32 +0100 -Subject: [PATCH 10/13] net: airoha: Rename airoha_set_gdm2_loopback in - airoha_enable_gdm2_loopback - -This is a preliminary patch in order to allow the user to select if the -configured device will be used as hw lan or wan. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2213,7 +2213,7 @@ static int airoha_dev_set_macaddr(struct - return 0; - } - --static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) -+static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) - { - struct airoha_gdm_port *port = dev->port; - struct airoha_eth *eth = dev->eth; -@@ -2346,7 +2346,7 @@ static int airoha_dev_init(struct net_de - (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { - int err; - -- err = airoha_set_gdm2_loopback(dev); -+ err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch index 2c16f2ac02d..77b37d54832 100644 --- a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch +++ b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -540,7 +540,7 @@ static bool airoha_fe_lro_is_enabled(str +@@ -533,7 +533,7 @@ static bool airoha_fe_lro_is_enabled(str static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) { @@ -28,7 +28,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_eth *eth = qdma->eth; int qdma_id = qdma - ð->qdma[0]; int i, lro_queue_index = 0; -@@ -1158,7 +1158,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -1159,7 +1159,7 @@ static void airoha_qdma_wake_netdev_txqs if (!dev) continue; @@ -37,7 +37,7 @@ Signed-off-by: Lorenzo Bianconi continue; netdev = netdev_from_priv(dev); -@@ -2031,7 +2031,8 @@ static void airoha_update_netdev_feature +@@ -2055,7 +2055,8 @@ static void airoha_update_netdev_feature if (!iter_dev || iter_dev == dev) continue; @@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi continue; netdev = netdev_from_priv(iter_dev); -@@ -2043,20 +2044,57 @@ static void airoha_update_netdev_feature +@@ -2067,20 +2068,57 @@ static void airoha_update_netdev_feature } } @@ -108,7 +108,7 @@ Signed-off-by: Lorenzo Bianconi if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", qdma_id); -@@ -2105,10 +2143,7 @@ static int airoha_dev_open(struct net_de +@@ -2123,10 +2161,7 @@ static int airoha_dev_open(struct net_de } port->users++; @@ -119,8 +119,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_qdma_start(qdma); if (!airoha_is_lan_gdm_dev(dev) && - airoha_ppe_is_enabled(eth, 1)) { -@@ -2154,8 +2189,7 @@ static int airoha_dev_stop(struct net_de + airoha_ppe_is_enabled(eth, 1)) +@@ -2170,8 +2205,7 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -130,7 +130,7 @@ Signed-off-by: Lorenzo Bianconi int i; netif_tx_disable(netdev); -@@ -2163,25 +2197,14 @@ static int airoha_dev_stop(struct net_de +@@ -2179,26 +2213,14 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); @@ -139,9 +139,9 @@ Signed-off-by: Lorenzo Bianconi - airoha_set_port_mtu(eth, port); + airoha_set_port_mtu(dev->eth, port); else -- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), +- airoha_set_gdm_port_fwd_cfg(eth, + airoha_set_gdm_port_fwd_cfg(qdma->eth, -+ REG_GDM_FWD_CFG(port->id), + REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); - - if (!--qdma->users) { @@ -160,8 +160,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_qdma_stop(qdma); airoha_update_netdev_features(dev); - #if defined(CONFIG_PCS_AIROHA) -@@ -2275,6 +2298,53 @@ static int airoha_enable_gdm2_loopback(s + phylink_stop(dev->phylink); +@@ -2288,6 +2310,53 @@ static int airoha_enable_gdm2_loopback(s return 0; } @@ -215,7 +215,7 @@ Signed-off-by: Lorenzo Bianconi static struct airoha_gdm_dev * airoha_get_wan_gdm_dev(struct airoha_eth *eth) { -@@ -2301,15 +2371,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth +@@ -2314,15 +2383,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) { struct net_device *netdev = netdev_from_priv(dev); @@ -248,7 +248,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_dev_init(struct net_device *netdev) -@@ -2473,8 +2558,9 @@ static netdev_features_t airoha_dev_fix_ +@@ -2477,8 +2561,9 @@ static netdev_features_t airoha_dev_fix_ netdev_features_t features) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -259,7 +259,7 @@ Signed-off-by: Lorenzo Bianconi if (qdma->users > 1) features &= ~NETIF_F_GRO_HW; -@@ -2486,9 +2572,8 @@ static int airoha_dev_set_features(struc +@@ -2490,9 +2575,8 @@ static int airoha_dev_set_features(struc { netdev_features_t diff = netdev->features ^ features; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -271,7 +271,7 @@ Signed-off-by: Lorenzo Bianconi if (!(diff & NETIF_F_GRO_HW)) return 0; -@@ -2496,7 +2581,7 @@ static int airoha_dev_set_features(struc +@@ -2500,7 +2584,7 @@ static int airoha_dev_set_features(struc if (features & NETIF_F_GRO_HW) airoha_dev_lro_enable(dev); else @@ -280,7 +280,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2505,9 +2590,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2509,9 +2593,9 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -291,7 +291,7 @@ Signed-off-by: Lorenzo Bianconi struct netdev_queue *txq; struct airoha_queue *q; LIST_HEAD(tx_list); -@@ -2516,6 +2601,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2520,6 +2604,8 @@ static netdev_tx_t airoha_dev_xmit(struc u16 index; u8 fport; @@ -300,7 +300,7 @@ Signed-off-by: Lorenzo Bianconi qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); tag = airoha_get_dsa_tag(skb, netdev); -@@ -2562,6 +2649,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2566,6 +2652,8 @@ static netdev_tx_t airoha_dev_xmit(struc netif_tx_stop_queue(txq); q->txq_stopped = true; spin_unlock_bh(&q->lock); @@ -309,7 +309,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_BUSY; } -@@ -2624,6 +2713,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2628,6 +2716,7 @@ static netdev_tx_t airoha_dev_xmit(struc FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); spin_unlock_bh(&q->lock); @@ -317,7 +317,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_OK; -@@ -2639,6 +2729,7 @@ error_unmap: +@@ -2643,6 +2732,7 @@ error_unmap: error: dev_kfree_skb_any(skb); netdev->stats.tx_dropped++; @@ -325,7 +325,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_OK; } -@@ -2720,17 +2811,19 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2740,17 +2830,19 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -347,7 +347,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2738,12 +2831,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2758,12 +2850,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -362,7 +362,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2807,13 +2900,15 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2827,13 +2919,15 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -384,7 +384,7 @@ Signed-off-by: Lorenzo Bianconi _bstats_update(opt->stats.bstats, 0, tx_packets); dev->cpu_tx_packets = cpu_tx_packets; -@@ -3073,16 +3168,18 @@ static int airoha_qdma_set_tx_rate_limit +@@ -3093,16 +3187,18 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -405,7 +405,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -3118,11 +3215,12 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -3138,11 +3234,12 @@ static int airoha_tc_htb_alloc_leaf_queu u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; int err, num_tx_queues = netdev->real_num_tx_queues; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -419,7 +419,7 @@ Signed-off-by: Lorenzo Bianconi if (test_and_set_bit(channel, qdma->qos_channel_map)) { NL_SET_ERR_MSG_MOD(opt->extack, "qdma qos channel already in use"); -@@ -3156,7 +3254,7 @@ static int airoha_qdma_set_rx_meter(stru +@@ -3176,7 +3273,7 @@ static int airoha_qdma_set_rx_meter(stru u32 rate, u32 bucket_size, enum trtcm_unit_type unit_type) { @@ -428,7 +428,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -3330,11 +3428,12 @@ static int airoha_dev_setup_tc_block(str +@@ -3350,11 +3447,12 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -442,7 +442,7 @@ Signed-off-by: Lorenzo Bianconi clear_bit(queue, qdma->qos_channel_map); clear_bit(queue, dev->qos_sq_bmap); } -@@ -3355,6 +3454,95 @@ static int airoha_tc_htb_delete_leaf_que +@@ -3375,6 +3473,95 @@ static int airoha_tc_htb_delete_leaf_que return 0; } @@ -538,7 +538,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -3363,6 +3551,8 @@ static int airoha_tc_htb_destroy(struct +@@ -3383,6 +3570,8 @@ static int airoha_tc_htb_destroy(struct for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) airoha_tc_remove_htb_queue(netdev, q); @@ -547,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3382,24 +3572,33 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -3402,24 +3591,33 @@ static int airoha_tc_get_htb_get_leaf_qu return 0; } @@ -588,16 +588,6 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3509,8 +3708,8 @@ static void airoha_mac_link_up(struct ph - { - struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, - phylink_config); -+ struct airoha_qdma *qdma = airoha_qdma_deref(dev); - struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; - --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -402,6 +402,7 @@ @@ -610,7 +600,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -552,11 +552,12 @@ struct airoha_qdma { +@@ -550,11 +550,12 @@ struct airoha_qdma { enum airoha_priv_flags { AIROHA_PRIV_F_WAN = BIT(0), @@ -623,8 +613,8 @@ Signed-off-by: Lorenzo Bianconi - struct airoha_qdma *qdma; struct airoha_eth *eth; - #if defined(CONFIG_PCS_AIROHA) -@@ -705,6 +706,16 @@ int airoha_get_fe_port(struct airoha_gdm + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +@@ -704,6 +705,16 @@ int airoha_get_fe_port(struct airoha_gdm bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, struct airoha_gdm_dev *dev); diff --git a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch index d17c537daa2..2e854b6f492 100644 --- a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch +++ b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch @@ -16,7 +16,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -188,10 +188,15 @@ static void airoha_fe_maccr_init(struct +@@ -181,10 +181,15 @@ static void airoha_fe_maccr_init(struct { int p; @@ -33,7 +33,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK, FIELD_PREP(CDM_VLAN_MASK, 0x8100)); -@@ -2078,15 +2083,25 @@ static void airoha_qdma_stop(struct airo +@@ -2102,15 +2107,25 @@ static void airoha_qdma_stop(struct airo } } @@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi /* HW LRO is configured on the QDMA and it is shared between * all the devices using it. Refuse to open a second device on -@@ -2128,19 +2143,7 @@ static int airoha_dev_open(struct net_de +@@ -2146,19 +2161,7 @@ static int airoha_dev_open(struct net_de airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); @@ -83,7 +83,7 @@ Signed-off-by: Lorenzo Bianconi port->users++; airoha_qdma_start(qdma); -@@ -2161,30 +2164,6 @@ static int airoha_dev_open(struct net_de +@@ -2177,30 +2180,6 @@ static int airoha_dev_open(struct net_de return 0; } @@ -114,7 +114,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2199,7 +2178,7 @@ static int airoha_dev_stop(struct net_de +@@ -2215,7 +2194,7 @@ static int airoha_dev_stop(struct net_de qdma = airoha_qdma_deref(dev); if (--port->users) @@ -123,7 +123,7 @@ Signed-off-by: Lorenzo Bianconi else airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -@@ -2258,10 +2237,6 @@ static int airoha_enable_gdm2_loopback(s +@@ -2274,10 +2253,6 @@ static int airoha_enable_gdm2_loopback(s FIELD_PREP(LPBK_CHAN_MASK, chan) | LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK | LBK_CHAN_MODE_MASK | LPBK_EN_MASK); @@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi /* Forward the traffic to the proper GDM port */ pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; -@@ -2469,7 +2444,7 @@ static int airoha_dev_change_mtu(struct +@@ -2472,7 +2447,7 @@ static int airoha_dev_change_mtu(struct WRITE_ONCE(netdev->mtu, mtu); if (port->users) @@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3471,6 +3446,7 @@ static void airoha_disable_qos_for_gdm34 +@@ -3490,6 +3465,7 @@ static void airoha_disable_qos_for_gdm34 dev->flags &= ~AIROHA_PRIV_F_WAN; airoha_dev_set_qdma(dev); @@ -151,7 +151,7 @@ Signed-off-by: Lorenzo Bianconi airoha_set_macaddr(dev, netdev->dev_addr); if (netif_running(netdev)) -@@ -3519,6 +3495,7 @@ static int airoha_enable_qos_for_gdm34(s +@@ -3538,6 +3514,7 @@ static int airoha_enable_qos_for_gdm34(s if (err) goto error_disable_loopback; @@ -169,7 +169,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_PACKET_SIZE 2048 #define AIROHA_NUM_QOS_CHANNELS 4 #define AIROHA_NUM_QOS_QUEUES 8 -@@ -716,6 +717,7 @@ airoha_qdma_deref(struct airoha_gdm_dev +@@ -715,6 +716,7 @@ airoha_qdma_deref(struct airoha_gdm_dev lockdep_is_held(&flow_offload_mutex)); } diff --git a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch index 2df1996d19a..a0a1ed01350 100644 --- a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch +++ b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch @@ -18,7 +18,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2543,17 +2543,9 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -2519,17 +2519,9 @@ static u32 airoha_get_dsa_tag(struct sk_ int airoha_get_fe_port(struct airoha_gdm_dev *dev) { struct airoha_gdm_port *port = dev->port; diff --git a/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch deleted file mode 100644 index 9cd99c759d7..00000000000 --- a/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 18aa76cd820c412358dc36d115b8e02d24a78f39 Mon Sep 17 00:00:00 2001 -Message-ID: <18aa76cd820c412358dc36d115b8e02d24a78f39.1780942778.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 8 Jun 2026 20:10:35 +0200 -Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of - airoha_enable_gdm2_loopback() - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2250,6 +2250,10 @@ static int airoha_enable_gdm2_loopback(s - u32 val, pse_port, chan; - int i, src_port; - -+ src_port = eth->soc->ops.get_sport(port, dev->nbq); -+ if (src_port < 0) -+ return src_port; -+ - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), - FE_PSE_PORT_DROP); - airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -@@ -2275,10 +2279,6 @@ static int airoha_enable_gdm2_loopback(s - airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); - airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); - -- src_port = eth->soc->ops.get_sport(port, dev->nbq); -- if (src_port < 0) -- return src_port; -- - airoha_fe_rmw(eth, REG_FE_WAN_PORT, - WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, - FIELD_PREP(WAN0_MASK, src_port));