Skip to content

qualcommax: qca_edma: fix misc-IRQ storm and register-range overruns (shared-EDMA safety) - #150

Closed
JuliusBairaktaris wants to merge 15 commits into
Ansuel:qca-edma-reworkfrom
JuliusBairaktaris:qca-edma-shared-fixes
Closed

JuliusBairaktaris wants to merge 15 commits into
Ansuel:qca-edma-reworkfrom
JuliusBairaktaris:qca-edma-shared-fixes

Conversation

@JuliusBairaktaris

@JuliusBairaktaris JuliusBairaktaris commented Jun 10, 2026 •

Copy link
Copy Markdown

Hi @Ansuel — first off, thank you for the qca-edma rework. I have been building Qualcomm NSS offloading on top of this branch, together with Claude Code (keeping your upstream qca_edma/qca_ppe drivers instead of the vendor qca-nss-dp/qca-ssdk stack): openwrt-nss-edma + docs/wiki. ECM NAT/PPPoE offload, NSS SQM and ath11k Wi-Fi offload are running in production on a Xiaomi AX3600 on this driver base. Along the way I hit a few things in qca_edma that are relevant even without NSS, which this PR fixes, plus some findings and questions below.

The fixes (one commit, qca_edma.c only)

  1. Misc interrupt handling can storm. Probe leaves EDMA_REG_MISC_INT_MASK = 0x1ff with a handler that reads MISC_INT_STAT but never acks or masks anything. Any sticky misc condition (e.g. TX SRAM / RX descriptor FIFO flow-control trips) becomes an interrupt storm that wedges the SoC with no oops — I hit this deterministically (NSS firmware ring bring-up trips it), but a host-only error path could too. The legacy edma_cfg.c ran with mask 0. Fix: mask 0 at init + a self-disarming handler as a backstop.
  2. edma_irq_disable_all() overruns the TX interrupt register space on IPQ807x. The loop masks per-TX-ring interrupts up to txdesc_ring (23), but IPQ807x only has 8 per-TXCMPL-ring interrupt slots — indices 8..15 alias into RXFILL_PROD_IDX(0..7) and 16..23 into RXFILL_INT_MASK(0..7). Value-neutral at probe time today, but it writes unrelated registers. Fix: bound the loop by txcmpl_ring.
  3. edma_hw_stop() clears more global state than the host owns (sweeps all 24 rings and zeroes PORT_CTRL, the global EDMA enable). The legacy driver's teardown is host-rings-only. Fix: stop host rings only; the full sweep stays in edma_hw_init right after reset.

One more observation I did not fix (likely not introduced by your changes): on the AX3600, the final reboot of a sysupgrade can hang right after remoteproc0: stopped ... q6v5_wcss — dead until power cycle, new image then boots fine. Reproduced repeatedly; might be worth a look on plain qca-edma-rework.

Questions I would value your view on

  • Is the EDMA block meant to stay shareable with the NSS firmware? Your ring indices (txdesc 23, txcmpl 7, rxfill 7, rxdesc 15) match the legacy firmware-compatible partition exactly — deliberate, or inherited coincidence? (The edma_hw_stop() behavior was the only thing breaking that convention.)
  • VSI-less ports after bridge leave: probe assigns user ports the default VSI 0 in hardware, but port_vsi[] starts INVALID and port_bridge_leave clears the L3_VP entry entirely, leaving the port VSI-less — different from its probe state. Intentional? What should ingress behavior of a VSI-less port be? (In my tree I made "standalone port == VSI 0" an invariant.)
  • Possible duplicate broadcast flooding: tag_oob never sets skb->offload_fwd_mark, while ppe_vsi_member_set() puts all bridge member ports in the UUC/UMC/BC flood masks — so the PPE floods broadcasts to sibling ports in hardware and the host bridge re-floods the CPU copy. I have not yet measured this on a stock build (flagging it as a suspicion, not a confirmed bug).

ath11k: generic fixes buried in the NSS patch piles — opinions welcome

