diff --git a/target/linux/airoha/patches-6.12/145-01-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch b/target/linux/airoha/patches-6.12/145-01-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch new file mode 100644 index 0000000000..c4045cc8af --- /dev/null +++ b/target/linux/airoha/patches-6.12/145-01-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch @@ -0,0 +1,55 @@ +From f329924bb49458c65297f1361f545816a5b90998 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Apr 2026 08:36:31 +0200 +Subject: [PATCH 1/2] net: airoha: Move ndesc initialization at end of + airoha_qdma_init_tx() + +If queue entry list allocation fails in airoha_qdma_init_tx_queue routine, +airoha_qdma_cleanup_tx_queue() will trigger a NULL pointer dereference +accessing the queue entry array. The issue is due to the early ndesc +initialization in airoha_qdma_init_tx_queue(). Fix the issue moving ndesc +initialization at end of airoha_qdma_init_tx routine. + +Fixes: 3f47e67dff1f7 ("net: airoha: Add the capability to consume out-of-order DMA tx descriptors") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260417-airoha_qdma_cleanup_tx_queue-fix-net-v4-1-e04bcc2c9642@kernel.org +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +--- + 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 +@@ -954,27 +954,27 @@ static int airoha_qdma_init_tx_queue(str + dma_addr_t dma_addr; + + spin_lock_init(&q->lock); +- q->ndesc = size; + q->qdma = qdma; + q->free_thr = 1 + MAX_SKB_FRAGS; + INIT_LIST_HEAD(&q->tx_list); + +- q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), ++ q->entry = devm_kzalloc(eth->dev, size * sizeof(*q->entry), + GFP_KERNEL); + if (!q->entry) + return -ENOMEM; + +- q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), ++ q->desc = dmam_alloc_coherent(eth->dev, size * sizeof(*q->desc), + &dma_addr, GFP_KERNEL); + if (!q->desc) + return -ENOMEM; + +- for (i = 0; i < q->ndesc; i++) { ++ for (i = 0; i < size; i++) { + u32 val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); + + list_add_tail(&q->entry[i].list, &q->tx_list); + WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); + } ++ q->ndesc = size; + + /* xmit ring drop default setting */ + airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid), diff --git a/target/linux/airoha/patches-6.12/145-02-v7.1-net-airoha-Add-missing-bits-in-airoha_qdma_cleanup_t.patch b/target/linux/airoha/patches-6.12/145-02-v7.1-net-airoha-Add-missing-bits-in-airoha_qdma_cleanup_t.patch new file mode 100644 index 0000000000..424a45c50b --- /dev/null +++ b/target/linux/airoha/patches-6.12/145-02-v7.1-net-airoha-Add-missing-bits-in-airoha_qdma_cleanup_t.patch @@ -0,0 +1,73 @@ +From 3309965fe44c00fd65af7cef5016e9e782c021a7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Apr 2026 08:36:32 +0200 +Subject: [PATCH 2/2] net: airoha: Add missing bits in + airoha_qdma_cleanup_tx_queue() + +Similar to airoha_qdma_cleanup_rx_queue(), reset DMA TX descriptors in +airoha_qdma_cleanup_tx_queue routine. Moreover, reset TX_DMA_IDX to +TX_CPU_IDX to notify the NIC the QDMA TX ring is empty. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260417-airoha_qdma_cleanup_tx_queue-fix-net-v4-2-e04bcc2c9642@kernel.org +Reviewed-by: Simon Horman +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 32 ++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1039,12 +1039,15 @@ static int airoha_qdma_init_tx(struct ai + + static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) + { +- struct airoha_eth *eth = q->qdma->eth; +- int i; ++ struct airoha_qdma *qdma = q->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int i, qid = q - &qdma->q_tx[0]; ++ u16 index = 0; + + spin_lock_bh(&q->lock); + for (i = 0; i < q->ndesc; i++) { + struct airoha_queue_entry *e = &q->entry[i]; ++ struct airoha_qdma_desc *desc = &q->desc[i]; + + if (!e->dma_addr) + continue; +@@ -1055,8 +1058,33 @@ static void airoha_qdma_cleanup_tx_queue + e->dma_addr = 0; + e->skb = NULL; + list_add_tail(&e->list, &q->tx_list); ++ ++ /* Reset DMA descriptor */ ++ WRITE_ONCE(desc->ctrl, 0); ++ WRITE_ONCE(desc->addr, 0); ++ WRITE_ONCE(desc->data, 0); ++ WRITE_ONCE(desc->msg0, 0); ++ WRITE_ONCE(desc->msg1, 0); ++ WRITE_ONCE(desc->msg2, 0); ++ + q->queued--; + } ++ ++ if (!list_empty(&q->tx_list)) { ++ struct airoha_queue_entry *e; ++ ++ e = list_first_entry(&q->tx_list, struct airoha_queue_entry, ++ list); ++ index = e - q->entry; ++ } ++ /* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is ++ * empty. ++ */ ++ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, ++ FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); ++ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, ++ FIELD_PREP(TX_RING_DMA_IDX_MASK, index)); ++ + spin_unlock_bh(&q->lock); + } + diff --git a/target/linux/airoha/patches-6.12/146-v7.1-net-airoha-Wait-for-NPU-PPE-configuration-to-complet.patch b/target/linux/airoha/patches-6.12/146-v7.1-net-airoha-Wait-for-NPU-PPE-configuration-to-complet.patch new file mode 100644 index 0000000000..d7b4680b52 --- /dev/null +++ b/target/linux/airoha/patches-6.12/146-v7.1-net-airoha-Wait-for-NPU-PPE-configuration-to-complet.patch @@ -0,0 +1,63 @@ +From f3206328bb52c2787197d80d7cbd687946047d5f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 14 Apr 2026 16:08:52 +0200 +Subject: [PATCH] net: airoha: Wait for NPU PPE configuration to complete in + airoha_ppe_offload_setup() + +In order to properly enable flowtable hw offloading, poll +REG_PPE_FLOW_CFG register in airoha_ppe_offload_setup routine and +wait for NPU PPE configuration triggered by ppe_init callback to complete +before running airoha_ppe_hw_init(). + +Fixes: 00a7678310fe3 ("net: airoha: Introduce flowtable offload support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260414-airoha-wait-for-npu-config-offload-setup-v2-1-5a9bf6d43aee@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 28 ++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1354,6 +1354,29 @@ static struct airoha_npu *airoha_ppe_npu + return npu; + } + ++static int airoha_ppe_wait_for_npu_init(struct airoha_eth *eth) ++{ ++ int err; ++ u32 val; ++ ++ /* PPE_FLOW_CFG default register value is 0. Since we reset FE ++ * during the device probe we can just check the configured value ++ * is not 0 here. ++ */ ++ err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC, ++ 100 * USEC_PER_MSEC, false, eth, ++ REG_PPE_PPE_FLOW_CFG(0)); ++ if (err) ++ return err; ++ ++ if (airoha_ppe_is_enabled(eth, 1)) ++ err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC, ++ 100 * USEC_PER_MSEC, false, eth, ++ REG_PPE_PPE_FLOW_CFG(1)); ++ ++ return err; ++} ++ + static int airoha_ppe_offload_setup(struct airoha_eth *eth) + { + struct airoha_npu *npu = airoha_ppe_npu_get(eth); +@@ -1367,6 +1390,11 @@ static int airoha_ppe_offload_setup(stru + if (err) + goto error_npu_put; + ++ /* Wait for NPU PPE configuration to complete */ ++ err = airoha_ppe_wait_for_npu_init(eth); ++ if (err) ++ goto error_npu_put; ++ + ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); + if (ppe_num_stats_entries > 0) { + err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma, diff --git a/target/linux/airoha/patches-6.12/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch b/target/linux/airoha/patches-6.12/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch new file mode 100644 index 0000000000..39b0fdfd90 --- /dev/null +++ b/target/linux/airoha/patches-6.12/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch @@ -0,0 +1,91 @@ +From d647f2545219754603b2064de948425cdfd93fba Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Apr 2026 17:24:41 +0200 +Subject: [PATCH] net: airoha: Fix PPE cpu port configuration for GDM2 loopback + path + +When QoS loopback is enabled for GDM3 or GDM4, incoming packets are +forwarded to GDM2. However, the PPE cpu port for GDM2 is not configured +in this path, causing traffic originating from GDM3/GDM4, which may +be set up as WAN ports backed by QDMA1, to be incorrectly directed +to QDMA0 instead. +Configure the PPE cpu port for GDM2 when QoS loopback is active on +GDM3 or GDM4 to ensure traffic is routed to the correct QDMA instance. + +Fixes: 9cd451d414f6 ("net: airoha: Add loopback support for GDM2") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260417-airoha-ppe-cpu-port-for-gdm2-loopback-v1-1-c7a9de0f6f57@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++++-- + drivers/net/ethernet/airoha/airoha_eth.h | 3 ++- + drivers/net/ethernet/airoha/airoha_ppe.c | 6 +++--- + 3 files changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1755,7 +1755,7 @@ static int airoha_set_gdm2_loopback(stru + { + struct airoha_eth *eth = port->qdma->eth; + u32 val, pse_port, chan; +- int src_port; ++ int i, src_port; + + /* Forward the traffic to the proper GDM port */ + pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 +@@ -1797,6 +1797,9 @@ static int airoha_set_gdm2_loopback(stru + SP_CPORT_MASK(val), + __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); + ++ for (i = 0; i < eth->soc->num_ppe; i++) ++ 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(port->nbq); + +@@ -1835,7 +1838,8 @@ static int airoha_dev_init(struct net_de + } + + for (i = 0; i < eth->soc->num_ppe; i++) +- airoha_ppe_set_cpu_port(port, i); ++ airoha_ppe_set_cpu_port(port, i, ++ airoha_get_fe_port(port)); + + return 0; + } +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -653,7 +653,8 @@ int airoha_get_fe_port(struct airoha_gdm + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + +-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id); ++void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, ++ u8 fport); + bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index); + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, + u16 hash, bool rx_wlan); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -85,10 +85,9 @@ static u32 airoha_ppe_get_timestamp(stru + return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp); + } + +-void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id) ++void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, u8 fport) + { + struct airoha_qdma *qdma = port->qdma; +- u8 fport = airoha_get_fe_port(port); + struct airoha_eth *eth = qdma->eth; + u8 qdma_id = qdma - ð->qdma[0]; + u32 fe_cpu_port; +@@ -182,7 +181,8 @@ static void airoha_ppe_hw_init(struct ai + if (!port) + continue; + +- airoha_ppe_set_cpu_port(port, i); ++ airoha_ppe_set_cpu_port(port, i, ++ airoha_get_fe_port(port)); + } + } + } diff --git a/target/linux/airoha/patches-6.12/148-v7.1-net-airoha-Fix-possible-TX-queue-stall-in-airoha_qdm.patch b/target/linux/airoha/patches-6.12/148-v7.1-net-airoha-Fix-possible-TX-queue-stall-in-airoha_qdm.patch new file mode 100644 index 0000000000..fa0d9064ef --- /dev/null +++ b/target/linux/airoha/patches-6.12/148-v7.1-net-airoha-Fix-possible-TX-queue-stall-in-airoha_qdm.patch @@ -0,0 +1,104 @@ +From b94769eb2f30e61e86cd8551c084c34134290d89 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 16 Apr 2026 12:30:12 +0200 +Subject: [PATCH] net: airoha: Fix possible TX queue stall in + airoha_qdma_tx_napi_poll() + +Since multiple net_device TX queues can share the same hw QDMA TX queue, +there is no guarantee we have inflight packets queued in hw belonging to a +net_device TX queue stopped in the xmit path because hw QDMA TX queue +can be full. In this corner case the net_device TX queue will never be +re-activated. In order to avoid any potential net_device TX queue stall, +we need to wake all the net_device TX queues feeding the same hw QDMA TX +queue in airoha_qdma_tx_napi_poll routine. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260416-airoha-txq-potential-stall-v2-1-42c732074540@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 37 ++++++++++++++++++++---- + drivers/net/ethernet/airoha/airoha_eth.h | 1 + + 2 files changed, 33 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -843,6 +843,21 @@ static int airoha_qdma_init_rx(struct ai + return 0; + } + ++static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q) ++{ ++ struct airoha_qdma *qdma = q->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ struct airoha_gdm_port *port = eth->ports[i]; ++ ++ if (port && port->qdma == qdma) ++ netif_tx_wake_all_queues(port->dev); ++ } ++ q->txq_stopped = false; ++} ++ + static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) + { + struct airoha_tx_irq_queue *irq_q; +@@ -919,12 +934,21 @@ static int airoha_qdma_tx_napi_poll(stru + + txq = netdev_get_tx_queue(skb->dev, queue); + netdev_tx_completed_queue(txq, 1, skb->len); +- if (netif_tx_queue_stopped(txq) && +- q->ndesc - q->queued >= q->free_thr) +- netif_tx_wake_queue(txq); +- + dev_kfree_skb_any(skb); + } ++ ++ if (q->txq_stopped && q->ndesc - q->queued >= q->free_thr) { ++ /* Since multiple net_device TX queues can share the ++ * same hw QDMA TX queue, there is no guarantee we have ++ * inflight packets queued in hw belonging to a ++ * net_device TX queue stopped in the xmit path. ++ * In order to avoid any potential net_device TX queue ++ * stall, we need to wake all the net_device TX queues ++ * feeding the same hw QDMA TX queue. ++ */ ++ airoha_qdma_wake_netdev_txqs(q); ++ } ++ + unlock: + spin_unlock_bh(&q->lock); + } +@@ -2016,6 +2040,7 @@ static netdev_tx_t airoha_dev_xmit(struc + if (q->queued + nr_frags >= q->ndesc) { + /* not enough space in the queue */ + netif_tx_stop_queue(txq); ++ q->txq_stopped = true; + spin_unlock_bh(&q->lock); + return NETDEV_TX_BUSY; + } +@@ -2071,8 +2096,10 @@ static netdev_tx_t airoha_dev_xmit(struc + TX_RING_CPU_IDX_MASK, + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + +- if (q->ndesc - q->queued < q->free_thr) ++ if (q->ndesc - q->queued < q->free_thr) { + netif_tx_stop_queue(txq); ++ q->txq_stopped = true; ++ } + + spin_unlock_bh(&q->lock); + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -193,6 +193,7 @@ struct airoha_queue { + int ndesc; + int free_thr; + int buf_size; ++ bool txq_stopped; + + struct napi_struct napi; + struct page_pool *page_pool; diff --git a/target/linux/airoha/patches-6.12/149-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch b/target/linux/airoha/patches-6.12/149-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch new file mode 100644 index 0000000000..29b6024a5a --- /dev/null +++ b/target/linux/airoha/patches-6.12/149-v7.1-net-airoha-Move-ndesc-initialization-at-end-of-airoh.patch @@ -0,0 +1,61 @@ +From 379050947a1828826ad7ea50c95245a56929b35a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 20 Apr 2026 10:07:47 +0200 +Subject: [PATCH] net: airoha: Move ndesc initialization at end of + airoha_qdma_init_rx_queue() + +If queue entry or DMA descriptor list allocation fails in +airoha_qdma_init_rx_queue routine, airoha_qdma_cleanup() will trigger a +NULL pointer dereference running netif_napi_del() for RX queue NAPIs +since netif_napi_add() has never been executed to this particular RX NAPI. +The issue is due to the early ndesc initialization in +airoha_qdma_init_rx_queue() since airoha_qdma_cleanup() relies on ndesc +value to check if the queue is properly initialized. Fix the issue moving +ndesc initialization at end of airoha_qdma_init_tx routine. +Move page_pool allocation after descriptor list allocation in order to +avoid memory leaks if desc allocation fails. + +Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260420-airoha_qdma_init_rx_queue-fix-v2-1-d99347e5c18d@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -745,14 +745,18 @@ static int airoha_qdma_init_rx_queue(str + dma_addr_t dma_addr; + + q->buf_size = PAGE_SIZE / 2; +- q->ndesc = ndesc; + q->qdma = qdma; + +- q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), ++ q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), + GFP_KERNEL); + if (!q->entry) + return -ENOMEM; + ++ q->desc = dmam_alloc_coherent(eth->dev, ndesc * sizeof(*q->desc), ++ &dma_addr, GFP_KERNEL); ++ if (!q->desc) ++ return -ENOMEM; ++ + q->page_pool = page_pool_create(&pp_params); + if (IS_ERR(q->page_pool)) { + int err = PTR_ERR(q->page_pool); +@@ -761,11 +765,7 @@ static int airoha_qdma_init_rx_queue(str + return err; + } + +- q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), +- &dma_addr, GFP_KERNEL); +- if (!q->desc) +- return -ENOMEM; +- ++ q->ndesc = ndesc; + netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); + + airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr); diff --git a/target/linux/airoha/patches-6.12/150-v7.1-net-airoha-Add-size-check-for-TX-NAPIs-in-airoha_qdm.patch b/target/linux/airoha/patches-6.12/150-v7.1-net-airoha-Add-size-check-for-TX-NAPIs-in-airoha_qdm.patch new file mode 100644 index 0000000000..ea5adb1b1b --- /dev/null +++ b/target/linux/airoha/patches-6.12/150-v7.1-net-airoha-Add-size-check-for-TX-NAPIs-in-airoha_qdm.patch @@ -0,0 +1,57 @@ +From 4b91cb65789b794bfc8d50554b8994f8e0f16309 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 20 Apr 2026 10:07:48 +0200 +Subject: [PATCH] net: airoha: Add size check for TX NAPIs in + airoha_qdma_cleanup() + +If airoha_qdma_init routine fails before airoha_qdma_tx_irq_init() runs +successfully for all TX NAPIs, airoha_qdma_cleanup() will +unconditionally runs netif_napi_del() on TX NAPIs, triggering a NULL +pointer dereference. Fix the issue relying on q_tx_irq size value to +check if the TX NAPIs is properly initialized in airoha_qdma_cleanup(). +Moreover, run netif_napi_add_tx() just if irq_q queue is properly +allocated. + +Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260420-airoha_qdma_init_rx_queue-fix-v2-2-d99347e5c18d@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1020,8 +1020,6 @@ static int airoha_qdma_tx_irq_init(struc + struct airoha_eth *eth = qdma->eth; + dma_addr_t dma_addr; + +- netif_napi_add_tx(eth->napi_dev, &irq_q->napi, +- airoha_qdma_tx_napi_poll); + irq_q->q = dmam_alloc_coherent(eth->dev, size * sizeof(u32), + &dma_addr, GFP_KERNEL); + if (!irq_q->q) +@@ -1031,6 +1029,9 @@ static int airoha_qdma_tx_irq_init(struc + irq_q->size = size; + irq_q->qdma = qdma; + ++ netif_napi_add_tx(eth->napi_dev, &irq_q->napi, ++ airoha_qdma_tx_napi_poll); ++ + airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr); + airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK, + FIELD_PREP(TX_IRQ_DEPTH_MASK, size)); +@@ -1450,8 +1451,12 @@ static void airoha_qdma_cleanup(struct a + } + } + +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { ++ if (!qdma->q_tx_irq[i].size) ++ continue; ++ + netif_napi_del(&qdma->q_tx_irq[i].napi); ++ } + + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { + if (!qdma->q_tx[i].ndesc) diff --git a/target/linux/airoha/patches-6.12/151-v7.1-net-airoha-fix-BQL-imbalance-in-TX-path.patch b/target/linux/airoha/patches-6.12/151-v7.1-net-airoha-fix-BQL-imbalance-in-TX-path.patch new file mode 100644 index 0000000000..8128607913 --- /dev/null +++ b/target/linux/airoha/patches-6.12/151-v7.1-net-airoha-fix-BQL-imbalance-in-TX-path.patch @@ -0,0 +1,59 @@ +From 2d9f5a118205da2683ffcec78b9347f1f01a820e Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 21 Apr 2026 08:35:11 +0200 +Subject: [PATCH] net: airoha: fix BQL imbalance in TX path + +Fix a possible BQL imbalance in airoha_dev_xmit(), where inflight +packets are accounted only for the AIROHA_NUM_TX_RING netdev TX +queues. The queue index is computed as: + + qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx) + txq = netdev_get_tx_queue(dev, qid); + +However, airoha_qdma_tx_napi_poll() accounts completions across all +netdev TX queues (num_tx_queues), leading to inconsistent BQL +accounting. + +Also reset all netdev TX queues in the ndo_stop callback. + +Fixes: 1d304174106c ("net: airoha: Implement BQL support") +Fixes: c9f947769b77 ("net: airoha: Reset BQL stopping the netdevice") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260421-airoha-fix-bql-v1-1-f135afe4275b@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -929,10 +929,9 @@ static int airoha_qdma_tx_napi_poll(stru + q->queued--; + + if (skb) { +- u16 queue = skb_get_queue_mapping(skb); + struct netdev_queue *txq; + +- txq = netdev_get_tx_queue(skb->dev, queue); ++ txq = skb_get_tx_queue(skb->dev, skb); + netdev_tx_completed_queue(txq, 1, skb->len); + dev_kfree_skb_any(skb); + } +@@ -1744,7 +1743,7 @@ static int airoha_dev_stop(struct net_de + if (err) + return err; + +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) ++ for (i = 0; i < dev->num_tx_queues; i++) + netdev_tx_reset_subqueue(dev, i); + + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), +@@ -2039,7 +2038,7 @@ static netdev_tx_t airoha_dev_xmit(struc + + spin_lock_bh(&q->lock); + +- txq = netdev_get_tx_queue(dev, qid); ++ txq = skb_get_tx_queue(dev, skb); + nr_frags = 1 + skb_shinfo(skb)->nr_frags; + + if (q->queued + nr_frags >= q->ndesc) { diff --git a/target/linux/airoha/patches-6.12/152-v7.1-net-airoha-stop-net_device-TX-queue-before-updating-.patch b/target/linux/airoha/patches-6.12/152-v7.1-net-airoha-stop-net_device-TX-queue-before-updating-.patch new file mode 100644 index 0000000000..f8a031e0d4 --- /dev/null +++ b/target/linux/airoha/patches-6.12/152-v7.1-net-airoha-stop-net_device-TX-queue-before-updating-.patch @@ -0,0 +1,46 @@ +From 3854de7b38be742cf7558476956d12414cb274f2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 21 Apr 2026 08:43:07 +0200 +Subject: [PATCH] net: airoha: stop net_device TX queue before updating CPU + index + +Currently, airoha_eth driver updates the CPU index register prior of +verifying whether the number of free descriptors has fallen below the +threshold. +Move net_device TX queue length check before updating the TX CPU index +in order to update TX CPU index even if there are more packets to be +transmitted but the net_device TX queue is going to be stopped +accounting the inflight packets. + +Fixes: 1d304174106c ("net: airoha: Implement BQL support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260421-airoha-xmit-stop-condition-v1-1-e670d6a48467@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2094,17 +2094,16 @@ static netdev_tx_t airoha_dev_xmit(struc + + skb_tx_timestamp(skb); + netdev_tx_sent_queue(txq, skb->len); ++ if (q->ndesc - q->queued < q->free_thr) { ++ netif_tx_stop_queue(txq); ++ q->txq_stopped = true; ++ } + + if (netif_xmit_stopped(txq) || !netdev_xmit_more()) + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), + TX_RING_CPU_IDX_MASK, + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + +- if (q->ndesc - q->queued < q->free_thr) { +- netif_tx_stop_queue(txq); +- q->txq_stopped = true; +- } +- + spin_unlock_bh(&q->lock); + + return NETDEV_TX_OK; diff --git a/target/linux/airoha/patches-6.12/153-v7.1-net-airoha-Do-not-wake-all-netdev-TX-queues-in-airoh.patch b/target/linux/airoha/patches-6.12/153-v7.1-net-airoha-Do-not-wake-all-netdev-TX-queues-in-airoh.patch new file mode 100644 index 0000000000..28a9e26e95 --- /dev/null +++ b/target/linux/airoha/patches-6.12/153-v7.1-net-airoha-Do-not-wake-all-netdev-TX-queues-in-airoh.patch @@ -0,0 +1,75 @@ +From e070aac63b42bf81f4dc565f9f841ff47e6c992f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 21 Apr 2026 10:53:33 +0200 +Subject: [PATCH] net: airoha: Do not wake all netdev TX queues in + airoha_qdma_wake_netdev_txqs() + +Do not wake every netdev TX queue across all ports sharing the QDMA +running netif_tx_wake_all_queues routine in airoha_qdma_wake_netdev_txqs() +but only the ones that are mapped the specific QDMA stopped hw TX queue. +This patch can potentially avoid waking already stopped netdev TX queues +that are mapped to a different QDMA hw TX queue. +Introduce airoha_qdma_get_txq utility routine. + +Fixes: b94769eb2f30 ("net: airoha: Fix possible TX queue stall in airoha_qdma_tx_napi_poll()") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260421-airoha-wake_netdev_txqs-optmization-v1-1-e0be95115d53@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 19 +++++++++++++++---- + drivers/net/ethernet/airoha/airoha_eth.h | 5 +++++ + 2 files changed, 20 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -847,13 +847,24 @@ static void airoha_qdma_wake_netdev_txqs + { + struct airoha_qdma *qdma = q->qdma; + struct airoha_eth *eth = qdma->eth; +- int i; ++ int i, qid = q - &qdma->q_tx[0]; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; ++ int j; + +- if (port && port->qdma == qdma) +- netif_tx_wake_all_queues(port->dev); ++ if (!port) ++ continue; ++ ++ if (port->qdma != qdma) ++ continue; ++ ++ for (j = 0; j < port->dev->num_tx_queues; j++) { ++ if (airoha_qdma_get_txq(qdma, j) != qid) ++ continue; ++ ++ netif_wake_subqueue(port->dev, j); ++ } + } + q->txq_stopped = false; + } +@@ -2001,7 +2012,7 @@ static netdev_tx_t airoha_dev_xmit(struc + u16 index; + u8 fport; + +- qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); ++ qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); + tag = airoha_get_dsa_tag(skb, dev); + + msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -631,6 +631,11 @@ u32 airoha_rmw(void __iomem *base, u32 o + #define airoha_qdma_clear(qdma, offset, val) \ + airoha_rmw((qdma)->regs, (offset), (val), 0) + ++static inline u16 airoha_qdma_get_txq(struct airoha_qdma *qdma, u16 qid) ++{ ++ return qid % ARRAY_SIZE(qdma->q_tx); ++} ++ + static inline bool airoha_is_lan_gdm_port(struct airoha_gdm_port *port) + { + /* GDM1 port on EN7581 SoC is connected to the lan dsa switch. diff --git a/target/linux/airoha/patches-6.12/154-v7.1-net-airoha-Do-not-read-uninitialized-fragment-addres.patch b/target/linux/airoha/patches-6.12/154-v7.1-net-airoha-Do-not-read-uninitialized-fragment-addres.patch new file mode 100644 index 0000000000..0980e5d31c --- /dev/null +++ b/target/linux/airoha/patches-6.12/154-v7.1-net-airoha-Do-not-read-uninitialized-fragment-addres.patch @@ -0,0 +1,64 @@ +From bde34e84edc8b5571fbde7e941e175a4293ee1eb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 24 Apr 2026 11:00:28 +0200 +Subject: [PATCH] net: airoha: Do not read uninitialized fragment address in + airoha_dev_xmit() + +The transmit loop in airoha_dev_xmit() reads fragment address and length +during its final iteration, when the loop index equals +skb_shinfo(skb)->nr_frags, at which point the fragment data is +uninitialized. While these values are never consumed, the read itself is +unsafe and may trigger a page fault. Fix this by avoiding the fragment +read on the last iteration. +Additionally, move the skb pointer from the first to the last used packet +descriptor, so that airoha_qdma_tx_napi_poll() defers freeing the skb +until the final descriptor is processed. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260424-airoha-xmit-fix-read-frag-v1-1-fdc0a83c79e8@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2007,8 +2007,8 @@ static netdev_tx_t airoha_dev_xmit(struc + struct netdev_queue *txq; + struct airoha_queue *q; + LIST_HEAD(tx_list); ++ int i = 0, qid; + void *data; +- int i, qid; + u16 index; + u8 fport; + +@@ -2067,7 +2067,7 @@ static netdev_tx_t airoha_dev_xmit(struc + list); + index = e - q->entry; + +- for (i = 0; i < nr_frags; i++) { ++ while (true) { + struct airoha_qdma_desc *desc = &q->desc[index]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + dma_addr_t addr; +@@ -2079,7 +2079,7 @@ static netdev_tx_t airoha_dev_xmit(struc + goto error_unmap; + + list_move_tail(&e->list, &tx_list); +- e->skb = i ? NULL : skb; ++ e->skb = i == nr_frags - 1 ? skb : NULL; + e->dma_addr = addr; + e->dma_len = len; + +@@ -2098,6 +2098,9 @@ static netdev_tx_t airoha_dev_xmit(struc + WRITE_ONCE(desc->msg1, cpu_to_le32(msg1)); + WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff)); + ++ if (++i == nr_frags) ++ break; ++ + data = skb_frag_address(frag); + len = skb_frag_size(frag); + } diff --git a/target/linux/airoha/patches-6.12/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch b/target/linux/airoha/patches-6.12/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch index 6d5b7c5e95..2d9ee580d6 100644 --- a/target/linux/airoha/patches-6.12/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch +++ b/target/linux/airoha/patches-6.12/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 -@@ -1423,6 +1423,10 @@ static int airoha_hw_init(struct platfor +@@ -1490,6 +1490,10 @@ static int airoha_hw_init(struct platfor if (err) return err; diff --git a/target/linux/airoha/patches-6.12/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch b/target/linux/airoha/patches-6.12/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch index 248aaa31a9..7dcdd745af 100644 --- a/target/linux/airoha/patches-6.12/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch +++ b/target/linux/airoha/patches-6.12/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch @@ -28,7 +28,7 @@ Signed-off-by: Christian Marangi airoha_fe_crsn_qsel_init(eth); -@@ -1655,7 +1657,8 @@ static int airoha_dev_open(struct net_de +@@ -1722,7 +1724,8 @@ static int airoha_dev_open(struct net_de if (err) return err; diff --git a/target/linux/airoha/patches-6.12/310-07-airoha-ethernet-drop-xsi-mac-reset.patch b/target/linux/airoha/patches-6.12/310-07-airoha-ethernet-drop-xsi-mac-reset.patch index f5246dd01d..1e70f32e9d 100644 --- a/target/linux/airoha/patches-6.12/310-07-airoha-ethernet-drop-xsi-mac-reset.patch +++ b/target/linux/airoha/patches-6.12/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 -@@ -3126,7 +3126,6 @@ static void airoha_remove(struct platfor +@@ -3202,7 +3202,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", -@@ -3180,7 +3179,6 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3256,7 +3255,6 @@ static u32 airoha_en7581_get_vip_port(st } static const char * const an7583_xsi_rsts_names[] = { diff --git a/target/linux/airoha/patches-6.12/310-10-net-airoha-add-phylink-support-for-GDM2-4.patch b/target/linux/airoha/patches-6.12/310-10-net-airoha-add-phylink-support-for-GDM2-4.patch index 9d23c58b2f..a6a44f1b98 100644 --- a/target/linux/airoha/patches-6.12/310-10-net-airoha-add-phylink-support-for-GDM2-4.patch +++ b/target/linux/airoha/patches-6.12/310-10-net-airoha-add-phylink-support-for-GDM2-4.patch @@ -35,7 +35,7 @@ Signed-off-by: Christian Marangi static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) { struct airoha_eth *eth = port->qdma->eth; -@@ -1652,6 +1658,17 @@ static int airoha_dev_open(struct net_de +@@ -1719,6 +1725,17 @@ static int airoha_dev_open(struct net_de struct airoha_qdma *qdma = port->qdma; u32 pse_port = FE_PSE_PORT_PPE1; @@ -53,7 +53,7 @@ Signed-off-by: Christian Marangi netif_tx_start_all_queues(dev); err = airoha_set_vip_for_gdm_port(port, true); if (err) -@@ -1716,6 +1733,11 @@ static int airoha_dev_stop(struct net_de +@@ -1783,6 +1800,11 @@ static int airoha_dev_stop(struct net_de } } @@ -65,7 +65,7 @@ Signed-off-by: Christian Marangi return 0; } -@@ -2846,6 +2868,20 @@ static const struct ethtool_ops airoha_e +@@ -2922,6 +2944,20 @@ static const struct ethtool_ops airoha_e .get_link = ethtool_op_get_link, }; @@ -86,7 +86,7 @@ Signed-off-by: Christian Marangi static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) { int i; -@@ -2890,6 +2926,99 @@ bool airoha_is_valid_gdm_port(struct air +@@ -2966,6 +3002,99 @@ bool airoha_is_valid_gdm_port(struct air return false; } @@ -186,7 +186,7 @@ Signed-off-by: Christian Marangi static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) { -@@ -2963,6 +3092,12 @@ static int airoha_alloc_gdm_port(struct +@@ -3039,6 +3168,12 @@ static int airoha_alloc_gdm_port(struct port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; eth->ports[p] = port; @@ -199,7 +199,7 @@ Signed-off-by: Christian Marangi return airoha_metadata_dst_alloc(port); } -@@ -3092,6 +3227,10 @@ error_napi_stop: +@@ -3168,6 +3303,10 @@ error_napi_stop: if (port->dev->reg_state == NETREG_REGISTERED) unregister_netdev(port->dev); @@ -210,7 +210,7 @@ Signed-off-by: Christian Marangi airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3118,6 +3257,10 @@ static void airoha_remove(struct platfor +@@ -3194,6 +3333,10 @@ static void airoha_remove(struct platfor unregister_netdev(port->dev); airoha_metadata_dst_free(port); @@ -223,7 +223,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -539,6 +539,10 @@ struct airoha_gdm_port { +@@ -540,6 +540,10 @@ struct airoha_gdm_port { int id; int nbq; diff --git a/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch b/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch index 699b11c60e..35e0b5fa55 100644 --- a/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch +++ b/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch @@ -28,7 +28,7 @@ Signed-off-by: Mikhail Kshevetskiy static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) { -@@ -1661,6 +1663,7 @@ static int airoha_dev_open(struct net_de +@@ -1728,6 +1730,7 @@ static int airoha_dev_open(struct net_de struct airoha_qdma *qdma = port->qdma; u32 pse_port = FE_PSE_PORT_PPE1; @@ -36,7 +36,7 @@ Signed-off-by: Mikhail Kshevetskiy if (airhoa_is_phy_external(port)) { err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); if (err) { -@@ -1671,6 +1674,7 @@ static int airoha_dev_open(struct net_de +@@ -1738,6 +1741,7 @@ static int airoha_dev_open(struct net_de phylink_start(port->phylink); } @@ -44,7 +44,7 @@ Signed-off-by: Mikhail Kshevetskiy netif_tx_start_all_queues(dev); err = airoha_set_vip_for_gdm_port(port, true); -@@ -1736,10 +1740,12 @@ static int airoha_dev_stop(struct net_de +@@ -1803,10 +1807,12 @@ static int airoha_dev_stop(struct net_de } } @@ -57,7 +57,7 @@ Signed-off-by: Mikhail Kshevetskiy return 0; } -@@ -2871,6 +2877,7 @@ static const struct ethtool_ops airoha_e +@@ -2947,6 +2953,7 @@ static const struct ethtool_ops airoha_e .get_link = ethtool_op_get_link, }; @@ -65,7 +65,7 @@ Signed-off-by: Mikhail Kshevetskiy static struct phylink_pcs *airoha_phylink_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { -@@ -2884,6 +2891,7 @@ static void airoha_mac_config(struct phy +@@ -2960,6 +2967,7 @@ static void airoha_mac_config(struct phy const struct phylink_link_state *state) { } @@ -73,7 +73,7 @@ Signed-off-by: Mikhail Kshevetskiy static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) { -@@ -2929,6 +2937,7 @@ bool airoha_is_valid_gdm_port(struct air +@@ -3005,6 +3013,7 @@ bool airoha_is_valid_gdm_port(struct air return false; } @@ -81,7 +81,7 @@ Signed-off-by: Mikhail Kshevetskiy 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) -@@ -3021,6 +3030,7 @@ static int airoha_setup_phylink(struct n +@@ -3097,6 +3106,7 @@ static int airoha_setup_phylink(struct n return 0; } @@ -89,7 +89,7 @@ Signed-off-by: Mikhail Kshevetskiy static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) -@@ -3095,11 +3105,13 @@ static int airoha_alloc_gdm_port(struct +@@ -3171,11 +3181,13 @@ static int airoha_alloc_gdm_port(struct port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; eth->ports[p] = port; @@ -103,7 +103,7 @@ Signed-off-by: Mikhail Kshevetskiy return airoha_metadata_dst_alloc(port); } -@@ -3230,10 +3242,12 @@ error_napi_stop: +@@ -3306,10 +3318,12 @@ error_napi_stop: if (port->dev->reg_state == NETREG_REGISTERED) unregister_netdev(port->dev); @@ -116,7 +116,7 @@ Signed-off-by: Mikhail Kshevetskiy airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3260,10 +3274,12 @@ static void airoha_remove(struct platfor +@@ -3336,10 +3350,12 @@ static void airoha_remove(struct platfor unregister_netdev(port->dev); airoha_metadata_dst_free(port); @@ -131,7 +131,7 @@ Signed-off-by: Mikhail Kshevetskiy --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -539,9 +539,11 @@ struct airoha_gdm_port { +@@ -540,9 +540,11 @@ struct airoha_gdm_port { int id; int nbq;