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

Merge branch 'net-stmmac-CPU-Performance-Improvements'

Jose Abreu says:

====================
net: stmmac: CPU Performance Improvements

CPU Performance improvements for stmmac. Please check bellow for results
before and after the series.

Patch 1/7, allows RX Interrupt on Completion to be disabled and only use the
RX HW Watchdog.

Patch 2/7, setups the default RX coalesce settings instead of using the
minimum value.

Patch 3/7 and 4/7, removes the uneeded computations for RX Flow Control
activation/de-activation, on some cases.

Patch 5/7, tunes-up the default coalesce settings.

Patch 6/7, re-works the TX coalesce timer activation logic.

Patch 7/7, removes the now uneeded TBU interrupt.

NetPerf UDP Results:
--------------------

Socket Message Elapsed Messages CPU Service
Size Size Time Okay Errors Throughput Util Demand
bytes bytes secs # # 10^6bits/sec % SS us/KB
--- XGMAC@2.5G: Before
212992 1400 10.00 2100620 0 2351.7 36.69 5.112
212992 10.00 2100539 2351.6 26.18 3.648
--- XGMAC@2.5G: After
212992 1400 10.00 2108972 0 2361.5 21.73 3.015
212992 10.00 2097038 2348.1 19.21 2.666

--- GMAC5@1G: Before
212992 1400 10.00 786000 0 880.2 34.71 12.923
212992 10.00 786000 880.2 23.42 8.719
--- GMAC5@1G: After
212992 1400 10.00 842648 0 943.7 14.12 4.903
212992 10.00 842648 943.7 12.73 4.418

Perf TCP Results on RX Path:
----------------------------
--- XGMAC@2.5G: Before
22.51% swapper [stmmac] [k] dwxgmac2_dma_interrupt
10.82% swapper [stmmac] [k] dwxgmac2_host_mtl_irq_status
5.21% swapper [stmmac] [k] dwxgmac2_host_irq_status
4.67% swapper [stmmac] [k] dwxgmac3_safety_feat_irq_status
3.63% swapper [kernel.kallsyms] [k] stack_trace_consume_entry
2.74% iperf3 [kernel.kallsyms] [k] copy_user_enhanced_fast_string
2.52% swapper [kernel.kallsyms] [k] update_stack_state
1.94% ksoftirqd/0 [stmmac] [k] dwxgmac2_dma_interrupt
1.45% iperf3 [kernel.kallsyms] [k] queued_spin_lock_slowpath
1.26% swapper [kernel.kallsyms] [k] create_object
--- XGMAC@2.5G: After
7.43% swapper [kernel.kallsyms] [k] stack_trace_consume_entry
5.86% swapper [stmmac] [k] dwxgmac2_dma_interrupt
5.68% swapper [kernel.kallsyms] [k] update_stack_state
4.71% iperf3 [kernel.kallsyms] [k] copy_user_enhanced_fast_string
2.88% swapper [kernel.kallsyms] [k] create_object
2.69% swapper [stmmac] [k] dwxgmac2_host_mtl_irq_status
2.61% swapper [stmmac] [k] stmmac_napi_poll_rx
2.52% swapper [kernel.kallsyms] [k] unwind_next_frame.part.4
1.48% swapper [kernel.kallsyms] [k] unwind_get_return_address
1.38% swapper [kernel.kallsyms] [k] arch_stack_walk