While porting the downstream NSS Wi-Fi patch sets onto backports 6.18.26, I audited all of them (with Claude Code) against the pristine backports source. A group of them are generic ath11k fixes, verified still missing upstream, that openwrt:main (or linux-wireless) could take independently of any NSS work (links point at the patches in qosmio's tree, where this lineage is maintained) — I would like your and the community's opinion on whether/where to submit these:

Happy to rebase/split this PR however you prefer, and to share any of the measurement methodology (everything above was established by live measurement on hardware, documented in the wiki).


Disclaimer: Claude Fable 5 (Anthropic's model, via Claude Code) helped in the generation of this PR — the analysis, fixes and text were produced with its assistance and reviewed/validated on hardware by me.

blogic and others added 15 commits June 7, 2026 23:03
Add kernel patch for the DSA out-of-band tagging protocol used by the
PPE switch driver, and enable CONFIG_NET_DSA_TAG_OOB.

Signed-off-by: John Crispin <john@phrozen.org>
Add pending patch that introduce a new HW CLK OP to trigger recalculation
of the rate.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
PCS driver for UNIPHY SerDes blocks on Qualcomm IPQ platforms.

Signed-off-by: John Crispin <john@phrozen.org>
[ rework Makefile for external repository, dependency ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
[ make it in-tree under qualcommax ]
Signed-off-by: Robert Marko <robimarko@gmail.com>
PPE switch driver for Qualcomm IPQ platforms, depends on EDMA and
UNIPHY PCS.

Signed-off-by: John Crispin <john@phrozen.org>
[ rework Makefile for external repository, dependency ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
[ bring PPE in-tree ]
Signed-off-by: Robert Marko <robimarko@gmail.com>
EDMA dataplane ethernet driver for Qualcomm IPQ platforms.

Signed-off-by: John Crispin <john@phrozen.org>
[ rework Makefile for external repository, dependency ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
[ rework for in-tree ]
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add IPQ5018 DWMAC driver. IP version of this Synopsys DWMAC is 3.7.

This Qualcomm IPQ5018 specific MAC implementation supports link speeds
of 10HD/FD, 100HD/FD, 1,000HD/FD, and 2500FD and SGMII and 2500BASEX
interface modes.

The driver supports the MAC be attached directly to a PHY or via an
optional PCS to a switch or PHY.

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Now that we are not using SSDK anymore, we must set the USXGMII MAC autoneg
bit manually, as otherwise MAC autonegotiation does not work.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Clocks are disabled by default for IPQ5018 GEPHY, but they are required
for the PHY to function properly. So let's enable the RX and TX clocks.

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Add DTSI files defining EDMA, PPE, and UNIPHY nodes for the new PPE
driver bindings on IPQ5018, IPQ6018 and IPQ8074 platforms.

IPQ5018 requires a patch for UNIPHY node as its cmn PLL node is upstream.

These replace the existing NSS-DP ones.

Signed-off-by: John Crispin <john@phrozen.org>
[IPQ5018]
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
[IPQ6018 and IPQ8074]
Signed-off-by: Robert Marko <robimarko@gmail.com>
Convert IPQ60xx and IPQ807x devices from the old NSS dataplane to the new
PPE stack.

IPQ50xx is not yet supported.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Import the interface renaming script from filogic so we can use DTS
label or openwrt,netdev-name to name interfaces from DTS on non DSA
ports.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Convert to UNIPHY PCS and DWMAC ethernet stack from qca-ssdk.

Since we are not using SSDK anymore, we dont need to patch in the UNIPHY
clock names anymore so drop the patch.

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Now that all targets using NSS-DP and SSDK have been converted, we can
finally drop these.

Signed-off-by: Robert Marko <robimarko@gmail.com>
… module"

This reverts commit 14beb34.

It turned out not to be required.

Signed-off-by: Robert Marko <robimarko@gmail.com>
The IPQ807x EDMA block is shared between the host and the NSS
firmware, with a ring partition convention (host: txdesc 23,
txcmpl 7, rxfill 7, rxdesc 15). Desk-diff against the legacy
qca-nss-dp edma_v1 hal shows the probe-time global register
programming is already value-identical, but three behaviors break
the firmware convention:

- edma_irq_disable_all() iterated TX_INT_MASK up to txdesc_ring
  (23); on IPQ807x the TX interrupt block only has 8 per-TXCMPL-ring
  slots and indices 8..23 alias into the RXFILL register block,
  zeroing RXFILL_PROD_IDX/INT_MASK of firmware-owned rings. Bound
  the loop by txcmpl_ring.

- MISC_INT_MASK was left at 0x1ff with a handler that never acks or
  masks the sticky status bits -> interrupt storm (hard wedge) when
  the firmware trips a shared SRAM/FIFO misc condition while
  bringing up its rings. The legacy driver runs with this mask at 0
  once any port is open (edma_enable_interrupts writes
  misc_intr_mask = 0x0) and its handler masks on any event. Keep
  the mask at 0 and make the handler self-disarm as a backstop.

- edma_hw_stop() swept ALL rings and wrote PORT_CTRL = 0, killing
  the firmware rings and the global EDMA enable the firmware
  depends on. Quiesce only host-owned rings at runtime; the
  full-range sweep stays in edma_hw_init() right after reset, the
  only point where the firmware cannot be running.
Copilot AI review requested due to automatic review settings June 10, 2026 18:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adjust EDMA interrupt/ring shutdown behavior for NSS-shared hardware, preventing accidental access to firmware-owned rings and reducing the risk of interrupt storms from misc error conditions.

Changes:

  • Limit TX interrupt mask iteration to TXCMPL ring range to avoid register aliasing.
  • Mask misc interrupts on first misc error and keep them masked by default during init.
  • Rework edma_hw_stop() to quiesce only host-owned rings and avoid disabling global EDMA enable relied on by NSS.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +145 to +146
dev_warn_ratelimited(&priv->pdev->dev,
"misc error 0x%x, masking misc interrupts\n", val);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ansuel your call. For me both is fine

@JuliusBairaktaris

Copy link
Copy Markdown
Author

If you'd rather squash this into the driver submission when it goes to mainline, that's totally fine — a Co-developed-by: Julius Bairaktaris <julius@bairaktaris.de> (or Reported-by:) would be appreciated so the fix stays attributed. Thanks!

@robimarko
robimarko force-pushed the qca-edma-rework branch 3 times, most recently from 1ef9819 to a9d5268 Compare July 11, 2026 13:42
@robimarko
robimarko force-pushed the qca-edma-rework branch 2 times, most recently from cf81f32 to 412526f Compare July 11, 2026 20:26
@JuliusBairaktaris

Copy link
Copy Markdown
Author

The qca-edma rework is merged into openwrt/main now, so this moves upstream to openwrt#24185. Closing here — thanks @Ansuel.

@JuliusBairaktaris
JuliusBairaktaris deleted the qca-edma-shared-fixes branch July 11, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants