diff --git a/target/linux/airoha/patches-6.12/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch b/target/linux/airoha/patches-6.12/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch new file mode 100644 index 0000000000..7515e5a79c --- /dev/null +++ b/target/linux/airoha/patches-6.12/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch @@ -0,0 +1,63 @@ +From cedc1bf327de62ec30af9743bd1f601c2de30553 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sun, 29 Mar 2026 12:32:27 +0200 +Subject: [PATCH] net: airoha: Delay offloading until all net_devices are fully + registered + +Netfilter flowtable can theoretically try to offload flower rules as soon +as a net_device is registered while all the other ones are not +registered or initialized, triggering a possible NULL pointer dereferencing +of qdma pointer in airoha_ppe_set_cpu_port routine. Moreover, if +register_netdev() fails for a particular net_device, there is a small +race if Netfilter tries to offload flowtable rules before all the +net_devices are properly unregistered in airoha_probe() error patch, +triggering a NULL pointer dereferencing in airoha_ppe_set_cpu_port +routine. In order to avoid any possible race, delay offloading until +all net_devices are registered in the networking subsystem. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260329-airoha-regiser-race-fix-v2-1-f4ebb139277b@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 ++ + drivers/net/ethernet/airoha/airoha_eth.h | 1 + + drivers/net/ethernet/airoha/airoha_ppe.c | 7 +++++++ + 3 files changed, 10 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2957,6 +2957,8 @@ static int airoha_register_gdm_devices(s + return err; + } + ++ set_bit(DEV_STATE_REGISTERED, ð->state); ++ + return 0; + } + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -88,6 +88,7 @@ enum { + + enum { + DEV_STATE_INITIALIZED, ++ DEV_STATE_REGISTERED, + }; + + enum { +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1387,6 +1387,13 @@ int airoha_ppe_setup_tc_block_cb(struct + struct airoha_eth *eth = ppe->eth; + int err = 0; + ++ /* Netfilter flowtable can try to offload flower rules while not all ++ * the net_devices are registered or initialized. Delay offloading ++ * until all net_devices are registered in the system. ++ */ ++ if (!test_bit(DEV_STATE_REGISTERED, ð->state)) ++ return -EBUSY; ++ + mutex_lock(&flow_offload_mutex); + + if (!eth->npu) diff --git a/target/linux/airoha/patches-6.12/135-v7.1-net-airoha-Add-missing-cleanup-bits-in-airoha_qdma_c.patch b/target/linux/airoha/patches-6.12/135-v7.1-net-airoha-Add-missing-cleanup-bits-in-airoha_qdma_c.patch new file mode 100644 index 0000000000..d9293c7673 --- /dev/null +++ b/target/linux/airoha/patches-6.12/135-v7.1-net-airoha-Add-missing-cleanup-bits-in-airoha_qdma_c.patch @@ -0,0 +1,57 @@ +From 514aac3599879a7ed48b7dc19e31145beb6958ac Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 27 Mar 2026 10:48:21 +0100 +Subject: [PATCH] net: airoha: Add missing cleanup bits in + airoha_qdma_cleanup_rx_queue() + +In order to properly cleanup hw rx QDMA queues and bring the device to +the initial state, reset rx DMA queue head/tail index. Moreover, reset +queued DMA descriptor fields. + +Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Tested-by: Madhur Agrawal +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260327-airoha_qdma_cleanup_rx_queue-fix-v1-1-369d6ab1511a@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -794,18 +794,34 @@ static int airoha_qdma_init_rx_queue(str + + static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) + { +- struct airoha_eth *eth = q->qdma->eth; ++ struct airoha_qdma *qdma = q->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qid = q - &qdma->q_rx[0]; + + while (q->queued) { + struct airoha_queue_entry *e = &q->entry[q->tail]; ++ struct airoha_qdma_desc *desc = &q->desc[q->tail]; + struct page *page = virt_to_head_page(e->buf); + + dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, + page_pool_get_dma_dir(q->page_pool)); + page_pool_put_full_page(q->page_pool, page, false); ++ /* 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); ++ WRITE_ONCE(desc->msg3, 0); ++ + q->tail = (q->tail + 1) % q->ndesc; + q->queued--; + } ++ ++ q->head = q->tail; ++ airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, ++ FIELD_PREP(RX_RING_DMA_IDX_MASK, q->tail)); + } + + static int airoha_qdma_init_rx(struct airoha_qdma *qdma) 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 67e9f03d8a..7c7f51e5cc 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 -@@ -1409,6 +1409,10 @@ static int airoha_hw_init(struct platfor +@@ -1425,6 +1425,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 6c2ef5df53..8c2718334d 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); -@@ -1641,7 +1643,8 @@ static int airoha_dev_open(struct net_de +@@ -1657,7 +1659,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 805ae09fec..166c1efd26 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 -@@ -3109,7 +3109,6 @@ static void airoha_remove(struct platfor +@@ -3127,7 +3127,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", -@@ -3141,7 +3140,6 @@ static int airoha_en7581_get_src_port_id +@@ -3159,7 +3158,6 @@ static int airoha_en7581_get_src_port_id } 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 3cf1dd8c2e..ed12c5684a 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; -@@ -1638,6 +1644,17 @@ static int airoha_dev_open(struct net_de +@@ -1654,6 +1660,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) -@@ -1702,6 +1719,11 @@ static int airoha_dev_stop(struct net_de +@@ -1718,6 +1735,11 @@ static int airoha_dev_stop(struct net_de } } @@ -65,7 +65,7 @@ Signed-off-by: Christian Marangi return 0; } -@@ -2833,6 +2855,20 @@ static const struct ethtool_ops airoha_e +@@ -2849,6 +2871,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; -@@ -2877,6 +2913,99 @@ bool airoha_is_valid_gdm_port(struct air +@@ -2893,6 +2929,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) { -@@ -2948,6 +3077,12 @@ static int airoha_alloc_gdm_port(struct +@@ -2964,6 +3093,12 @@ static int airoha_alloc_gdm_port(struct port->id = id; eth->ports[p] = port; @@ -199,7 +199,7 @@ Signed-off-by: Christian Marangi return airoha_metadata_dst_alloc(port); } -@@ -3075,6 +3210,10 @@ error_napi_stop: +@@ -3093,6 +3228,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); -@@ -3101,6 +3240,10 @@ static void airoha_remove(struct platfor +@@ -3119,6 +3258,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 -@@ -537,6 +537,10 @@ struct airoha_gdm_port { +@@ -538,6 +538,10 @@ struct airoha_gdm_port { struct net_device *dev; int id; 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 f569da7444..b3897784dd 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) { -@@ -1647,6 +1649,7 @@ static int airoha_dev_open(struct net_de +@@ -1663,6 +1665,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) { -@@ -1657,6 +1660,7 @@ static int airoha_dev_open(struct net_de +@@ -1673,6 +1676,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); -@@ -1722,10 +1726,12 @@ static int airoha_dev_stop(struct net_de +@@ -1738,10 +1742,12 @@ static int airoha_dev_stop(struct net_de } } @@ -57,7 +57,7 @@ Signed-off-by: Mikhail Kshevetskiy return 0; } -@@ -2858,6 +2864,7 @@ static const struct ethtool_ops airoha_e +@@ -2874,6 +2880,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) { -@@ -2871,6 +2878,7 @@ static void airoha_mac_config(struct phy +@@ -2887,6 +2894,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) { -@@ -2916,6 +2924,7 @@ bool airoha_is_valid_gdm_port(struct air +@@ -2932,6 +2940,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) -@@ -3008,6 +3017,7 @@ static int airoha_setup_phylink(struct n +@@ -3024,6 +3033,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) -@@ -3080,11 +3090,13 @@ static int airoha_alloc_gdm_port(struct +@@ -3096,11 +3106,13 @@ static int airoha_alloc_gdm_port(struct port->id = id; eth->ports[p] = port; @@ -103,7 +103,7 @@ Signed-off-by: Mikhail Kshevetskiy return airoha_metadata_dst_alloc(port); } -@@ -3213,10 +3225,12 @@ error_napi_stop: +@@ -3231,10 +3243,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); -@@ -3243,10 +3257,12 @@ static void airoha_remove(struct platfor +@@ -3261,10 +3275,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 -@@ -537,9 +537,11 @@ struct airoha_gdm_port { +@@ -538,9 +538,11 @@ struct airoha_gdm_port { struct net_device *dev; int id;