realtek: eth: merge & simplify irq handlers

Two different irq handlers exist for RTL83xx and RTL93xx. Basically
they do always the same.

- Check transmit interrupts (not needed anymore)
- Check rx overflow interrupts (not needed anymore)
- Determine rx interrupts and queues that must be processed.
- In case of RTL839x check for L2 interrupts

With all the recent refactoring their logic is more or less the
same. Merge them into one handler. For better readability add a
helper that determines the work (aka rings) that needs to be
processed.

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/22023
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Markus Stockhausen
2026-02-14 19:40:31 +01:00
committed by Hauke Mehrtens
parent 8e33c40c7f
commit b74e261d56
2 changed files with 24 additions and 74 deletions

View File

@@ -196,6 +196,24 @@ struct rteth_ctrl {
struct rteth_tx *tx_data; struct rteth_tx *tx_data;
}; };
static inline void rteth_confirm_and_disable_irqs(struct rteth_ctrl *ctrl,
unsigned long *rings, bool *l2)
{
u32 mask = GENMASK(ctrl->r->rx_rings - 1, 0);
u32 shift = ctrl->r->rx_rings % 32;
u32 reg = ctrl->r->rx_rings / 32;
u32 active;
/* get all irqs, disable only rx (on RTL839x this keeps L2), confirm all */
active = sw_r32(ctrl->r->dma_if_intr_sts + reg * 4);
sw_w32_mask(active & (mask << shift), 0, ctrl->r->dma_if_intr_msk + reg * 4);
sw_w32(active, ctrl->r->dma_if_intr_sts + reg * 4);
/* ~mask filters out RTL93xx devices */
*l2 = !!(active & ~mask & RTL839X_DMA_IF_INTR_NOTIFY_MASK);
*rings = (active >> shift) & mask;
}
static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl) static void rteth_disable_all_irqs(struct rteth_ctrl *ctrl)
{ {
int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1; int registers = ((ctrl->r->rx_rings * 2 + 7) / 32) + 1;
@@ -386,74 +404,22 @@ static void rtl839x_l2_notification_handler(struct rteth_ctrl *ctrl)
ctrl->lastEvent = e; ctrl->lastEvent = e;
} }
static irqreturn_t rteth_83xx_net_irq(int irq, void *dev_id) static irqreturn_t rteth_net_irq(int irq, void *dev_id)
{ {
struct net_device *ndev = dev_id; struct net_device *ndev = dev_id;
struct rteth_ctrl *ctrl = netdev_priv(ndev); struct rteth_ctrl *ctrl = netdev_priv(ndev);
u32 status = sw_r32(ctrl->r->dma_if_intr_sts);
unsigned long ring, rings; unsigned long ring, rings;
bool l2;
netdev_dbg(ndev, "rx interrupt received, status %08x\n", status); rteth_confirm_and_disable_irqs(ctrl, &rings, &l2);
if (status & RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK)
if (net_ratelimit())
netdev_warn(ndev, "rx ring overrun, status 0x%08x, mask 0x%08x\n",
status, sw_r32(ctrl->r->dma_if_intr_msk));
rings = FIELD_GET(RTL83XX_DMA_IF_INTR_RX_DONE_MASK, status);
for_each_set_bit(ring, &rings, RTETH_RX_RINGS) { for_each_set_bit(ring, &rings, RTETH_RX_RINGS) {
netdev_dbg(ndev, "schedule rx ring %lu\n", ring); netdev_dbg(ndev, "schedule rx ring %lu\n", ring);
sw_w32_mask(RTL83XX_DMA_IF_INTR_RX_MASK(ring), 0, ctrl->r->dma_if_intr_msk);
napi_schedule(&ctrl->rx_qs[ring].napi); napi_schedule(&ctrl->rx_qs[ring].napi);
} }
if (status & RTL839X_DMA_IF_INTR_NOTIFY_MASK) if (unlikely(l2))
rtl839x_l2_notification_handler(ctrl); rtl839x_l2_notification_handler(ctrl);
sw_w32(status, ctrl->r->dma_if_intr_sts);
return IRQ_HANDLED;
}
static irqreturn_t rteth_93xx_net_irq(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct rteth_ctrl *ctrl = netdev_priv(dev);
u32 status_rx_r = sw_r32(ctrl->r->dma_if_intr_sts);
u32 status_rx = sw_r32(ctrl->r->dma_if_intr_rx_done_sts);
u32 status_tx = sw_r32(ctrl->r->dma_if_intr_tx_done_sts);
pr_debug("In %s, status_tx: %08x, status_rx: %08x, status_rx_r: %08x\n",
__func__, status_tx, status_rx, status_rx_r);
/* Ignore TX interrupt */
if (status_tx) {
/* Clear ISR */
pr_debug("TX done\n");
sw_w32(status_tx, ctrl->r->dma_if_intr_tx_done_sts);
}
/* RX interrupt */
if (status_rx) {
pr_debug("RX IRQ\n");
/* ACK and disable RX interrupt for given rings */
sw_w32(status_rx, ctrl->r->dma_if_intr_rx_done_sts);
sw_w32_mask(status_rx, 0, ctrl->r->dma_if_intr_rx_done_msk);
for (int i = 0; i < RTETH_RX_RINGS; i++) {
if (status_rx & BIT(i)) {
pr_debug("Scheduling queue: %d\n", i);
napi_schedule(&ctrl->rx_qs[i].napi);
}
}
}
/* RX buffer overrun */
if (status_rx_r) {
pr_debug("RX buffer overrun: status %x, mask: %x\n",
status_rx_r, sw_r32(ctrl->r->dma_if_intr_msk));
sw_w32(status_rx_r, ctrl->r->dma_if_intr_sts);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -1419,7 +1385,6 @@ static const struct rteth_config rteth_838x_cfg = {
.rx_rings = 8, .rx_rings = 8,
.tx_rx_enable = 0xc, .tx_rx_enable = 0xc,
.tx_trigger_mask = BIT(1), .tx_trigger_mask = BIT(1),
.net_irq = rteth_83xx_net_irq,
.mac_l2_port_ctrl = RTETH_838X_MAC_L2_PORT_CTRL, .mac_l2_port_ctrl = RTETH_838X_MAC_L2_PORT_CTRL,
.qm_pkt2cpu_intpri_map = RTETH_838X_QM_PKT2CPU_INTPRI_MAP, .qm_pkt2cpu_intpri_map = RTETH_838X_QM_PKT2CPU_INTPRI_MAP,
.qm_rsn2cpuqid_ctrl = RTETH_838X_QM_PKT2CPU_INTPRI_0, .qm_rsn2cpuqid_ctrl = RTETH_838X_QM_PKT2CPU_INTPRI_0,
@@ -1467,7 +1432,6 @@ static const struct rteth_config rteth_839x_cfg = {
.rx_rings = 8, .rx_rings = 8,
.tx_rx_enable = 0xc, .tx_rx_enable = 0xc,
.tx_trigger_mask = BIT(1), .tx_trigger_mask = BIT(1),
.net_irq = rteth_83xx_net_irq,
.mac_l2_port_ctrl = RTETH_839X_MAC_L2_PORT_CTRL, .mac_l2_port_ctrl = RTETH_839X_MAC_L2_PORT_CTRL,
.qm_pkt2cpu_intpri_map = RTETH_839X_QM_PKT2CPU_INTPRI_MAP, .qm_pkt2cpu_intpri_map = RTETH_839X_QM_PKT2CPU_INTPRI_MAP,
.qm_rsn2cpuqid_ctrl = RTETH_839X_QM_PKT2CPU_INTPRI_0, .qm_rsn2cpuqid_ctrl = RTETH_839X_QM_PKT2CPU_INTPRI_0,
@@ -1515,16 +1479,13 @@ static const struct rteth_config rteth_930x_cfg = {
.rx_rings = 32, .rx_rings = 32,
.tx_rx_enable = 0x30, .tx_rx_enable = 0x30,
.tx_trigger_mask = GENMASK(3, 2), .tx_trigger_mask = GENMASK(3, 2),
.net_irq = rteth_93xx_net_irq,
.mac_l2_port_ctrl = RTETH_930X_MAC_L2_PORT_CTRL, .mac_l2_port_ctrl = RTETH_930X_MAC_L2_PORT_CTRL,
.qm_rsn2cpuqid_ctrl = RTETH_930X_QM_RSN2CPUQID_CTRL_0, .qm_rsn2cpuqid_ctrl = RTETH_930X_QM_RSN2CPUQID_CTRL_0,
.qm_rsn2cpuqid_cnt = RTETH_930X_QM_RSN2CPUQID_CTRL_CNT, .qm_rsn2cpuqid_cnt = RTETH_930X_QM_RSN2CPUQID_CTRL_CNT,
.dma_if_intr_sts = RTETH_930X_DMA_IF_INTR_STS, .dma_if_intr_sts = RTETH_930X_DMA_IF_INTR_STS,
.dma_if_intr_rx_done_sts = RTL930X_DMA_IF_INTR_RX_DONE_STS,
.dma_if_intr_tx_done_sts = RTL930X_DMA_IF_INTR_TX_DONE_STS, .dma_if_intr_tx_done_sts = RTL930X_DMA_IF_INTR_TX_DONE_STS,
.dma_if_intr_msk = RTETH_930X_DMA_IF_INTR_MSK, .dma_if_intr_msk = RTETH_930X_DMA_IF_INTR_MSK,
.dma_if_intr_rx_done_msk = RTL930X_DMA_IF_INTR_RX_DONE_MSK, .dma_if_intr_rx_done_msk = RTL930X_DMA_IF_INTR_RX_DONE_MSK,
.dma_if_intr_tx_done_msk = RTL930X_DMA_IF_INTR_TX_DONE_MSK,
.l2_ntfy_if_intr_sts = RTL930X_L2_NTFY_IF_INTR_STS, .l2_ntfy_if_intr_sts = RTL930X_L2_NTFY_IF_INTR_STS,
.l2_ntfy_if_intr_msk = RTL930X_L2_NTFY_IF_INTR_MSK, .l2_ntfy_if_intr_msk = RTL930X_L2_NTFY_IF_INTR_MSK,
.dma_if_ctrl = RTL930X_DMA_IF_CTRL, .dma_if_ctrl = RTL930X_DMA_IF_CTRL,
@@ -1567,16 +1528,13 @@ static const struct rteth_config rteth_931x_cfg = {
.rx_rings = 32, .rx_rings = 32,
.tx_rx_enable = 0x30, .tx_rx_enable = 0x30,
.tx_trigger_mask = GENMASK(3, 2), .tx_trigger_mask = GENMASK(3, 2),
.net_irq = rteth_93xx_net_irq,
.mac_l2_port_ctrl = RTETH_931X_MAC_L2_PORT_CTRL, .mac_l2_port_ctrl = RTETH_931X_MAC_L2_PORT_CTRL,
.qm_rsn2cpuqid_ctrl = RTETH_931X_QM_RSN2CPUQID_CTRL_0, .qm_rsn2cpuqid_ctrl = RTETH_931X_QM_RSN2CPUQID_CTRL_0,
.qm_rsn2cpuqid_cnt = RTETH_931X_QM_RSN2CPUQID_CTRL_CNT, .qm_rsn2cpuqid_cnt = RTETH_931X_QM_RSN2CPUQID_CTRL_CNT,
.dma_if_intr_sts = RTETH_931X_DMA_IF_INTR_STS, .dma_if_intr_sts = RTETH_931X_DMA_IF_INTR_STS,
.dma_if_intr_rx_done_sts = RTL931X_DMA_IF_INTR_RX_DONE_STS,
.dma_if_intr_tx_done_sts = RTL931X_DMA_IF_INTR_TX_DONE_STS, .dma_if_intr_tx_done_sts = RTL931X_DMA_IF_INTR_TX_DONE_STS,
.dma_if_intr_msk = RTETH_931X_DMA_IF_INTR_MSK, .dma_if_intr_msk = RTETH_931X_DMA_IF_INTR_MSK,
.dma_if_intr_rx_done_msk = RTL931X_DMA_IF_INTR_RX_DONE_MSK, .dma_if_intr_rx_done_msk = RTL931X_DMA_IF_INTR_RX_DONE_MSK,
.dma_if_intr_tx_done_msk = RTL931X_DMA_IF_INTR_TX_DONE_MSK,
.l2_ntfy_if_intr_sts = RTL931X_L2_NTFY_IF_INTR_STS, .l2_ntfy_if_intr_sts = RTL931X_L2_NTFY_IF_INTR_STS,
.l2_ntfy_if_intr_msk = RTL931X_L2_NTFY_IF_INTR_MSK, .l2_ntfy_if_intr_msk = RTL931X_L2_NTFY_IF_INTR_MSK,
.dma_if_ctrl = RTL931X_DMA_IF_CTRL, .dma_if_ctrl = RTL931X_DMA_IF_CTRL,
@@ -1680,8 +1638,7 @@ static int rtl838x_eth_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
rteth_disable_all_irqs(ctrl); rteth_disable_all_irqs(ctrl);
err = devm_request_irq(&pdev->dev, dev->irq, ctrl->r->net_irq, err = devm_request_irq(&pdev->dev, dev->irq, rteth_net_irq, IRQF_SHARED, dev->name, dev);
IRQF_SHARED, dev->name, dev);
if (err) { if (err) {
dev_err(&pdev->dev, "%s: could not acquire interrupt: %d\n", dev_err(&pdev->dev, "%s: could not acquire interrupt: %d\n",
__func__, err); __func__, err);

View File

@@ -64,26 +64,22 @@
#define RTL839X_DMA_IF_CTRL (0x786c) #define RTL839X_DMA_IF_CTRL (0x786c)
#define RTL930X_DMA_IF_CTRL (0xe028) #define RTL930X_DMA_IF_CTRL (0xe028)
#define RTL930X_DMA_IF_INTR_RX_DONE_STS (0xe020)
#define RTL930X_DMA_IF_INTR_TX_DONE_STS (0xe024) #define RTL930X_DMA_IF_INTR_TX_DONE_STS (0xe024)
#define RTL930X_DMA_IF_INTR_RX_DONE_MSK (0xe014) #define RTL930X_DMA_IF_INTR_RX_DONE_MSK (0xe014)
#define RTL930X_DMA_IF_INTR_TX_DONE_MSK (0xe018)
#define RTL930X_L2_NTFY_IF_INTR_MSK (0xe04C) #define RTL930X_L2_NTFY_IF_INTR_MSK (0xe04C)
#define RTL930X_L2_NTFY_IF_INTR_STS (0xe050) #define RTL930X_L2_NTFY_IF_INTR_STS (0xe050)
/* TODO: RTL931X_DMA_IF_CTRL has different bits meanings */ /* TODO: RTL931X_DMA_IF_CTRL has different bits meanings */
#define RTL931X_DMA_IF_CTRL (0x0928) #define RTL931X_DMA_IF_CTRL (0x0928)
#define RTL931X_DMA_IF_INTR_RX_DONE_STS (0x0920)
#define RTL931X_DMA_IF_INTR_TX_DONE_STS (0x0924) #define RTL931X_DMA_IF_INTR_TX_DONE_STS (0x0924)
#define RTL931X_DMA_IF_INTR_RX_DONE_MSK (0x0914) #define RTL931X_DMA_IF_INTR_RX_DONE_MSK (0x0914)
#define RTL931X_DMA_IF_INTR_TX_DONE_MSK (0x0918)
#define RTL931X_L2_NTFY_IF_INTR_MSK (0x09E4) #define RTL931X_L2_NTFY_IF_INTR_MSK (0x09E4)
#define RTL931X_L2_NTFY_IF_INTR_STS (0x09E8) #define RTL931X_L2_NTFY_IF_INTR_STS (0x09E8)
#define RTL839X_DMA_IF_INTR_NOTIFY_MASK GENMASK(22, 20) #define RTL839X_DMA_IF_INTR_NOTIFY_MASK GENMASK(22, 20)
#define RTL83XX_DMA_IF_INTR_RX_DONE_MASK GENMASK(15, 8) #define RTL83XX_DMA_IF_INTR_RX_DONE_MASK GENMASK(15, 8)
#define RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK GENMASK(7, 0) #define RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK GENMASK(7, 0)
#define RTL83XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring) | BIT(ring + 8)) #define RTL83XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring + 8))
#define RTL93XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring)) #define RTL93XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring))
/* MAC address settings */ /* MAC address settings */
@@ -411,17 +407,14 @@ struct rteth_config {
int rx_rings; int rx_rings;
int tx_rx_enable; int tx_rx_enable;
int tx_trigger_mask; int tx_trigger_mask;
irqreturn_t (*net_irq)(int irq, void *dev_id);
int mac_l2_port_ctrl; int mac_l2_port_ctrl;
int qm_pkt2cpu_intpri_map; int qm_pkt2cpu_intpri_map;
int qm_rsn2cpuqid_ctrl; int qm_rsn2cpuqid_ctrl;
int qm_rsn2cpuqid_cnt; int qm_rsn2cpuqid_cnt;
int dma_if_intr_sts; int dma_if_intr_sts;
int dma_if_intr_msk; int dma_if_intr_msk;
int dma_if_intr_rx_done_sts;
int dma_if_intr_tx_done_sts; int dma_if_intr_tx_done_sts;
int dma_if_intr_rx_done_msk; int dma_if_intr_rx_done_msk;
int dma_if_intr_tx_done_msk;
int l2_ntfy_if_intr_sts; int l2_ntfy_if_intr_sts;
int l2_ntfy_if_intr_msk; int l2_ntfy_if_intr_msk;
int dma_if_ctrl; int dma_if_ctrl;