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 'convert-3-drivers-to-ndo_hwtstamp-api'

Vadim Fedorenko says:

====================
convert 3 drivers to ndo_hwtstamp API

Convert tg3, bnxt_en and mlx5 to use ndo_hwtstamp API. These 3 drivers
were chosen because I have access to the HW and is able to test the
changes. Also there is a selftest provided to validated that the driver
correctly sets up timestamp configuration, according to what is exposed
as supported by the hardware. Selftest allows driver to fallback to some
wider scope of RX timestamping, i.e. it allows the driver to set up
ptpv2-event filter when ptpv2-l2-event is requested.
====================

Link: https://patch.msgid.link/20250923173310.139623-1-vadim.fedorenko@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+166 -64
+2 -6
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 13278 13278 return bnxt_hwrm_port_phy_write(bp, mdio->phy_id, mdio->reg_num, 13279 13279 mdio->val_in); 13280 13280 13281 - case SIOCSHWTSTAMP: 13282 - return bnxt_hwtstamp_set(dev, ifr); 13283 - 13284 - case SIOCGHWTSTAMP: 13285 - return bnxt_hwtstamp_get(dev, ifr); 13286 - 13287 13281 default: 13288 13282 /* do nothing */ 13289 13283 break; ··· 15800 15806 .ndo_xdp_xmit = bnxt_xdp_xmit, 15801 15807 .ndo_bridge_getlink = bnxt_bridge_getlink, 15802 15808 .ndo_bridge_setlink = bnxt_bridge_setlink, 15809 + .ndo_hwtstamp_get = bnxt_hwtstamp_get, 15810 + .ndo_hwtstamp_set = bnxt_hwtstamp_set, 15803 15811 }; 15804 15812 15805 15813 static void bnxt_get_queue_stats_rx(struct net_device *dev, int i,
+16 -19
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
··· 560 560 return bnxt_ptp_cfg_tstamp_filters(bp); 561 561 } 562 562 563 - int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) 563 + int bnxt_hwtstamp_set(struct net_device *dev, 564 + struct kernel_hwtstamp_config *stmpconf, 565 + struct netlink_ext_ack *extack) 564 566 { 565 567 struct bnxt *bp = netdev_priv(dev); 566 - struct hwtstamp_config stmpconf; 567 568 struct bnxt_ptp_cfg *ptp; 568 569 u16 old_rxctl; 569 570 int old_rx_filter, rc; ··· 574 573 if (!ptp) 575 574 return -EOPNOTSUPP; 576 575 577 - if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) 578 - return -EFAULT; 579 - 580 - if (stmpconf.tx_type != HWTSTAMP_TX_ON && 581 - stmpconf.tx_type != HWTSTAMP_TX_OFF) 576 + if (stmpconf->tx_type != HWTSTAMP_TX_ON && 577 + stmpconf->tx_type != HWTSTAMP_TX_OFF) 582 578 return -ERANGE; 583 579 584 580 old_rx_filter = ptp->rx_filter; 585 581 old_rxctl = ptp->rxctl; 586 582 old_tx_tstamp_en = ptp->tx_tstamp_en; 587 - switch (stmpconf.rx_filter) { 583 + switch (stmpconf->rx_filter) { 588 584 case HWTSTAMP_FILTER_NONE: 589 585 ptp->rxctl = 0; 590 586 ptp->rx_filter = HWTSTAMP_FILTER_NONE; ··· 614 616 return -ERANGE; 615 617 } 616 618 617 - if (stmpconf.tx_type == HWTSTAMP_TX_ON) 619 + if (stmpconf->tx_type == HWTSTAMP_TX_ON) 618 620 ptp->tx_tstamp_en = 1; 619 621 else 620 622 ptp->tx_tstamp_en = 0; ··· 623 625 if (rc) 624 626 goto ts_set_err; 625 627 626 - stmpconf.rx_filter = ptp->rx_filter; 627 - return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 628 - -EFAULT : 0; 628 + stmpconf->rx_filter = ptp->rx_filter; 629 + return 0; 629 630 630 631 ts_set_err: 631 632 ptp->rx_filter = old_rx_filter; ··· 633 636 return rc; 634 637 } 635 638 636 - int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) 639 + int bnxt_hwtstamp_get(struct net_device *dev, 640 + struct kernel_hwtstamp_config *stmpconf) 637 641 { 638 642 struct bnxt *bp = netdev_priv(dev); 639 - struct hwtstamp_config stmpconf; 640 643 struct bnxt_ptp_cfg *ptp; 641 644 642 645 ptp = bp->ptp_cfg; 643 646 if (!ptp) 644 647 return -EOPNOTSUPP; 645 648 646 - stmpconf.flags = 0; 647 - stmpconf.tx_type = ptp->tx_tstamp_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; 649 + stmpconf->flags = 0; 650 + stmpconf->tx_type = ptp->tx_tstamp_en ? HWTSTAMP_TX_ON 651 + : HWTSTAMP_TX_OFF; 648 652 649 - stmpconf.rx_filter = ptp->rx_filter; 650 - return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 651 - -EFAULT : 0; 653 + stmpconf->rx_filter = ptp->rx_filter; 654 + return 0; 652 655 } 653 656 654 657 static int bnxt_map_regs(struct bnxt *bp, u32 *reg_arr, int count, int reg_win)
+5 -2
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
··· 160 160 void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2); 161 161 int bnxt_ptp_cfg_tstamp_filters(struct bnxt *bp); 162 162 void bnxt_ptp_reapply_pps(struct bnxt *bp); 163 - int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr); 164 - int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr); 163 + int bnxt_hwtstamp_set(struct net_device *dev, 164 + struct kernel_hwtstamp_config *stmpconf, 165 + struct netlink_ext_ack *extack); 166 + int bnxt_hwtstamp_get(struct net_device *dev, 167 + struct kernel_hwtstamp_config *stmpconf); 165 168 void bnxt_ptp_free_txts_skbs(struct bnxt_ptp_cfg *ptp); 166 169 int bnxt_ptp_get_txts_prod(struct bnxt_ptp_cfg *ptp, u16 *prod); 167 170 void bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb, u16 prod);
+29 -37
drivers/net/ethernet/broadcom/tg3.c
··· 13929 13929 13930 13930 } 13931 13931 13932 - static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) 13932 + static int tg3_hwtstamp_set(struct net_device *dev, 13933 + struct kernel_hwtstamp_config *stmpconf, 13934 + struct netlink_ext_ack *extack) 13933 13935 { 13934 13936 struct tg3 *tp = netdev_priv(dev); 13935 - struct hwtstamp_config stmpconf; 13936 13937 13937 13938 if (!tg3_flag(tp, PTP_CAPABLE)) 13938 13939 return -EOPNOTSUPP; 13939 13940 13940 - if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf))) 13941 - return -EFAULT; 13942 - 13943 - if (stmpconf.tx_type != HWTSTAMP_TX_ON && 13944 - stmpconf.tx_type != HWTSTAMP_TX_OFF) 13941 + if (stmpconf->tx_type != HWTSTAMP_TX_ON && 13942 + stmpconf->tx_type != HWTSTAMP_TX_OFF) 13945 13943 return -ERANGE; 13946 13944 13947 - switch (stmpconf.rx_filter) { 13945 + switch (stmpconf->rx_filter) { 13948 13946 case HWTSTAMP_FILTER_NONE: 13949 13947 tp->rxptpctl = 0; 13950 13948 break; ··· 14002 14004 tw32(TG3_RX_PTP_CTL, 14003 14005 tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK); 14004 14006 14005 - if (stmpconf.tx_type == HWTSTAMP_TX_ON) 14007 + if (stmpconf->tx_type == HWTSTAMP_TX_ON) 14006 14008 tg3_flag_set(tp, TX_TSTAMP_EN); 14007 14009 else 14008 14010 tg3_flag_clear(tp, TX_TSTAMP_EN); 14009 14011 14010 - return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 14011 - -EFAULT : 0; 14012 + return 0; 14012 14013 } 14013 14014 14014 - static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) 14015 + static int tg3_hwtstamp_get(struct net_device *dev, 14016 + struct kernel_hwtstamp_config *stmpconf) 14015 14017 { 14016 14018 struct tg3 *tp = netdev_priv(dev); 14017 - struct hwtstamp_config stmpconf; 14018 14019 14019 14020 if (!tg3_flag(tp, PTP_CAPABLE)) 14020 14021 return -EOPNOTSUPP; 14021 14022 14022 - stmpconf.flags = 0; 14023 - stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ? 14024 - HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF); 14023 + stmpconf->flags = 0; 14024 + stmpconf->tx_type = tg3_flag(tp, TX_TSTAMP_EN) ? 14025 + HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; 14025 14026 14026 14027 switch (tp->rxptpctl) { 14027 14028 case 0: 14028 - stmpconf.rx_filter = HWTSTAMP_FILTER_NONE; 14029 + stmpconf->rx_filter = HWTSTAMP_FILTER_NONE; 14029 14030 break; 14030 14031 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS: 14031 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 14032 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 14032 14033 break; 14033 14034 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT: 14034 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 14035 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 14035 14036 break; 14036 14037 case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ: 14037 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 14038 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 14038 14039 break; 14039 14040 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: 14040 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 14041 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 14041 14042 break; 14042 14043 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: 14043 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 14044 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 14044 14045 break; 14045 14046 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS: 14046 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 14047 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 14047 14048 break; 14048 14049 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: 14049 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 14050 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 14050 14051 break; 14051 14052 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT: 14052 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; 14053 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC; 14053 14054 break; 14054 14055 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT: 14055 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 14056 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 14056 14057 break; 14057 14058 case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ: 14058 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 14059 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 14059 14060 break; 14060 14061 case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ: 14061 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; 14062 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ; 14062 14063 break; 14063 14064 case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ: 14064 - stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 14065 + stmpconf->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 14065 14066 break; 14066 14067 default: 14067 14068 WARN_ON_ONCE(1); 14068 14069 return -ERANGE; 14069 14070 } 14070 14071 14071 - return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ? 14072 - -EFAULT : 0; 14072 + return 0; 14073 14073 } 14074 14074 14075 14075 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ··· 14121 14125 spin_unlock_bh(&tp->lock); 14122 14126 14123 14127 return err; 14124 - 14125 - case SIOCSHWTSTAMP: 14126 - return tg3_hwtstamp_set(dev, ifr); 14127 - 14128 - case SIOCGHWTSTAMP: 14129 - return tg3_hwtstamp_get(dev, ifr); 14130 14128 14131 14129 default: 14132 14130 /* do nothing */ ··· 14397 14407 #ifdef CONFIG_NET_POLL_CONTROLLER 14398 14408 .ndo_poll_controller = tg3_poll_controller, 14399 14409 #endif 14410 + .ndo_hwtstamp_get = tg3_hwtstamp_get, 14411 + .ndo_hwtstamp_set = tg3_hwtstamp_set, 14400 14412 }; 14401 14413 14402 14414 static void tg3_get_eeprom_size(struct tg3 *tp)
+1
tools/testing/selftests/drivers/net/hw/Makefile
··· 15 15 iou-zcrx.py \ 16 16 irq.py \ 17 17 loopback.sh \ 18 + nic_timestamp.py \ 18 19 pp_alloc_fail.py \ 19 20 rss_api.py \ 20 21 rss_ctx.py \
+113
tools/testing/selftests/drivers/net/hw/nic_timestamp.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + """ 5 + Tests related to configuration of HW timestamping 6 + """ 7 + 8 + import errno 9 + from lib.py import ksft_run, ksft_exit, ksft_ge, ksft_eq, KsftSkipEx 10 + from lib.py import NetDrvEnv, EthtoolFamily, NlError 11 + 12 + 13 + def __get_hwtimestamp_support(cfg): 14 + """ Retrieve supported configuration information """ 15 + 16 + try: 17 + tsinfo = cfg.ethnl.tsinfo_get({'header': {'dev-name': cfg.ifname}}) 18 + except NlError as e: 19 + if e.error == errno.EOPNOTSUPP: 20 + raise KsftSkipEx("timestamping configuration is not supported") from e 21 + raise 22 + 23 + ctx = {} 24 + tx = tsinfo.get('tx-types', {}) 25 + rx = tsinfo.get('rx-filters', {}) 26 + 27 + bits = tx.get('bits', {}) 28 + ctx['tx'] = bits.get('bit', []) 29 + bits = rx.get('bits', {}) 30 + ctx['rx'] = bits.get('bit', []) 31 + return ctx 32 + 33 + 34 + def __get_hwtimestamp_config(cfg): 35 + """ Retrieve current TS configuration information """ 36 + 37 + try: 38 + tscfg = cfg.ethnl.tsconfig_get({'header': {'dev-name': cfg.ifname}}) 39 + except NlError as e: 40 + if e.error == errno.EOPNOTSUPP: 41 + raise KsftSkipEx("timestamping configuration is not supported via netlink") from e 42 + raise 43 + return tscfg 44 + 45 + 46 + def __set_hwtimestamp_config(cfg, ts): 47 + """ Setup new TS configuration information """ 48 + 49 + ts['header'] = {'dev-name': cfg.ifname} 50 + try: 51 + res = cfg.ethnl.tsconfig_set(ts) 52 + except NlError as e: 53 + if e.error == errno.EOPNOTSUPP: 54 + raise KsftSkipEx("timestamping configuration is not supported via netlink") from e 55 + raise 56 + return res 57 + 58 + 59 + def test_hwtstamp_tx(cfg): 60 + """ 61 + Test TX timestamp configuration. 62 + The driver should apply provided config and report back proper state. 63 + """ 64 + 65 + orig_tscfg = __get_hwtimestamp_config(cfg) 66 + ts = __get_hwtimestamp_support(cfg) 67 + tx = ts['tx'] 68 + for t in tx: 69 + tscfg = orig_tscfg 70 + tscfg['tx-types']['bits']['bit'] = [t] 71 + res = __set_hwtimestamp_config(cfg, tscfg) 72 + if res is None: 73 + res = __get_hwtimestamp_config(cfg) 74 + ksft_eq(res['tx-types']['bits']['bit'], [t]) 75 + __set_hwtimestamp_config(cfg, orig_tscfg) 76 + 77 + 78 + def test_hwtstamp_rx(cfg): 79 + """ 80 + Test RX timestamp configuration. 81 + The filter configuration is taken from the list of supported filters. 82 + The driver should apply the config without error and report back proper state. 83 + Some extension of the timestamping scope is allowed for PTP filters. 84 + """ 85 + 86 + orig_tscfg = __get_hwtimestamp_config(cfg) 87 + ts = __get_hwtimestamp_support(cfg) 88 + rx = ts['rx'] 89 + for r in rx: 90 + tscfg = orig_tscfg 91 + tscfg['rx-filters']['bits']['bit'] = [r] 92 + res = __set_hwtimestamp_config(cfg, tscfg) 93 + if res is None: 94 + res = __get_hwtimestamp_config(cfg) 95 + if r['index'] == 0 or r['index'] == 1: 96 + ksft_eq(res['rx-filters']['bits']['bit'][0]['index'], r['index']) 97 + else: 98 + # the driver can fallback to some value which has higher coverage for timestamping 99 + ksft_ge(res['rx-filters']['bits']['bit'][0]['index'], r['index']) 100 + __set_hwtimestamp_config(cfg, orig_tscfg) 101 + 102 + 103 + def main() -> None: 104 + """ Ksft boiler plate main """ 105 + 106 + with NetDrvEnv(__file__, nsim_test=False) as cfg: 107 + cfg.ethnl = EthtoolFamily() 108 + ksft_run([test_hwtstamp_tx, test_hwtstamp_rx], args=(cfg,)) 109 + ksft_exit() 110 + 111 + 112 + if __name__ == "__main__": 113 + main()