--- GMAC5@1G: Before
31.29% swapper [stmmac] [k] dwmac4_dma_interrupt
14.57% swapper [stmmac] [k] dwmac4_irq_mtl_status
10.66% swapper [stmmac] [k] dwmac4_irq_status
1.97% swapper [kernel.kallsyms] [k] stack_trace_consume_entry
1.73% iperf3 [kernel.kallsyms] [k] copy_user_enhanced_fast_string
1.59% swapper [kernel.kallsyms] [k] update_stack_state
1.15% iperf3 [kernel.kallsyms] [k] do_syscall_64
1.01% ksoftirqd/0 [stmmac] [k] dwmac4_dma_interrupt
0.89% swapper [kernel.kallsyms] [k] __default_send_IPI_dest_field
0.75% swapper [stmmac] [k] stmmac_napi_poll_rx
--- GMAC5@1G: After
6.70% swapper [kernel.kallsyms] [k] stack_trace_consume_entry
5.79% swapper [stmmac] [k] dwmac4_dma_interrupt
5.29% swapper [kernel.kallsyms] [k] update_stack_state
3.52% iperf3 [kernel.kallsyms] [k] copy_user_enhanced_fast_string
2.83% swapper [stmmac] [k] dwmac4_irq_mtl_status
2.62% swapper [kernel.kallsyms] [k] create_object
2.46% swapper [stmmac] [k] stmmac_napi_poll_rx
2.32% swapper [kernel.kallsyms] [k] unwind_next_frame.part.4
2.19% swapper [stmmac] [k] dwmac4_irq_status
1.39% swapper [kernel.kallsyms] [k] unwind_get_return_address
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+59 -50
+3 -2
drivers/net/ethernet/stmicro/stmmac/common.h
··· 248 248 /* Max/Min RI Watchdog Timer count value */ 249 249 #define MAX_DMA_RIWT 0xff 250 250 #define MIN_DMA_RIWT 0x10 251 + #define DEF_DMA_RIWT 0xa0 251 252 /* Tx coalesce parameters */ 252 253 #define STMMAC_COAL_TX_TIMER 1000 253 254 #define STMMAC_MAX_COAL_TX_TICK 100000 254 255 #define STMMAC_TX_MAX_FRAMES 256 255 - #define STMMAC_TX_FRAMES 1 256 - #define STMMAC_RX_FRAMES 25 256 + #define STMMAC_TX_FRAMES 25 257 + #define STMMAC_RX_FRAMES 0 257 258 258 259 /* Packets types */ 259 260 enum packets_types {
+2 -12
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
··· 252 252 rfa = 0x01; /* Full-1.5K */ 253 253 break; 254 254 255 - case 8192: 256 - rfd = 0x06; /* Full-4K */ 257 - rfa = 0x0a; /* Full-6K */ 258 - break; 259 - 260 - case 16384: 261 - rfd = 0x06; /* Full-4K */ 262 - rfa = 0x12; /* Full-10K */ 263 - break; 264 - 265 255 default: 266 - rfd = 0x06; /* Full-4K */ 267 - rfa = 0x1e; /* Full-16K */ 256 + rfd = 0x07; /* Full-4.5K */ 257 + rfa = 0x04; /* Full-3K */ 268 258 break; 269 259 } 270 260
+1 -1
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
··· 360 360 #define XGMAC_TBUE BIT(2) 361 361 #define XGMAC_TIE BIT(0) 362 362 #define XGMAC_DMA_INT_DEFAULT_EN (XGMAC_NIE | XGMAC_AIE | XGMAC_RBUE | \ 363 - XGMAC_RIE | XGMAC_TBUE | XGMAC_TIE) 363 + XGMAC_RIE | XGMAC_TIE) 364 364 #define XGMAC_DMA_CH_Rx_WATCHDOG(x) (0x0000313c + (0x80 * (x))) 365 365 #define XGMAC_RWT GENMASK(7, 0) 366 366 #define XGMAC_DMA_CH_STATUS(x) (0x00003160 + (0x80 * (x)))
+2 -12
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
··· 183 183 rfa = 0x01; /* Full-1.5K */ 184 184 break; 185 185 186 - case 8192: 187 - rfd = 0x06; /* Full-4K */ 188 - rfa = 0x0a; /* Full-6K */ 189 - break; 190 - 191 - case 16384: 192 - rfd = 0x06; /* Full-4K */ 193 - rfa = 0x12; /* Full-10K */ 194 - break; 195 - 196 186 default: 197 - rfd = 0x06; /* Full-4K */ 198 - rfa = 0x1e; /* Full-16K */ 187 + rfd = 0x07; /* Full-4.5K */ 188 + rfa = 0x04; /* Full-3K */ 199 189 break; 200 190 } 201 191
+51 -23
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 2605 2605 priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 2606 2606 2607 2607 if (priv->use_riwt) { 2608 - ret = stmmac_rx_watchdog(priv, priv->ioaddr, MIN_DMA_RIWT, rx_cnt); 2609 - if (!ret) 2610 - priv->rx_riwt = MIN_DMA_RIWT; 2608 + if (!priv->rx_riwt) 2609 + priv->rx_riwt = DEF_DMA_RIWT; 2610 + 2611 + ret = stmmac_rx_watchdog(priv, priv->ioaddr, priv->rx_riwt, rx_cnt); 2611 2612 } 2612 2613 2613 2614 if (priv->hw->pcs) ··· 2916 2915 struct stmmac_priv *priv = netdev_priv(dev); 2917 2916 int nfrags = skb_shinfo(skb)->nr_frags; 2918 2917 u32 queue = skb_get_queue_mapping(skb); 2918 + unsigned int first_entry, tx_packets; 2919 + int tmp_pay_len = 0, first_tx; 2919 2920 struct stmmac_tx_queue *tx_q; 2920 - unsigned int first_entry; 2921 2921 u8 proto_hdr_len, hdr; 2922 - int tmp_pay_len = 0; 2922 + bool has_vlan, set_ic; 2923 2923 u32 pay_len, mss; 2924 2924 dma_addr_t des; 2925 - bool has_vlan; 2926 2925 int i; 2927 2926 2928 2927 tx_q = &priv->tx_queue[queue]; 2928 + first_tx = tx_q->cur_tx; 2929 2929 2930 2930 /* Compute header lengths */ 2931 2931 if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { ··· 3034 3032 tx_q->tx_skbuff[tx_q->cur_tx] = skb; 3035 3033 3036 3034 /* Manage tx mitigation */ 3037 - tx_q->tx_count_frames += nfrags + 1; 3038 - if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) && 3039 - !((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 3040 - priv->hwts_tx_en)) { 3041 - stmmac_tx_timer_arm(priv, queue); 3042 - } else { 3035 + tx_packets = (tx_q->cur_tx + 1) - first_tx; 3036 + tx_q->tx_count_frames += tx_packets; 3037 + 3038 + if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en) 3039 + set_ic = true; 3040 + else if (!priv->tx_coal_frames) 3041 + set_ic = false; 3042 + else if (tx_packets > priv->tx_coal_frames) 3043 + set_ic = true; 3044 + else if ((tx_q->tx_count_frames % priv->tx_coal_frames) < tx_packets) 3045 + set_ic = true; 3046 + else 3047 + set_ic = false; 3048 + 3049 + if (set_ic) { 3043 3050 desc = &tx_q->dma_tx[tx_q->cur_tx]; 3044 3051 tx_q->tx_count_frames = 0; 3045 3052 stmmac_set_tx_ic(priv, desc); 3046 3053 priv->xstats.tx_set_ic_bit++; 3054 + } else { 3055 + stmmac_tx_timer_arm(priv, queue); 3047 3056 } 3048 3057 3049 3058 /* We've used all descriptors we need for this skb, however, ··· 3145 3132 */ 3146 3133 static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 3147 3134 { 3135 + unsigned int first_entry, tx_packets, enh_desc; 3148 3136 struct stmmac_priv *priv = netdev_priv(dev); 3149 3137 unsigned int nopaged_len = skb_headlen(skb); 3150 3138 int i, csum_insertion = 0, is_jumbo = 0; ··· 3154 3140 int gso = skb_shinfo(skb)->gso_type; 3155 3141 struct dma_desc *desc, *first; 3156 3142 struct stmmac_tx_queue *tx_q; 3157 - unsigned int first_entry; 3158 - unsigned int enh_desc; 3143 + bool has_vlan, set_ic; 3144 + int entry, first_tx; 3159 3145 dma_addr_t des; 3160 - bool has_vlan; 3161 - int entry; 3162 3146 3163 3147 tx_q = &priv->tx_queue[queue]; 3148 + first_tx = tx_q->cur_tx; 3164 3149 3165 3150 if (priv->tx_path_in_lpi_mode) 3166 3151 stmmac_disable_eee_mode(priv); ··· 3253 3240 * This approach takes care about the fragments: desc is the first 3254 3241 * element in case of no SG. 3255 3242 */ 3256 - tx_q->tx_count_frames += nfrags + 1; 3257 - if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) && 3258 - !((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 3259 - priv->hwts_tx_en)) { 3260 - stmmac_tx_timer_arm(priv, queue); 3261 - } else { 3243 + tx_packets = (entry + 1) - first_tx; 3244 + tx_q->tx_count_frames += tx_packets; 3245 + 3246 + if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en) 3247 + set_ic = true; 3248 + else if (!priv->tx_coal_frames) 3249 + set_ic = false; 3250 + else if (tx_packets > priv->tx_coal_frames) 3251 + set_ic = true; 3252 + else if ((tx_q->tx_count_frames % priv->tx_coal_frames) < tx_packets) 3253 + set_ic = true; 3254 + else 3255 + set_ic = false; 3256 + 3257 + if (set_ic) { 3262 3258 if (likely(priv->extend_desc)) 3263 3259 desc = &tx_q->dma_etx[entry].basic; 3264 3260 else ··· 3276 3254 tx_q->tx_count_frames = 0; 3277 3255 stmmac_set_tx_ic(priv, desc); 3278 3256 priv->xstats.tx_set_ic_bit++; 3257 + } else { 3258 + stmmac_tx_timer_arm(priv, queue); 3279 3259 } 3280 3260 3281 3261 /* We've used all descriptors we need for this skb, however, ··· 3464 3440 rx_q->rx_count_frames += priv->rx_coal_frames; 3465 3441 if (rx_q->rx_count_frames > priv->rx_coal_frames) 3466 3442 rx_q->rx_count_frames = 0; 3467 - use_rx_wd = priv->use_riwt && rx_q->rx_count_frames; 3443 + 3444 + use_rx_wd = !priv->rx_coal_frames; 3445 + use_rx_wd |= rx_q->rx_count_frames > 0; 3446 + if (!priv->use_riwt) 3447 + use_rx_wd = false; 3468 3448 3469 3449 dma_wmb(); 3470 3450 stmmac_set_rx_owner(priv, p, use_rx_wd);