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-wangxun-complete-ethtool-coalesce-options'

Jiawen Wu says:

====================
net: wangxun: complete ethtool coalesce options

Support to use adaptive RX coalescing. Change the default RX coalesce
usecs and limit the range of parameters for various types of devices,
according to their hardware design.
====================

Link: https://patch.msgid.link/20250821023408.53472-1-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+155 -27
+1
drivers/net/ethernet/wangxun/Kconfig
··· 20 20 tristate 21 21 depends on PTP_1588_CLOCK_OPTIONAL 22 22 select PAGE_POOL 23 + select DIMLIB 23 24 help 24 25 Common library for Wangxun(R) Ethernet drivers. 25 26
+35 -20
drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
··· 303 303 else 304 304 ec->rx_coalesce_usecs = wx->rx_itr_setting >> 2; 305 305 306 + if (wx->adaptive_itr) { 307 + ec->use_adaptive_rx_coalesce = 1; 308 + ec->use_adaptive_tx_coalesce = 1; 309 + } 310 + 306 311 /* if in mixed tx/rx queues per vector mode, report only rx settings */ 307 312 if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count) 308 313 return 0; ··· 339 334 return -EOPNOTSUPP; 340 335 } 341 336 342 - if (ec->tx_max_coalesced_frames_irq) 343 - wx->tx_work_limit = ec->tx_max_coalesced_frames_irq; 337 + if (ec->tx_max_coalesced_frames_irq > U16_MAX || 338 + !ec->tx_max_coalesced_frames_irq) 339 + return -EINVAL; 340 + 341 + wx->tx_work_limit = ec->tx_max_coalesced_frames_irq; 344 342 345 343 switch (wx->mac.type) { 346 344 case wx_mac_sp: 347 345 max_eitr = WX_SP_MAX_EITR; 346 + rx_itr_param = WX_20K_ITR; 347 + tx_itr_param = WX_12K_ITR; 348 348 break; 349 349 case wx_mac_aml: 350 350 case wx_mac_aml40: 351 351 max_eitr = WX_AML_MAX_EITR; 352 + rx_itr_param = WX_20K_ITR; 353 + tx_itr_param = WX_12K_ITR; 352 354 break; 353 355 default: 354 356 max_eitr = WX_EM_MAX_EITR; 357 + rx_itr_param = WX_7K_ITR; 358 + tx_itr_param = WX_7K_ITR; 355 359 break; 356 360 } 357 361 ··· 368 354 (ec->tx_coalesce_usecs > (max_eitr >> 2))) 369 355 return -EINVAL; 370 356 357 + if (ec->use_adaptive_rx_coalesce) { 358 + wx->adaptive_itr = true; 359 + wx->rx_itr_setting = 1; 360 + wx->tx_itr_setting = 1; 361 + return 0; 362 + } 363 + 371 364 if (ec->rx_coalesce_usecs > 1) 372 365 wx->rx_itr_setting = ec->rx_coalesce_usecs << 2; 373 366 else 374 367 wx->rx_itr_setting = ec->rx_coalesce_usecs; 375 - 376 - if (wx->rx_itr_setting == 1) 377 - rx_itr_param = WX_20K_ITR; 378 - else 379 - rx_itr_param = wx->rx_itr_setting; 380 368 381 369 if (ec->tx_coalesce_usecs > 1) 382 370 wx->tx_itr_setting = ec->tx_coalesce_usecs << 2; 383 371 else 384 372 wx->tx_itr_setting = ec->tx_coalesce_usecs; 385 373 386 - if (wx->tx_itr_setting == 1) { 387 - switch (wx->mac.type) { 388 - case wx_mac_sp: 389 - case wx_mac_aml: 390 - case wx_mac_aml40: 391 - tx_itr_param = WX_12K_ITR; 392 - break; 393 - default: 394 - tx_itr_param = WX_20K_ITR; 395 - break; 396 - } 397 - } else { 398 - tx_itr_param = wx->tx_itr_setting; 374 + if (wx->adaptive_itr) { 375 + wx->adaptive_itr = false; 376 + wx->rx_itr_setting = rx_itr_param; 377 + wx->tx_itr_setting = tx_itr_param; 378 + } else if (wx->rx_itr_setting == 1 || wx->tx_itr_setting == 1) { 379 + wx->adaptive_itr = true; 399 380 } 381 + 382 + if (wx->rx_itr_setting != 1) 383 + rx_itr_param = wx->rx_itr_setting; 384 + 385 + if (wx->tx_itr_setting != 1) 386 + tx_itr_param = wx->tx_itr_setting; 400 387 401 388 /* mixed Rx/Tx */ 402 389 if (wx->q_vector[0]->tx.count && wx->q_vector[0]->rx.count)
+102 -1
drivers/net/ethernet/wangxun/libwx/wx_lib.c
··· 16 16 #include "wx_lib.h" 17 17 #include "wx_ptp.h" 18 18 #include "wx_hw.h" 19 + #include "wx_vf_lib.h" 19 20 20 21 /* Lookup table mapping the HW PTYPE to the bit field for decoding */ 21 22 static struct wx_dec_ptype wx_ptype_lookup[256] = { ··· 833 832 return !!budget; 834 833 } 835 834 835 + static void wx_update_rx_dim_sample(struct wx_q_vector *q_vector) 836 + { 837 + struct dim_sample sample = {}; 838 + 839 + dim_update_sample(q_vector->total_events, 840 + q_vector->rx.total_packets, 841 + q_vector->rx.total_bytes, 842 + &sample); 843 + 844 + net_dim(&q_vector->rx.dim, &sample); 845 + } 846 + 847 + static void wx_update_tx_dim_sample(struct wx_q_vector *q_vector) 848 + { 849 + struct dim_sample sample = {}; 850 + 851 + dim_update_sample(q_vector->total_events, 852 + q_vector->tx.total_packets, 853 + q_vector->tx.total_bytes, 854 + &sample); 855 + 856 + net_dim(&q_vector->tx.dim, &sample); 857 + } 858 + 859 + static void wx_update_dim_sample(struct wx_q_vector *q_vector) 860 + { 861 + wx_update_rx_dim_sample(q_vector); 862 + wx_update_tx_dim_sample(q_vector); 863 + } 864 + 836 865 /** 837 866 * wx_poll - NAPI polling RX/TX cleanup routine 838 867 * @napi: napi struct with our devices info in it ··· 909 878 910 879 /* all work done, exit the polling mode */ 911 880 if (likely(napi_complete_done(napi, work_done))) { 881 + if (wx->adaptive_itr) 882 + wx_update_dim_sample(q_vector); 912 883 if (netif_running(wx->netdev)) 913 884 wx_intr_enable(wx, WX_INTR_Q(q_vector->v_idx)); 914 885 } ··· 1624 1591 } 1625 1592 EXPORT_SYMBOL(wx_xmit_frame); 1626 1593 1594 + static void wx_set_itr(struct wx_q_vector *q_vector) 1595 + { 1596 + struct wx *wx = q_vector->wx; 1597 + u32 new_itr; 1598 + 1599 + if (!wx->adaptive_itr) 1600 + return; 1601 + 1602 + /* use the smallest value of new ITR delay calculations */ 1603 + new_itr = min(q_vector->rx.itr, q_vector->tx.itr); 1604 + new_itr <<= 2; 1605 + 1606 + if (new_itr != q_vector->itr) { 1607 + /* save the algorithm value here */ 1608 + q_vector->itr = new_itr; 1609 + 1610 + if (wx->pdev->is_virtfn) 1611 + wx_write_eitr_vf(q_vector); 1612 + else 1613 + wx_write_eitr(q_vector); 1614 + } 1615 + } 1616 + 1617 + static void wx_rx_dim_work(struct work_struct *work) 1618 + { 1619 + struct dim *dim = container_of(work, struct dim, work); 1620 + struct dim_cq_moder rx_moder; 1621 + struct wx_ring_container *rx; 1622 + struct wx_q_vector *q_vector; 1623 + 1624 + rx = container_of(dim, struct wx_ring_container, dim); 1625 + 1626 + rx_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); 1627 + rx->itr = rx_moder.usec; 1628 + 1629 + q_vector = container_of(rx, struct wx_q_vector, rx); 1630 + wx_set_itr(q_vector); 1631 + 1632 + dim->state = DIM_START_MEASURE; 1633 + } 1634 + 1635 + static void wx_tx_dim_work(struct work_struct *work) 1636 + { 1637 + struct dim *dim = container_of(work, struct dim, work); 1638 + struct dim_cq_moder tx_moder; 1639 + struct wx_ring_container *tx; 1640 + struct wx_q_vector *q_vector; 1641 + 1642 + tx = container_of(dim, struct wx_ring_container, dim); 1643 + 1644 + tx_moder = net_dim_get_tx_moderation(dim->mode, dim->profile_ix); 1645 + tx->itr = tx_moder.usec; 1646 + 1647 + q_vector = container_of(tx, struct wx_q_vector, tx); 1648 + wx_set_itr(q_vector); 1649 + 1650 + dim->state = DIM_START_MEASURE; 1651 + } 1652 + 1627 1653 void wx_napi_enable_all(struct wx *wx) 1628 1654 { 1629 1655 struct wx_q_vector *q_vector; ··· 1690 1598 1691 1599 for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) { 1692 1600 q_vector = wx->q_vector[q_idx]; 1601 + 1602 + INIT_WORK(&q_vector->rx.dim.work, wx_rx_dim_work); 1603 + INIT_WORK(&q_vector->tx.dim.work, wx_tx_dim_work); 1604 + q_vector->rx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; 1605 + q_vector->tx.dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; 1693 1606 napi_enable(&q_vector->napi); 1694 1607 } 1695 1608 } ··· 1708 1611 for (q_idx = 0; q_idx < wx->num_q_vectors; q_idx++) { 1709 1612 q_vector = wx->q_vector[q_idx]; 1710 1613 napi_disable(&q_vector->napi); 1614 + disable_work_sync(&q_vector->rx.dim.work); 1615 + disable_work_sync(&q_vector->tx.dim.work); 1711 1616 } 1712 1617 } 1713 1618 EXPORT_SYMBOL(wx_napi_disable_all); ··· 2296 2197 struct wx_q_vector *q_vector = data; 2297 2198 2298 2199 /* EIAM disabled interrupts (on this vector) for us */ 2299 - if (q_vector->rx.ring || q_vector->tx.ring) 2200 + if (q_vector->rx.ring || q_vector->tx.ring) { 2300 2201 napi_schedule_irqoff(&q_vector->napi); 2202 + q_vector->total_events++; 2203 + } 2301 2204 2302 2205 return IRQ_HANDLED; 2303 2206 }
+5
drivers/net/ethernet/wangxun/libwx/wx_type.h
··· 10 10 #include <linux/netdevice.h> 11 11 #include <linux/if_vlan.h> 12 12 #include <linux/phylink.h> 13 + #include <linux/dim.h> 13 14 #include <net/ip.h> 14 15 15 16 #define WX_NCSI_SUP 0x8000 ··· 1034 1033 unsigned int total_packets; /* total packets processed this int */ 1035 1034 u8 count; /* total number of rings in vector */ 1036 1035 u8 itr; /* current ITR setting for ring */ 1036 + struct dim dim; /* data for net_dim algorithm */ 1037 1037 }; 1038 1038 struct wx_ring { 1039 1039 struct wx_ring *next; /* pointer to next ring in q_vector */ ··· 1090 1088 struct wx_ring_container rx, tx; 1091 1089 struct napi_struct napi; 1092 1090 struct rcu_head rcu; /* to avoid race with update stats on free */ 1091 + 1092 + u16 total_events; /* number of interrupts processed */ 1093 1093 1094 1094 char name[IFNAMSIZ + 17]; 1095 1095 ··· 1272 1268 int num_rx_queues; 1273 1269 u16 rx_itr_setting; 1274 1270 u16 rx_work_limit; 1271 + bool adaptive_itr; 1275 1272 1276 1273 int num_q_vectors; /* current number of q_vectors for device */ 1277 1274 int max_q_vectors; /* upper limit of q_vectors for device */
+1 -1
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
··· 10 10 #include "wx_vf.h" 11 11 #include "wx_vf_lib.h" 12 12 13 - static void wx_write_eitr_vf(struct wx_q_vector *q_vector) 13 + void wx_write_eitr_vf(struct wx_q_vector *q_vector) 14 14 { 15 15 struct wx *wx = q_vector->wx; 16 16 int v_idx = q_vector->v_idx;
+1
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.h
··· 4 4 #ifndef _WX_VF_LIB_H_ 5 5 #define _WX_VF_LIB_H_ 6 6 7 + void wx_write_eitr_vf(struct wx_q_vector *q_vector); 7 8 void wx_configure_msix_vf(struct wx *wx); 8 9 int wx_write_uc_addr_list_vf(struct net_device *netdev); 9 10 void wx_setup_psrtype_vf(struct wx *wx);
+2 -1
drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
··· 115 115 116 116 static const struct ethtool_ops ngbe_ethtool_ops = { 117 117 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 118 - ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ, 118 + ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ | 119 + ETHTOOL_COALESCE_USE_ADAPTIVE, 119 120 .get_drvinfo = wx_get_drvinfo, 120 121 .get_link = ethtool_op_get_link, 121 122 .get_link_ksettings = wx_get_link_ksettings,
+3 -3
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
··· 119 119 num_online_cpus()); 120 120 wx->rss_enabled = true; 121 121 122 - /* enable itr by default in dynamic mode */ 123 - wx->rx_itr_setting = 1; 124 - wx->tx_itr_setting = 1; 122 + wx->adaptive_itr = false; 123 + wx->rx_itr_setting = WX_7K_ITR; 124 + wx->tx_itr_setting = WX_7K_ITR; 125 125 126 126 /* set default ring sizes */ 127 127 wx->tx_ring_count = NGBE_DEFAULT_TXD;
+1
drivers/net/ethernet/wangxun/ngbevf/ngbevf_main.c
··· 100 100 wx->mac.max_tx_queues = NGBEVF_MAX_TX_QUEUES; 101 101 wx->mac.max_rx_queues = NGBEVF_MAX_RX_QUEUES; 102 102 /* Enable dynamic interrupt throttling rates */ 103 + wx->adaptive_itr = true; 103 104 wx->rx_itr_setting = 1; 104 105 wx->tx_itr_setting = 1; 105 106 /* set default ring sizes */
+2 -1
drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
··· 538 538 539 539 static const struct ethtool_ops txgbe_ethtool_ops = { 540 540 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 541 - ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ, 541 + ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ | 542 + ETHTOOL_COALESCE_USE_ADAPTIVE, 542 543 .get_drvinfo = wx_get_drvinfo, 543 544 .nway_reset = wx_nway_reset, 544 545 .get_link = ethtool_op_get_link,
+1
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
··· 401 401 set_bit(WX_FLAG_MULTI_64_FUNC, wx->flags); 402 402 403 403 /* enable itr by default in dynamic mode */ 404 + wx->adaptive_itr = true; 404 405 wx->rx_itr_setting = 1; 405 406 wx->tx_itr_setting = 1; 406 407
+1
drivers/net/ethernet/wangxun/txgbevf/txgbevf_main.c
··· 144 144 wx->mac.max_tx_queues = TXGBEVF_MAX_TX_QUEUES; 145 145 wx->mac.max_rx_queues = TXGBEVF_MAX_RX_QUEUES; 146 146 /* Enable dynamic interrupt throttling rates */ 147 + wx->adaptive_itr = true; 147 148 wx->rx_itr_setting = 1; 148 149 wx->tx_itr_setting = 1; 149 150 /* set default ring sizes */