aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/airoha
AgeCommit message (Collapse)AuthorFilesLines
2026-10-05net: airoha: Add retry mechanism to airoha_qdma_set_trtcm_param()Leto Liu (刘涛)2-6/+28
CPU accesses QDMA via the bus. When multiple modules are using the bus simultaneously, CPU access to QDMA may encounter bus timeouts and fails, resulting in QDMA configuration failures and potentially causing packet transmission issues. In order to mitigate the issue, introduce a retry mechanism to airoha_qdma_set_trtcm_param routine in order to ensure the configuration is correctly applied to the hardware. It's enough to try a second time for the TRTCM config to be actually applied to make sure we are not in the middle of bucket handling as it does operate on fixed time slot internally. Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") Signed-off-by: Leto Liu (刘涛) <Leto.Liu@airoha.com> [ improve commit description, drop memory block, apply better loop logic] Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> Link: https://patch.msgid.link/20260930065855.46171-1-ansuelsmth@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-09-23net: airoha: npu: cancel wdt_work after releasing the WDT IRQMyeonghun Pak1-12/+6
airoha_npu_remove() calls cancel_work_sync() on each core's wdt_work, but the watchdog IRQ that queues it is requested with devm_request_irq() and is freed only after .remove() returns. airoha_npu_wdt_handler() can therefore schedule_work() again once the cancel has returned. struct airoha_npu, which contains the work, is devm_kzalloc()'d and is freed in that same unwind, so the late work dereferences freed memory. Register the work with devm_work_autocancel() before devm_request_irq() and drop .remove(). Devres runs in reverse order, so the IRQ is freed before cancel_work_sync(), including when probe fails. A cancel left in .remove() cannot get that order. Initializing the work first also stops a pending watchdog interrupt from queuing an uninitialized work item. Probe currently calls INIT_WORK() only after devm_request_irq(). This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: 23290c7bc190 ("net: airoha: Introduce Airoha NPU support") Cc: stable@vger.kernel.org # 6.15+ Co-developed-by: Ijae Kim <ae878000@gmail.com> Signed-off-by: Ijae Kim <ae878000@gmail.com> Signed-off-by: Myeonghun Pak <mhun512@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com> Link: https://patch.msgid.link/20260922000914.542068-1-mhun512@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-09-03net: airoha: enable RX_DONE interrupt for RX queue 31Lorenzo Bianconi1-1/+1
RX queue 31 has always been allocated and filled by airoha_qdma_init_rx() since RX_DONE_INT_MASK spans queues 0-31, but none of the RX_IRQ* _BANK_PIN_MASK values covered BIT(31). As a consequence the RX_DONE interrupt for queue 31 was never enabled, airoha_qdma_rx_process() never ran on that queue and its buffers were never reaped. Route RX queue 31's RX_DONE interrupt to IRQ bank 1 so that the queue is drained and its buffers returned to the page pool. Fixes: f252493e1835 ("net: airoha: Enable multiple IRQ lines support in airoha_eth driver.") Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260830-airoha-rxdone-rxq31-v1-1-830a91503f2f@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-08-27net: airoha: npu: fix missing streaming DMA maskDaniel Pawlik1-1/+1
The driver calls dma_set_coherent_mask() but never dma_set_mask(), leaving the streaming DMA mask at the bus default. On the non-coherent EN7581 platform (Cortex-A53), this causes the NPU mailbox to hang after approximately 41 calls when using streaming DMA mappings. Replace dma_set_coherent_mask() with dma_set_mask_and_coherent() to set both the streaming and coherent DMA masks, matching standard driver practice. Fixes: 6f884eb87a79 ("net: airoha: Fix DMA direction for NPU mailbox buffer") Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260814110017.2795022-1-pawlik.dan@gmail.com/ Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260809152813.585797-1-pawlik.dan@gmail.com/ Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260805070851.2885888-1-pawlik.dan@gmail.com/ Signed-off-by: Daniel Pawlik <pawlik.dan@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260820085941.380401-1-pawlik.dan@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-17net: airoha: npu: load the firmware without the sysfs fallbackVitaliy Sochnev1-4/+6
airoha_npu_load_firmware() maps a missing firmware file to -EPROBE_DEFER so that the NPU can be brought up once the rootfs carrying /lib/firmware has been mounted. That mapping holds only as long as request_firmware() reports -ENOENT. It does not when the sysfs fallback is in play. With CONFIG_FW_LOADER_USER_HELPER_FALLBACK set, or with the fallback armed at runtime through /proc/sys/kernel/firmware_config/force_sysfs_fallback, request_firmware() hands the request to a userspace helper, waits out the full loading_timeout and returns -ETIMEDOUT. The -ENOENT test no longer matches, dev_err_probe() turns the result into a hard failure, and the NPU is left unbound after stalling the boot for 60 seconds: airoha-npu 1e900000.npu: Direct firmware load for airoha/en7581_npu_rv32.bin failed with error -2 airoha-npu 1e900000.npu: Falling back to sysfs fallback for: airoha/en7581_npu_rv32.bin airoha-npu 1e900000.npu: error -ETIMEDOUT: failed to run npu firmware airoha-npu 1e900000.npu: probe with driver airoha-npu failed with error -110 Clearing FW_LOADER_USER_HELPER in the configuration is not a dependable guard against this, because unrelated drivers select it. On the affected build the symbol was turned back on by LEDS_LP55XX_COMMON, even though the platform had explicitly disabled it. Use request_firmware_direct() instead. It sets FW_OPT_NOFALLBACK_SYSFS, so a missing file is reported as -ENOENT whatever the firmware loader is configured to do, and the deferred probe path works as intended. Two consequences are worth stating plainly. The helper is not merely bypassed for the boot-before-rootfs case. fw_run_sysfs_fallback() returns early on FW_OPT_NOFALLBACK_SYSFS, so this driver's firmware requests can no longer be served by a usermode helper at all, including on a system where that is the only delivery route; having no second firmware source, the driver would defer forever there. That is a deliberate trade-off: the -ENOENT to -EPROBE_DEFER mapping was written to wait for a filesystem, and the sysfs helper interface has had no in-tree consumer since udev dropped firmware loading. request_firmware_direct() also sets FW_OPT_NO_WARN, which drops the only message naming the file that failed to load. Report it from the driver instead, so the name lands in the deferred probe reason and shows up in the "deferred probe pending" line emitted at driver_deferred_probe_timeout. The generic report in airoha_npu_probe() goes away with it, since it would otherwise overwrite that reason with a message naming nothing; of the paths it covered, devm_ioremap_resource() reports itself and the malformed firmware-name property now does too. Measured on a Nokia XG-040G-MD with FW_LOADER_USER_HELPER=y and FW_LOADER_USER_HELPER_FALLBACK=y forced on, two images from the same tree differing only by this patch: without: fallback at 2.477s -> -ETIMEDOUT at 64.555s -> probe failed with -110, preinit at 69.6s, NPU unbound with: no fallback, NPU fw version 1456.62 at 3.665s, preinit at 7.6s Cc: stable+noautosel@kernel.org # never worked Signed-off-by: Vitaliy Sochnev <sochnev.v.74@gmail.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-10net: pass net_device_path_ctx to dev_fill_forward_path()Lorenzo Bianconi1-1/+6
Refactor dev_fill_forward_path() to take a struct net_device_path_ctx pointer instead of a (dev, daddr) pair, so the caller can build and populate the context up front and keep it after the forward path walk. This allows additional fields (e.g. vlan and ether_type) to be carried in the context and shared with ndo_fill_forward_path implementations, instead of being reconstructed on the stack inside the core helper. Update the mtk_ppe_offload, airoha_ppe and nf_flow_table_path callers to allocate and fill the context before invoking dev_fill_forward_path(). The network topology resolution behaviour is unchanged. This is a preliminary patch to enable HW flowtable offload for IPv4 over IPv6 tunnels. Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2026-08-05Merge tag 'nf-next-26-07-31' of ↵Jakub Kicinski1-3/+7
git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next: 1) Update conncount to use the original tuple after ct lookup to ensure consistent counting, from Fernando F. Mancera. 2) Remove redundant net_device field in info structure that helps parse the flowtable path discovery. 3) Move net_device to flowtable check to the flowtable discovery path parser. This is preparation work to pass the tunnel dst_entry via .fill_forward_path. 4) Update DSA .fill_forward_path to break at the user DSA, since the conduit DSA is not used in the datapath. This slighly simplifies the flowtable path discovery parser. 5) Do not advance index in the path stack prematurely, otherwise it points to uninitialized slots on error. Not an issue currently but it could be once tunnel dst_entry is passed via .fill_forward_path. 6) Pass the tunnel dst_entry via dev_fill_forward_path(). 7) Update ipip and ip6ip6 tunnels to pass the dst_entry through dev_fill_forward_path(). 8) Call skb_valid_dst() before accessing skb_dst() to ensure dst_entry is not a template. 9) Use UNACK timeout when RST packet does not match the expected window while in ESTABLISHED state, the existing approach the CLOSE state timeout which is only 10 seconds. Adopt a more conservative timeout by default for this case. * tag 'nf-next-26-07-31' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next: netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets netfilter: nf_tables: call skb_valid_dst() before skb_dst() netfilter: flowtable: release tunnel route on error when building forward path net: pass dst via net_device_path in dev_fill_forward_path() net: do not advance stack index from dev_fwd_path() net: dsa: stop at the user device in .fill_forward_path netfilter: flowtable: consolidate flowtable device check netfilter: flowtable: consolidate net_device field in nft_forward_info struct netfilter: conncount: normalize tuple and zone on successful ct lookup ==================== Link: https://patch.msgid.link/20260731153402.851224-1-pablo@netfilter.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-08-04net: airoha: fix ARRAY_SIZE() division by zero on UP buildsLorenzo Bianconi1-1/+1
airoha_alloc_gdm_device() initializes the txq_lock[] array iterating over ARRAY_SIZE(dev->txq_lock). ARRAY_SIZE() expands to sizeof(dev->txq_lock) / sizeof((dev->txq_lock)[0]), but on UP builds (CONFIG_SMP unset, CONFIG_DEBUG_SPINLOCK unset) arch_spinlock_t is an empty struct, so sizeof(spinlock_t) is zero and the expression is a compile-time division by zero (undefined behavior), reported by clang as "division by zero is undefined [-Wdivision-by-zero]". Since the array is statically sized with AIROHA_NUM_NETDEV_TX_RINGS, use the named constant as loop bound instead of ARRAY_SIZE(). Fixes: 78a35725e533 ("net: airoha: defer GDM3/GDM4 WAN mode and GDM2 loopback to QoS offload") Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202607311850.6p0ZUVq4-lkp@intel.com/ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> Link: https://patch.msgid.link/20260731-airoha-spinlock-array-fix-v1-1-863a7e239a5f@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-07-31net: pass dst via net_device_path in dev_fill_forward_path()Pablo Neira Ayuso1-3/+7
Add dst_entry to tunnel device path, this will allow us to remove a duplicated route lookup. This is a preparation patch to retrieve the tunnel route directly from the .fill_forward_path. This new dst_entry in the tunnel will be used by a follow up patch. Since dst_release() works fine on NULL interface, this is still noop until the flowtable starts using this. Add a new dev_fill_forward_path_release() function to drop the refcount on the tunnel device route and use it in case of error out. Export it so to drop the refcount on the tunnel route at a later stage. Adjust existing drivers that recycle dev_fill_forward_path() to call dev_fill_forward_path_release() for safety reasons. Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2026-07-30net: airoha: defer GDM3/GDM4 WAN mode and GDM2 loopback to QoS offloadLorenzo Bianconi4-30/+243
GDM3 and GDM4 ports require GDM2 loopback to be enabled for hardware QoS offload to function. Without it, HTB and ETS offload on these ports do not work. Previously, GDM3/GDM4 ports were automatically configured as WAN with GDM2 loopback enabled during ndo_init(). Add the capability to configure GDM3/GDM4 as WAN/LAN on demand when QoS offload is created or destroyed. Hook airoha_enable_qos_for_gdm34() into TC_HTB_CREATE so that requesting HTB offload on a GDM3/GDM4 LAN port switches it to WAN mode and enables GDM2 loopback. Introduce the AIROHA_DEV_F_TX_QOS flag to track whether a device has an active TX HTB qdisc; set it in airoha_tc_setup_qdisc_htb() on successful TC_HTB_CREATE and clear it on TC_HTB_DESTROY. The device keeps its WAN role after qdisc teardown so that its configuration is preserved until another device explicitly needs the WAN role for QoS offload. If another GDM3/GDM4 device already holds the WAN role without an active TX qdisc, demote it to LAN before promoting the requesting device. Skip the demotion when the requesting device is itself already the WAN device. Since airoha_dev_set_qdma() can now be called on a running device to migrate between QDMA blocks, make dev->qdma an RCU pointer so the TX path can safely dereference it without holding RTNL. When migrating between QDMA blocks, stop TX queues, swap the pointer via rcu_assign_pointer(), then synchronize_rcu() to ensure no in-flight ndo_start_xmit holds the old pointer. Serialize netdev_tx_completed_queue() calls via per-TX-queue spinlocks txq_lock[] so that both the old and new QDMA NAPI instances can complete packets concurrently on the same netdev TX queues without racing on dql_completed(). Hold flow_offload_mutex in airoha_enable_qos_for_gdm34() and airoha_disable_qos_for_gdm34() around the dev->flags update, airoha_dev_set_qdma() and GDM2 loopback configuration, serializing against concurrent airoha_ppe_hw_init() in the TC_SETUP_CLSFLOWER offload path. Introduce airoha_qdma_deref() helper that wraps rcu_dereference_protected() with a lockdep condition accepting either rtnl_lock or flow_offload_mutex, and use it across all control-path dereferences of the RCU-protected dev->qdma pointer. Add airoha_disable_gdm2_loopback() to disable GDM2 hw loopback. Tested-by: Madhur Agarwal <madhur.agrawal@airoha.com> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260725-airoha-ethtool-priv_flags-v12-3-5136a30b2157@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-30net: airoha: fix ETS QoS stats counter underflow and cross-channel corruptionLorenzo Bianconi2-10/+15
airoha_qdma_get_tx_ets_stats() has two bugs: - The hardware counters read via airoha_qdma_rr() are 32-bit values but are stored in u64 locals and subtracted from u64 baselines. When a 32-bit hardware counter wraps around, the subtraction produces a large underflow value passed to _bstats_update(). - The baseline counters (cpu_tx_packets, fwd_tx_packets) are stored as single per-device fields, but airoha_qdma_get_tx_ets_stats() is called with different channel values (0-3). Each call reads a different channel's hardware counter but overwrites the same baseline, corrupting the delta computation for other channels. Fix both by: - Narrowing the counter locals and baselines to u32 so that 32-bit unsigned subtraction handles wrap-around naturally. - Grouping the baselines into a per-channel qos_stats array so each channel tracks its own previous counter value independently. - Splitting the delta addition into two statements so the first u32 delta is widened to u64 on assignment and the second is added in u64 arithmetic, preventing overflow when both deltas are large. Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260725-airoha-ethtool-priv_flags-v12-2-5136a30b2157@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-30net: airoha: rename airoha_priv_flags to airoha_dev_flagsLorenzo Bianconi2-5/+5
Rename the airoha_priv_flags enum to airoha_dev_flags and the AIROHA_PRIV_F_WAN flag to AIROHA_DEV_F_WAN. The "priv_flags" naming dates back to an earlier design that used ethtool private flags; since this series switched to tc qdisc offload for LAN/WAN configuration, align the naming to reflect that these are per-device flags rather than ethtool private flags. While at it, switch to test_bit()/set_bit()/clear_bit() APIs and convert the flags field from u32 to unsigned long to make flags manipulation atomic. Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260725-airoha-ethtool-priv_flags-v12-1-5136a30b2157@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-23Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netJakub Kicinski4-70/+136
Cross-merge networking fixes after downstream PR (net-7.2-rc5). Conflicts: drivers/net/amt.c 3656a79f94c47 ("amt: re-read skb header pointers after every pull") 586c4dcf28eb6 ("amt: no longer rely on RTNL in amt_fill_info()") https://lore.kernel.org/amIaJr3aOQNS_Fvl@sirena.org.uk Adjacent changes: drivers/net/geneve.c 8efb8f8bbb35 ("geneve: require CAP_NET_ADMIN in the device netns for changelink") 0ba269933f73 ("geneve: convert config to RCU-protected pointer") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-07-23net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()Lorenzo Bianconi1-2/+1
Derive the hardware QoS channel from opt->parent instead of opt->handle in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either user-specified or auto-allocated by qdisc_alloc_handle() and bears no relation to the HTB leaf classid that identifies the hardware channel. HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always attached as a child of an HTB leaf, so its opt->parent matches that classid. Using opt->handle instead can cause two ETS qdiscs on different HTB leaves to collide on the same hardware channel, corrupting scheduler configuration and stats. Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260720-airoha-ets-handle-fix-v2-1-6f7129ddc06f@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-07-21net: airoha: Fix DMA direction for NPU mailbox bufferWayen Yan1-2/+2
airoha_npu_send_msg() always maps the mailbox buffer with DMA_TO_DEVICE, but some callers expect the NPU to write response data back into the same buffer: - airoha_npu_wlan_msg_get() (NPU_OP_GET): NPU writes response into the buffer, then the caller reads it via memcpy() - airoha_npu_ppe_stats_setup() (NPU_OP_SET): NPU writes back npu_stats_addr field in the response On non-cache-coherent architectures like EN7581 (Cortex-A53 without hardware cache coherency for NPU DMA), DMA_TO_DEVICE unmap is a no-op — it does not invalidate the CPU cache. If the NPU-written cache line is still present in the CPU cache when the caller reads the buffer, the CPU observes stale data instead of the NPU response. This is a timing-sensitive bug: small mailbox buffers (~24 bytes) typically fit in a single cache line and may survive in the cache until the caller reads them, producing silent data corruption rather than a crash. The bug is more likely to trigger when the caller reads the response immediately after dma_unmap_single() without intervening cache-evicting operations. Fix by using DMA_BIDIRECTIONAL for both map and unmap, which ensures dma_unmap_single() invalidates the CPU cache on non-coherent systems. The mailbox buffers are small so there is no performance concern. Fixes: c52918744ee1e49cea86622a2633b9782446428f ("net: airoha: npu: Move memory allocation in airoha_npu_send_msg() caller") Signed-off-by: Wayen Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/178351055214.98729.11403147818632027428@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-21net: airoha: Fix potential use-after-free in airoha_ppe_deinit()Wayen Yan1-0/+1
airoha_ppe_deinit() replaces the NPU pointer with NULL via rcu_replace_pointer() but does not wait for existing RCU readers to exit before calling ppe_deinit() and airoha_npu_put(). This can cause a use-after-free if a reader in an RCU read-side critical section still holds a reference to the NPU when it is freed. The init path (airoha_ppe_init) already calls synchronize_rcu() after rcu_assign_pointer(), but the deinit path introduced in commit 6abcf751bc08 ("net: airoha: Fix schedule while atomic in airoha_ppe_deinit()") omitted the matching barrier when switching from rcu_read_lock()/rcu_dereference() to rcu_replace_pointer(). Add synchronize_rcu() before ppe_deinit() to ensure all existing RCU readers have completed before the NPU resources are released. Fixes: 6abcf751bc084804a9e5b3051442e8a2ce67f48a ("net: airoha: Fix schedule while atomic in airoha_ppe_deinit()") Signed-off-by: Wayen Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/178351022574.97989.6880403520276841703@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-21net: airoha: fix MIB stats collection to be losslessAniket Negi2-66/+132
REG_FE_GDM_MIB_CLEAR after every read creates a race window where packets arriving between read and clear are lost from statistics. Switch to a delta-based approach instead: - 64-bit H+L registers (ok pkts/bytes, E64..L1023): read absolute hardware total directly into a local variable; clamp with max(new, old) to prevent torn-read regression when the counter carries between the two reads. - 32-bit registers (drops, bc, mc, errors, runt, long): accumulate (u32)(curr - prev) into a 64-bit software counter; unsigned subtraction handles wrap-around transparently. - tx/rx_len[0] ([0,64] bucket): combines RUNT_CNT (32-bit, delta via tx_runt/rx_runt) and E64_CNT (64-bit, absolute) into a single local accumulator; max(new, old) applied here too to guard against a torn read of E64 when the RUNT accumulator is unchanged between polls. MIB counters are zeroed by the SCU FE reset (EN7581_FE_RST) asserted in airoha_hw_init() at module load, so no explicit MIB clear is needed in airoha_fe_init(). Merge airoha_dev_get_hw_stats() into airoha_update_hw_stats() and move stats_lock inside. Plain spin_lock() is correct: the function is only called from ndo_get_stats64() in process context. Each dev refreshes only its own MIB counters; sibling devs on a shared GDM3/4 port are polled when their own netdev is queried. Fixes: 8f4695fb67b2 ("net: airoha: better handle MIBs for GDM ports with multiple devs attached") Signed-off-by: Aniket Negi <aniket.negi03@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260707152639.105628-1-aniket.negi03@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-07-17net: airoha: add preliminary support to configure tx hw QoS queue during ↵Lorenzo Bianconi1-4/+6
flowtable offloading Add the plumbing to program the AIROHA_FOE_QID field in the PPE FOE entry with a per-flow priority value during flowtable offload. This allows the hardware to steer offloaded flows to a specific QoS queue on the egress QDMA block for traffic forwarded between two interfaces via hardware acceleration, bypassing the kernel forwarding path. The priority parameter is currently always zero because netfilter does not yet provide a mechanism to pass the skb priority field to the flowtable offload driver. Once that support is added in the netfilter subsystem, the driver will be able to extract the priority from the flow rule and map it to the appropriate hardware queue. Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260703-airoha-hw-qos-queue-stub-v1-1-ef253ffdd093@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-30net: airoha: fix max receive size configurationLorenzo Bianconi4-60/+58
Set the GDM maximum receive size to AIROHA_MAX_RX_SIZE unconditionally during hardware initialization instead of updating it according to the configured MTU. This avoids dropping incoming frames that exceed the current MTU but could still be processed by the networking stack, which is able to fragment the reply on the TX side (e.g. ICMP echo requests). Move the per-port MTU configuration to the PPE egress path where it belongs, and set the tx frame size running airoha_ppe_set_xmit_frame_size() to dynamically track the maximum MTU across running interfaces sharing the same PPE instance. Fix the PPE MTU register addressing to pack two port entries per register word and add WAN_MTU0 configuration for non-LAN GDM devices. Fixes: 54d989d58d2a ("net: airoha: Move min/max packet len configuration in airoha_dev_open()") Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260625-airoha-fix-rx-max-len-v1-1-45b9b827358d@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2026-06-27net: airoha: dma map xmit frags with skb_frag_dma_map()Lorenzo Bianconi2-23/+45
Map xmit skb fragments using skb_frag_dma_map() instead of dma_map_single(skb_frag_address()). skb_frag_address() relies on page_address() to obtain a kernel virtual address, which is not guaranteed to work for all page types (e.g. highmem pages or user-pinned pages from MSG_ZEROCOPY). skb_frag_dma_map() maps the fragment directly via its struct page and offset through dma_map_page(), avoiding the need for a kernel virtual address entirely. Introduce an enum airoha_dma_map_type to track how each queue entry was mapped (single vs page), so that the matching unmap function is called on completion and in error paths. Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com> Link: https://patch.msgid.link/20260625-airoha-eth-skb_frag_dma_map-v1-1-31d9e460aae6@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-24net: airoha: fix BQL underflow in shared QDMA TX ringLorenzo Bianconi2-76/+93
When multiple netdevs share a QDMA TX ring and one device is stopped, netdev_tx_reset_subqueue() zeroes that device's BQL counters while its pending skbs remain in the shared HW TX ring. When NAPI later completes those skbs via netdev_tx_completed_queue(), the already-zeroed dql->num_queued counter underflows. Fix the issue: - Remove netdev_tx_reset_subqueue() from airoha_dev_stop() so pending skbs are completed naturally by NAPI with proper BQL accounting. - Rework airoha_qdma_tx_cleanup() to disable TX DMA, flush BQL counters, DMA-unmap and free all pending skbs while skb->dev references are still valid. Use a per-queue flushing flag checked under q->lock in airoha_dev_xmit() to prevent races between teardown and transmit. Call airoha_qdma_stop_napi() before airoha_qdma_tx_cleanup() at the call sites. - Move DMA engine start into probe. Split DMA teardown so TX DMA is disabled in airoha_qdma_tx_cleanup() and RX DMA in airoha_qdma_cleanup(). - Remove qdma->users counter since DMA lifetime is now tied to probe/cleanup rather than per-netdev open/stop. Fixes: a9c2ca61fec7 ("net: airoha: Support multiple net_devices for a single FE GDM port") Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260620-airoha-bql-fixes-v3-1-76b95374e63e@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-24net: airoha: fix netif_set_real_num_tx_queues for sparse QoS channelsLorenzo Bianconi1-9/+16
airoha_tc_htb_alloc_leaf_queue() assigns queue IDs based on the channel index (opt->qid = AIROHA_NUM_TX_RING + channel), but updates real_num_tx_queues with a simple increment (num_tx_queues + 1). When QoS channels are allocated sparsely (e.g., channels 0 and 3 without 1 and 2), the returned qid can exceed real_num_tx_queues, causing out-of-bounds accesses in the networking stack. For example, allocating channel 0 then channel 3 results in real_num_tx_queues = 34 but qid = 35, which is out of range [0, 34). Fix this by computing real_num_tx_queues based on the highest active channel index rather than using a simple counter, in both the allocation and deletion paths. Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-2-5c43485038f9@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-24net: airoha: Fix off-by-one in airoha_tc_remove_htb_queue()Lorenzo Bianconi1-1/+1
airoha_tc_htb_alloc_leaf_queue() computes the HTB QoS channel index as opt->classid % AIROHA_NUM_QOS_CHANNELS and stores it in qos_sq_bmap. However, airoha_tc_remove_htb_queue() clears the HTB configuration using queue + 1 as the channel index, causing an off-by-one error. Use queue directly as the QoS channel index to match the allocation logic. Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-1-5c43485038f9@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-22net: airoha: Fix TX scheduler queue mask loop upper boundWayen Yan1-1/+1
In airoha_qdma_set_chan_tx_sched(), the loop clearing queue mask was using AIROHA_NUM_TX_RING (32) instead of AIROHA_NUM_QOS_QUEUES (8). Each channel has 8 queues, and TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i) computes BIT(i + (channel * 8)). With i ranging 0..31, this causes: - channel 0: clears bit 0..31 (all 4 channels) instead of 0..7 - channel 1: clears bit 8..31 (channels 1-3) instead of 8..15 - channel 2: clears bit 16..31 (channels 2-3) instead of 16..23 - channel 3: clears bit 24..31 (channel 3 only) - correct by accident While BIT(32+) on arm64 produces 64-bit values truncated to 0 in u32 mask parameter, the loop still incorrectly clears queues within the same channel beyond queue 7. Even though this is functionally harmless (the register resets to 0 and is only ever cleared, never set — so clearing extra bits is a no-op), the loop bound is semantically wrong and should be fixed for correctness and clarity. Fix by using AIROHA_NUM_QOS_QUEUES (8) as the loop upper bound. Fixes: ef1ca9271313 ("net: airoha: Add sched HTB offload support") Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Wayen Yan <win847@gmail.com> Link: https://patch.msgid.link/178187479434.2400840.1312143943526335838@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-21net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()Wayen Yan1-1/+1
In airoha_dev_select_queue(), the expression: queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; implicitly converts to unsigned arithmetic: when skb->priority is 0 (the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX, and UINT_MAX % 8 = 7, routing default best-effort packets to the highest-priority QoS queue. This causes QoS inversion where the majority of traffic on a PON gateway starves actual high-priority flows (VoIP, gaming, etc.). The "- 1" offset was a leftover from the ETS offload implementation that has since been removed. The correct mapping is a direct modulo: queue = skb->priority % AIROHA_NUM_QOS_QUEUES; This maps priority 0 → queue 0 (lowest), priority 7 → queue 7 (highest), with higher priorities wrapping around. This is the standard Linux sk_prio → HW queue mapping used by other drivers. Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback") Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/ Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Joe Damato <joe@dama.to> Signed-off-by: Wayen Yan <win847@gmail.com> Link: https://patch.msgid.link/178194366700.2485734.5368768965976693502@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-18net: airoha: fix foe_check_time allocation sizeWayen Yan1-1/+2
foe_check_time is declared as u16 pointer but was allocated with only ppe_num_entries bytes instead of ppe_num_entries * sizeof(u16). When airoha_ppe_foe_verify_entry() is called with hash >= ppe_num_entries/2, it writes beyond the allocated buffer, causing heap buffer overflow and potential kernel crash. Fixes: 6d5b601d52a2 ("net: airoha: ppe: Dynamically allocate foe_check_time array in airoha_ppe struct") Signed-off-by: Wayen Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/178161119471.2163752.14373384830691569758@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-16Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netJakub Kicinski3-7/+5
Merge in late fixes in preparation for the net-next PR. Conflicts: net/tls/tls_sw.c 406e8a651a7b ("net: skmsg: preserve sg.copy across SG transforms") 79511603a65b ("tls: remove dead sockmap (psock) handling from the SW path") drivers/net/ethernet/microsoft/mana/mana_en.c f8fd56977eeea ("net: mana: guard TX wq object destroy with INVALID_MANA_HANDLE check") d07efe5a6e641 ("net: mana: Use per-queue allocation for tx_qp to reduce allocation size") https://lore.kernel.org/ajAPXu-C_PuTgV-a@sirena.org.uk No adjacent changes. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15net: airoha: use int instead of atomic_t for qdma users counterLorenzo Bianconi2-3/+3
QDMA users counter is always accessed holding RTNL lock so we do not require atomic_t for it. Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15net: airoha: Fix MODULE_LICENSE to match SPDX GPL-2.0-only identifierWayen.Yan2-2/+2
Both airoha_eth.c and airoha_npu.c declare SPDX-License-Identifier: GPL-2.0-only but use MODULE_LICENSE("GPL"), which the kernel module loader interprets as GPL-2.0+ (any GPL version). This mismatch causes license compliance tools (FOSSology, ScanCode, etc.) to misidentify the effective license as more permissive than intended. Replace MODULE_LICENSE("GPL") with MODULE_LICENSE("GPL v2") to align with the GPL-2.0-only SPDX identifier. Per include/linux/module.h, "GPL v2" maps to GPL-2.0-only, matching the source files' declared license. Signed-off-by: Wayen <win847@gmail.com> Link: https://patch.msgid.link/6a2ded59.63d39acb.391892.7632@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15net: airoha: Fix typos in comments and KconfigWayen.Yan2-6/+6
Fix several typos found during code review: - Kconfig: "Aiorha" -> "Airoha" in NET_AIROHA_FLOW_STATS help text - Comment: "CMD1" -> "CDM1" (Central DMA, not Command) - Comments: "GMD1/2/3/4" -> "GDM1/2/3/4" (Gigabit DMA, not GMD) These are pure comment and documentation fixes with no functional impact. Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2ca74a.c5b1db4e.21a698.01e7@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15net: airoha: Fix always-true condition in PPE1 queue reservation loopWayen.Yan1-1/+1
In airoha_fe_pse_ports_init(), the inner condition for PPE1 queue reservation is identical to the for-loop bound, making it always true and the else branch dead code: for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) { if (q < pse_port_num_queues[FE_PSE_PORT_PPE1]) /* always true */ set RSV_PAGES; else set 0; /* unreachable */ } The intended behavior is to reserve pages only for the first half of the queues, matching the PPE2 implementation on line 334 which correctly uses the /2 divisor. Fix the PPE1 condition accordingly. Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2ca3de.ad59c0a6.147df9.2ac1@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-15net: airoha: Fix non-standard return value in airoha_ppe_get_wdma_info()Wayen.Yan1-1/+1
airoha_ppe_get_wdma_info() returns -1 when the last path in the forwarding path stack is not of type DEV_PATH_MTK_WDMA. This is not a standard kernel error code. Replace it with -EINVAL since the input path type is invalid from the caller's perspective. Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2ca3d9.ad59c0a6.147df9.2a62@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-13net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE entriesWayen.Yan1-2/+0
In airoha_ppe_debugfs_foe_show(), the second switch statement falls through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE, accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE (3-tuple) entries do not contain a valid new_tuple — this field is only meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the memory at the new_tuple offset holds routing information, not NAT data, so displaying "new=" produces garbage output. Display new_tuple only for HNAPT and DSLITE, and let IPV4_ROUTE fall through to the default case. Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support") Link: https://lore.kernel.org/6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2be54b.ef98c1b2.3c3224.2ed8@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-13net: airoha: Fix register index for Tx-fwd counter configurationWayen.Yan1-1/+1
In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration register uses the same index (i << 1) as the Tx-cpu counter, which overwrites the Tx-cpu configuration. The Tx-fwd counter value register correctly uses (i << 1) + 1, so the configuration register should use the same index. Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that the Tx-fwd counter is properly configured instead of clobbering the Tx-cpu counter config. Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2b40e7.4dd82583.3a5c46.e566@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-13net: airoha: better handle MIBs for GDM ports with multiple devs attachedLorenzo Bianconi2-86/+112
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. Co-developed-by: Christian Marangi <ansuelsmth@gmail.com> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-13net: airoha: Fix error handling in airoha_ppe_flush_sram_entries()Wayen.Yan1-3/+3
In airoha_ppe_flush_sram_entries(), the outer "err" variable was never updated when the inner loop variable shadowed it, causing the function to always return 0 even when airoha_ppe_foe_commit_sram_entry() fails. Drop the outer "err" variable and return directly on error, propagating the error code from airoha_ppe_foe_commit_sram_entry() correctly. Fixes: 620d7b91aadb ("net: airoha: ppe: Flush PPE SRAM table during PPE setup") Link: https://lore.kernel.org/netdev/6a2b40e4.4dd82583.3a5c46.e52f@mx.google.com/ Signed-off-by: Wayen.Yan <win847@gmail.com> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/6a2bd37a.4034e349.1b41bb.1caf@mx.google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11net: airoha: simplify WAN device check in airoha_dev_init()Lorenzo Bianconi1-10/+2
airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's netdev is always registered before GDM3/GDM4. This means the explicit check for eth->ports[1] && eth->ports[1]->devs[0] is a redundant special-case of what airoha_get_wan_gdm_dev() already covers, since GDM2 is always marked as WAN during its own ndo_init. 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 <lorenzo@kernel.org> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Link: https://patch.msgid.link/20260610-airoha-eth-simplify-dev-init-v2-1-8f244e69b0d4@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11net: airoha: move get_sport() callback at the beginning of ↵Lorenzo Bianconi1-4/+4
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 <lorenzo@kernel.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260608-airoha_enable_gdm2_loopback-minor-change-v1-1-1787a0f42b31@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-06-11Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netJakub Kicinski1-0/+3
Cross-merge networking fixes after downstream PR (net-7.1-rc8). Conflicts: drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c f67aead16e85 ("net: txgbe: rework service event handling") 57d39faed4c9 ("net: txgbe: improve functions of AML 40G devices") net/rds/info.c 512db8267b73 ("rds: mark snapshot pages dirty in rds_info_getsockopt()") 6e94eeb2a2a6 ("rds: convert to getsockopt_iter") Adjacent changes: include/net/sock.h 1ee9