From 4d37c515e7660eeb6afaa1fb8b75fc80271abb73 Mon Sep 17 00:00:00 2001 From: Julius Bairaktaris Date: Sat, 10 Oct 2026 22:17:50 +0200 Subject: [PATCH] qualcommax: qca_edma: add ethtool DMA reset The EDMA block has a reset line of its own, but the driver asserts it only at probe and when it rebuilds the rings. qca_edma is built in and the switch sits on the conduit, so a reboot is the only other way back to the engine's power-on state. Implement the ethtool reset op for ETH_RESET_DMA with the rebuild ring resizing already uses. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Julius Bairaktaris Link: https://github.com/openwrt/openwrt/pull/25700 Signed-off-by: Robert Marko --- .../drivers/net/ethernet/qualcomm/qca_edma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c index 9518ee4c5cd..b17ab7d1334 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_edma.c @@ -1422,6 +1422,23 @@ static int edma_set_ringparam(struct net_device *netdev, ring->tx_pending, ring->rx_pending); } +/* The rebuild asserts the block's reset line, so it is the DMA reset too. */ +static int edma_reset(struct net_device *netdev, u32 *flags) +{ + struct edma_priv *priv = netdev_priv(netdev); + int ret; + + if (!(*flags & ETH_RESET_DMA)) + return -EINVAL; + + ret = edma_reconfigure(priv, priv->rx_page_order, priv->num_queues, + priv->tx_ring_size, priv->rx_ring_size); + if (!ret) + *flags &= ~ETH_RESET_DMA; + + return ret; +} + /* A ring interrupts once it holds more frames than its threshold, and its * timer interrupts for fewer once they have waited that long. A threshold of * zero interrupts on every frame, which leaves the timer nothing to do. @@ -1725,6 +1742,7 @@ static const struct ethtool_ops edma_ethtool_ops = { .get_rxfh_indir_size = edma_get_rxfh_indir_size, .get_rxfh = edma_get_rxfh, .set_rxfh = edma_set_rxfh, + .reset = edma_reset, }; static void edma_rx_vlan_strip(struct edma_priv *priv,