Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-macb-remove-dedicated-irq-handler-for-wol'

Kevin Hao says:

====================
net: macb: Remove dedicated IRQ handler for WoL

During debugging of a suspend/resume issue, I observed that the macb driver
employs a dedicated IRQ handler for Wake-on-LAN (WoL) support. To my knowledge,
no other Ethernet driver adopts this approach. This implementation unnecessarily
complicates the suspend/resume process without providing any clear benefit.
Instead, we can easily modify the existing IRQ handler to manage WoL events,
avoiding any overhead in the TX/RX hot path.

The net throughput shows no significant difference following these changes.
The following data(net throughput and execution time of macb_interrupt) were
collected from my AMD Zynqmp board using the commands:
taskset -c 1,2,3 iperf3 -c 192.168.3.4 -t 60 -Z -P 3 -R
cat /sys/kernel/debug/tracing/trace_stat/function0

Before:
-------
[SUM] 0.00-60.00 sec 5.99 GBytes 858 Mbits/sec 0 sender
[SUM] 0.00-60.00 sec 5.99 GBytes 857 Mbits/sec receiver

Function Hit Time Avg s^2
-------- --- ---- --- ---
macb_interrupt 217996 678425.2 us 3.112 us 1.446 us

After:
------
[SUM] 0.00-60.00 sec 6.00 GBytes 858 Mbits/sec 0 sender
[SUM] 0.00-60.00 sec 5.99 GBytes 857 Mbits/sec receiver

Function Hit Time Avg s^2
-------- --- ---- --- ---
macb_interrupt 218212 668107.3 us 3.061 us 1.413 us
====================

Link: https://patch.msgid.link/20260402-macb-irq-v2-0-942d98ab1154@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+99 -158
+7
drivers/net/ethernet/cadence/macb.h
··· 1474 1474 bp->caps & MACB_CAPS_DMA_PTP; 1475 1475 } 1476 1476 1477 + static inline void macb_queue_isr_clear(struct macb *bp, 1478 + struct macb_queue *queue, u32 value) 1479 + { 1480 + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 1481 + queue_writel(queue, ISR, value); 1482 + } 1483 + 1477 1484 /** 1478 1485 * struct macb_platform_data - platform data for MACB Ethernet used for PCI registration 1479 1486 * @pclk: platform clock
+92 -158
drivers/net/ethernet/cadence/macb_main.c
··· 70 70 #define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP) \ 71 71 | MACB_BIT(TXUBR)) 72 72 73 + #define MACB_INT_MISC_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(RXUBR) | \ 74 + MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP) | \ 75 + GEM_BIT(WOL) | MACB_BIT(WOL)) 76 + 73 77 /* Max length of transmit frame must be a multiple of 8 bytes */ 74 78 #define MACB_TX_LEN_ALIGN 8 75 79 #define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) ··· 1891 1887 */ 1892 1888 if (macb_rx_pending(queue)) { 1893 1889 queue_writel(queue, IDR, bp->rx_intr_mask); 1894 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 1895 - queue_writel(queue, ISR, MACB_BIT(RCOMP)); 1890 + macb_queue_isr_clear(bp, queue, MACB_BIT(RCOMP)); 1896 1891 netdev_vdbg(bp->dev, "poll: packets pending, reschedule\n"); 1897 1892 napi_schedule(napi); 1898 1893 } ··· 1978 1975 */ 1979 1976 if (macb_tx_complete_pending(queue)) { 1980 1977 queue_writel(queue, IDR, MACB_BIT(TCOMP)); 1981 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 1982 - queue_writel(queue, ISR, MACB_BIT(TCOMP)); 1978 + macb_queue_isr_clear(bp, queue, MACB_BIT(TCOMP)); 1983 1979 netdev_vdbg(bp->dev, "TX poll: packets pending, reschedule\n"); 1984 1980 napi_schedule(napi); 1985 1981 } ··· 2026 2024 netif_tx_start_all_queues(dev); 2027 2025 } 2028 2026 2029 - static irqreturn_t macb_wol_interrupt(int irq, void *dev_id) 2027 + static void macb_wol_interrupt(struct macb_queue *queue, u32 status) 2030 2028 { 2031 - struct macb_queue *queue = dev_id; 2032 2029 struct macb *bp = queue->bp; 2033 - u32 status; 2034 2030 2035 - status = queue_readl(queue, ISR); 2036 - 2037 - if (unlikely(!status)) 2038 - return IRQ_NONE; 2039 - 2040 - spin_lock(&bp->lock); 2041 - 2042 - if (status & MACB_BIT(WOL)) { 2043 - queue_writel(queue, IDR, MACB_BIT(WOL)); 2044 - macb_writel(bp, WOL, 0); 2045 - netdev_vdbg(bp->dev, "MACB WoL: queue = %u, isr = 0x%08lx\n", 2046 - (unsigned int)(queue - bp->queues), 2047 - (unsigned long)status); 2048 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2049 - queue_writel(queue, ISR, MACB_BIT(WOL)); 2050 - pm_wakeup_event(&bp->pdev->dev, 0); 2051 - } 2052 - 2053 - spin_unlock(&bp->lock); 2054 - 2055 - return IRQ_HANDLED; 2031 + queue_writel(queue, IDR, MACB_BIT(WOL)); 2032 + macb_writel(bp, WOL, 0); 2033 + netdev_vdbg(bp->dev, "MACB WoL: queue = %u, isr = 0x%08lx\n", 2034 + (unsigned int)(queue - bp->queues), 2035 + (unsigned long)status); 2036 + macb_queue_isr_clear(bp, queue, MACB_BIT(WOL)); 2037 + pm_wakeup_event(&bp->pdev->dev, 0); 2056 2038 } 2057 2039 2058 - static irqreturn_t gem_wol_interrupt(int irq, void *dev_id) 2040 + static void gem_wol_interrupt(struct macb_queue *queue, u32 status) 2059 2041 { 2060 - struct macb_queue *queue = dev_id; 2061 2042 struct macb *bp = queue->bp; 2062 - u32 status; 2063 2043 2064 - status = queue_readl(queue, ISR); 2044 + queue_writel(queue, IDR, GEM_BIT(WOL)); 2045 + gem_writel(bp, WOL, 0); 2046 + netdev_vdbg(bp->dev, "GEM WoL: queue = %u, isr = 0x%08lx\n", 2047 + (unsigned int)(queue - bp->queues), 2048 + (unsigned long)status); 2049 + macb_queue_isr_clear(bp, queue, GEM_BIT(WOL)); 2050 + pm_wakeup_event(&bp->pdev->dev, 0); 2051 + } 2065 2052 2066 - if (unlikely(!status)) 2067 - return IRQ_NONE; 2053 + static int macb_interrupt_misc(struct macb_queue *queue, u32 status) 2054 + { 2055 + struct macb *bp = queue->bp; 2056 + struct net_device *dev; 2057 + u32 ctrl; 2068 2058 2069 - spin_lock(&bp->lock); 2059 + dev = bp->dev; 2070 2060 2071 - if (status & GEM_BIT(WOL)) { 2072 - queue_writel(queue, IDR, GEM_BIT(WOL)); 2073 - gem_writel(bp, WOL, 0); 2074 - netdev_vdbg(bp->dev, "GEM WoL: queue = %u, isr = 0x%08lx\n", 2075 - (unsigned int)(queue - bp->queues), 2076 - (unsigned long)status); 2077 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2078 - queue_writel(queue, ISR, GEM_BIT(WOL)); 2079 - pm_wakeup_event(&bp->pdev->dev, 0); 2061 + if (unlikely(status & (MACB_TX_ERR_FLAGS))) { 2062 + queue_writel(queue, IDR, MACB_TX_INT_FLAGS); 2063 + schedule_work(&queue->tx_error_task); 2064 + macb_queue_isr_clear(bp, queue, MACB_TX_ERR_FLAGS); 2065 + return -1; 2080 2066 } 2081 2067 2082 - spin_unlock(&bp->lock); 2068 + /* Link change detection isn't possible with RMII, so we'll 2069 + * add that if/when we get our hands on a full-blown MII PHY. 2070 + */ 2083 2071 2084 - return IRQ_HANDLED; 2072 + /* There is a hardware issue under heavy load where DMA can 2073 + * stop, this causes endless "used buffer descriptor read" 2074 + * interrupts but it can be cleared by re-enabling RX. See 2075 + * the at91rm9200 manual, section 41.3.1 or the Zynq manual 2076 + * section 16.7.4 for details. RXUBR is only enabled for 2077 + * these two versions. 2078 + */ 2079 + if (status & MACB_BIT(RXUBR)) { 2080 + ctrl = macb_readl(bp, NCR); 2081 + macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); 2082 + wmb(); 2083 + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); 2084 + macb_queue_isr_clear(bp, queue, MACB_BIT(RXUBR)); 2085 + } 2086 + 2087 + if (status & MACB_BIT(ISR_ROVR)) { 2088 + /* We missed at least one packet */ 2089 + spin_lock(&bp->stats_lock); 2090 + if (macb_is_gem(bp)) 2091 + bp->hw_stats.gem.rx_overruns++; 2092 + else 2093 + bp->hw_stats.macb.rx_overruns++; 2094 + spin_unlock(&bp->stats_lock); 2095 + macb_queue_isr_clear(bp, queue, MACB_BIT(ISR_ROVR)); 2096 + } 2097 + 2098 + if (status & MACB_BIT(HRESP)) { 2099 + queue_work(system_bh_wq, &bp->hresp_err_bh_work); 2100 + netdev_err(dev, "DMA bus error: HRESP not OK\n"); 2101 + macb_queue_isr_clear(bp, queue, MACB_BIT(HRESP)); 2102 + } 2103 + 2104 + if (macb_is_gem(bp)) { 2105 + if (status & GEM_BIT(WOL)) 2106 + gem_wol_interrupt(queue, status); 2107 + } else { 2108 + if (status & MACB_BIT(WOL)) 2109 + macb_wol_interrupt(queue, status); 2110 + } 2111 + 2112 + return 0; 2085 2113 } 2086 2114 2087 2115 static irqreturn_t macb_interrupt(int irq, void *dev_id) ··· 2119 2087 struct macb_queue *queue = dev_id; 2120 2088 struct macb *bp = queue->bp; 2121 2089 struct net_device *dev = bp->dev; 2122 - u32 status, ctrl; 2090 + u32 status; 2123 2091 2124 2092 status = queue_readl(queue, ISR); 2125 2093 ··· 2132 2100 /* close possible race with dev_close */ 2133 2101 if (unlikely(!netif_running(dev))) { 2134 2102 queue_writel(queue, IDR, -1); 2135 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2136 - queue_writel(queue, ISR, -1); 2103 + macb_queue_isr_clear(bp, queue, -1); 2137 2104 break; 2138 2105 } 2139 2106 ··· 2148 2117 * now. 2149 2118 */ 2150 2119 queue_writel(queue, IDR, bp->rx_intr_mask); 2151 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2152 - queue_writel(queue, ISR, MACB_BIT(RCOMP)); 2153 - 2154 - if (napi_schedule_prep(&queue->napi_rx)) { 2155 - netdev_vdbg(bp->dev, "scheduling RX softirq\n"); 2156 - __napi_schedule(&queue->napi_rx); 2157 - } 2120 + macb_queue_isr_clear(bp, queue, MACB_BIT(RCOMP)); 2121 + napi_schedule(&queue->napi_rx); 2158 2122 } 2159 2123 2160 2124 if (status & (MACB_BIT(TCOMP) | 2161 2125 MACB_BIT(TXUBR))) { 2162 2126 queue_writel(queue, IDR, MACB_BIT(TCOMP)); 2163 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2164 - queue_writel(queue, ISR, MACB_BIT(TCOMP) | 2165 - MACB_BIT(TXUBR)); 2166 - 2127 + macb_queue_isr_clear(bp, queue, MACB_BIT(TCOMP) | 2128 + MACB_BIT(TXUBR)); 2167 2129 if (status & MACB_BIT(TXUBR)) { 2168 2130 queue->txubr_pending = true; 2169 2131 wmb(); // ensure softirq can see update 2170 2132 } 2171 2133 2172 - if (napi_schedule_prep(&queue->napi_tx)) { 2173 - netdev_vdbg(bp->dev, "scheduling TX softirq\n"); 2174 - __napi_schedule(&queue->napi_tx); 2175 - } 2134 + napi_schedule(&queue->napi_tx); 2176 2135 } 2177 2136 2178 - if (unlikely(status & (MACB_TX_ERR_FLAGS))) { 2179 - queue_writel(queue, IDR, MACB_TX_INT_FLAGS); 2180 - schedule_work(&queue->tx_error_task); 2137 + if (unlikely(status & MACB_INT_MISC_FLAGS)) 2138 + if (macb_interrupt_misc(queue, status)) 2139 + break; 2181 2140 2182 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2183 - queue_writel(queue, ISR, MACB_TX_ERR_FLAGS); 2184 - 2185 - break; 2186 - } 2187 - 2188 - /* Link change detection isn't possible with RMII, so we'll 2189 - * add that if/when we get our hands on a full-blown MII PHY. 2190 - */ 2191 - 2192 - /* There is a hardware issue under heavy load where DMA can 2193 - * stop, this causes endless "used buffer descriptor read" 2194 - * interrupts but it can be cleared by re-enabling RX. See 2195 - * the at91rm9200 manual, section 41.3.1 or the Zynq manual 2196 - * section 16.7.4 for details. RXUBR is only enabled for 2197 - * these two versions. 2198 - */ 2199 - if (status & MACB_BIT(RXUBR)) { 2200 - ctrl = macb_readl(bp, NCR); 2201 - macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); 2202 - wmb(); 2203 - macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); 2204 - 2205 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2206 - queue_writel(queue, ISR, MACB_BIT(RXUBR)); 2207 - } 2208 - 2209 - if (status & MACB_BIT(ISR_ROVR)) { 2210 - /* We missed at least one packet */ 2211 - spin_lock(&bp->stats_lock); 2212 - if (macb_is_gem(bp)) 2213 - bp->hw_stats.gem.rx_overruns++; 2214 - else 2215 - bp->hw_stats.macb.rx_overruns++; 2216 - spin_unlock(&bp->stats_lock); 2217 - 2218 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2219 - queue_writel(queue, ISR, MACB_BIT(ISR_ROVR)); 2220 - } 2221 - 2222 - if (status & MACB_BIT(HRESP)) { 2223 - queue_work(system_bh_wq, &bp->hresp_err_bh_work); 2224 - netdev_err(dev, "DMA bus error: HRESP not OK\n"); 2225 - 2226 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2227 - queue_writel(queue, ISR, MACB_BIT(HRESP)); 2228 - } 2229 2141 status = queue_readl(queue, ISR); 2230 2142 } 2231 2143 ··· 2863 2889 for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { 2864 2890 queue_writel(queue, IDR, -1); 2865 2891 queue_readl(queue, ISR); 2866 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 2867 - queue_writel(queue, ISR, -1); 2892 + macb_queue_isr_clear(bp, queue, -1); 2868 2893 } 2869 2894 } 2870 2895 ··· 5983 6010 unsigned long flags; 5984 6011 u32 tmp, ifa_local; 5985 6012 unsigned int q; 5986 - int err; 5987 6013 5988 6014 if (!device_may_wakeup(&bp->dev->dev)) 5989 6015 phy_exit(bp->phy); ··· 6031 6059 /* Disable all interrupts */ 6032 6060 queue_writel(queue, IDR, -1); 6033 6061 queue_readl(queue, ISR); 6034 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 6035 - queue_writel(queue, ISR, -1); 6062 + macb_queue_isr_clear(bp, queue, -1); 6036 6063 } 6037 6064 /* Enable Receive engine */ 6038 6065 macb_writel(bp, NCR, tmp | MACB_BIT(RE)); ··· 6045 6074 /* write IP address into register */ 6046 6075 tmp |= MACB_BFEXT(IP, ifa_local); 6047 6076 } 6048 - spin_unlock_irqrestore(&bp->lock, flags); 6049 6077 6050 - /* Change interrupt handler and 6051 - * Enable WoL IRQ on queue 0 6052 - */ 6053 - devm_free_irq(dev, bp->queues[0].irq, bp->queues); 6054 6078 if (macb_is_gem(bp)) { 6055 - err = devm_request_irq(dev, bp->queues[0].irq, gem_wol_interrupt, 6056 - IRQF_SHARED, netdev->name, bp->queues); 6057 - if (err) { 6058 - dev_err(dev, 6059 - "Unable to request IRQ %d (error %d)\n", 6060 - bp->queues[0].irq, err); 6061 - return err; 6062 - } 6063 - spin_lock_irqsave(&bp->lock, flags); 6064 6079 queue_writel(bp->queues, IER, GEM_BIT(WOL)); 6065 6080 gem_writel(bp, WOL, tmp); 6066 - spin_unlock_irqrestore(&bp->lock, flags); 6067 6081 } else { 6068 - err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt, 6069 - IRQF_SHARED, netdev->name, bp->queues); 6070 - if (err) { 6071 - dev_err(dev, 6072 - "Unable to request IRQ %d (error %d)\n", 6073 - bp->queues[0].irq, err); 6074 - return err; 6075 - } 6076 - spin_lock_irqsave(&bp->lock, flags); 6077 6082 queue_writel(bp->queues, IER, MACB_BIT(WOL)); 6078 6083 macb_writel(bp, WOL, tmp); 6079 - spin_unlock_irqrestore(&bp->lock, flags); 6080 6084 } 6085 + spin_unlock_irqrestore(&bp->lock, flags); 6081 6086 6082 6087 enable_irq_wake(bp->queues[0].irq); 6083 6088 } ··· 6095 6148 struct macb_queue *queue; 6096 6149 unsigned long flags; 6097 6150 unsigned int q; 6098 - int err; 6099 6151 6100 6152 if (!device_may_wakeup(&bp->dev->dev)) 6101 6153 phy_init(bp->phy); ··· 6117 6171 } 6118 6172 /* Clear ISR on queue 0 */ 6119 6173 queue_readl(bp->queues, ISR); 6120 - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) 6121 - queue_writel(bp->queues, ISR, -1); 6174 + macb_queue_isr_clear(bp, bp->queues, -1); 6122 6175 spin_unlock_irqrestore(&bp->lock, flags); 6123 - 6124 - /* Replace interrupt handler on queue 0 */ 6125 - devm_free_irq(dev, bp->queues[0].irq, bp->queues); 6126 - err = devm_request_irq(dev, bp->queues[0].irq, macb_interrupt, 6127 - IRQF_SHARED, netdev->name, bp->queues); 6128 - if (err) { 6129 - dev_err(dev, 6130 - "Unable to request IRQ %d (error %d)\n", 6131 - bp->queues[0].irq, err); 6132 - return err; 6133 - } 6134 6176 6135 6177 disable_irq_wake(bp->queues[0].irq); 6136 6178