Skip to content

Commit b9e3f7d

Browse files
kmaincentdavem330
authored andcommitted
net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology
Either the MAC or the PHY can provide hwtstamp, so we should be able to read the tsinfo for any hwtstamp provider. Enhance 'get' command to retrieve tsinfo of hwtstamp providers within a network topology. Add support for a specific dump command to retrieve all hwtstamp providers within the network topology, with added functionality for filtered dump to target a single interface. Signed-off-by: Kory Maincent <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 35f7cad commit b9e3f7d

File tree

10 files changed

+563
-21
lines changed

10 files changed

+563
-21
lines changed

Documentation/netlink/specs/ethtool.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,20 @@ attribute-sets:
836836
-
837837
name: tx-err
838838
type: uint
839+
-
840+
name: ts-hwtstamp-provider
841+
attr-cnt-name: __ethtool-a-ts-hwtstamp-provider-cnt
842+
attributes:
843+
-
844+
name: unspec
845+
type: unused
846+
value: 0
847+
-
848+
name: index
849+
type: u32
850+
-
851+
name: qualifier
852+
type: u32
839853
-
840854
name: tsinfo
841855
attr-cnt-name: __ethtool-a-tsinfo-cnt
@@ -867,6 +881,10 @@ attribute-sets:
867881
name: stats
868882
type: nest
869883
nested-attributes: ts-stat
884+
-
885+
name: hwtstamp-provider
886+
type: nest
887+
nested-attributes: ts-hwtstamp-provider
870888
-
871889
name: cable-result
872890
attr-cnt-name: __ethtool-a-cable-result-cnt
@@ -1912,6 +1930,7 @@ operations:
19121930
request:
19131931
attributes:
19141932
- header
1933+
- hwtstamp-provider
19151934
reply:
19161935
attributes:
19171936
- header
@@ -1920,6 +1939,7 @@ operations:
19201939
- rx-filters
19211940
- phc-index
19221941
- stats
1942+
- hwtstamp-provider
19231943
dump: *tsinfo-get-op
19241944
-
19251945
name: cable-test-act

Documentation/networking/ethtool-netlink.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,9 +1245,10 @@ Gets timestamping information like ``ETHTOOL_GET_TS_INFO`` ioctl request.
12451245

12461246
Request contents:
12471247

1248-
===================================== ====== ==========================
1249-
``ETHTOOL_A_TSINFO_HEADER`` nested request header
1250-
===================================== ====== ==========================
1248+
======================================== ====== ============================
1249+
``ETHTOOL_A_TSINFO_HEADER`` nested request header
1250+
``ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
1251+
======================================== ====== ============================
12511252

12521253
Kernel response contents:
12531254

include/linux/ethtool.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,13 +711,15 @@ struct ethtool_rxfh_param {
711711
* @cmd: command number = %ETHTOOL_GET_TS_INFO
712712
* @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags
713713
* @phc_index: device index of the associated PHC, or -1 if there is none
714+
* @phc_qualifier: qualifier of the associated PHC
714715
* @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
715716
* @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
716717
*/
717718
struct kernel_ethtool_ts_info {
718719
u32 cmd;
719720
u32 so_timestamping;
720721
int phc_index;
722+
enum hwtstamp_provider_qualifier phc_qualifier;
721723
enum hwtstamp_tx_types tx_types;
722724
enum hwtstamp_rx_filters rx_filters;
723725
};
@@ -749,6 +751,7 @@ struct kernel_ethtool_ts_info {
749751
* @rss_context argument to @create_rxfh_context and friends.
750752
* @supported_coalesce_params: supported types of interrupt coalescing.
751753
* @supported_ring_params: supported ring params.
754+
* @supported_hwtstamp_qualifiers: bitfield of supported hwtstamp qualifier.
752755
* @get_drvinfo: Report driver/device information. Modern drivers no
753756
* longer have to implement this callback. Most fields are
754757
* correctly filled in by the core using system information, or
@@ -966,6 +969,7 @@ struct ethtool_ops {
966969
u32 rxfh_max_num_contexts;
967970
u32 supported_coalesce_params;
968971
u32 supported_ring_params;
972+
u32 supported_hwtstamp_qualifiers;
969973
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
970974
int (*get_regs_len)(struct net_device *);
971975
void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);

include/uapi/linux/ethtool_netlink_generated.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,15 @@ enum {
385385
ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
386386
};
387387

388+
enum {
389+
ETHTOOL_A_TS_HWTSTAMP_PROVIDER_UNSPEC,
390+
ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX,
391+
ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER,
392+
393+
__ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT,
394+
ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX = (__ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT - 1)
395+
};
396+
388397
enum {
389398
ETHTOOL_A_TSINFO_UNSPEC,
390399
ETHTOOL_A_TSINFO_HEADER,
@@ -393,6 +402,7 @@ enum {
393402
ETHTOOL_A_TSINFO_RX_FILTERS,
394403
ETHTOOL_A_TSINFO_PHC_INDEX,
395404
ETHTOOL_A_TSINFO_STATS,
405+
ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER,
396406

397407
__ETHTOOL_A_TSINFO_CNT,
398408
ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)

net/ethtool/common.c

Lines changed: 132 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
#include <linux/phy.h>
66
#include <linux/rtnetlink.h>
77
#include <linux/ptp_clock_kernel.h>
8+
#include <linux/phy_link_topology.h>
89

910
#include "netlink.h"
1011
#include "common.h"
12+
#include "../core/dev.h"
13+
1114

1215
const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
1316
[NETIF_F_SG_BIT] = "tx-scatter-gather",
@@ -763,27 +766,147 @@ int ethtool_check_ops(const struct ethtool_ops *ops)
763766
return 0;
764767
}
765768

766-
int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info)
769+
static void ethtool_init_tsinfo(struct kernel_ethtool_ts_info *info)
767770
{
768-
const struct ethtool_ops *ops = dev->ethtool_ops;
769-
struct phy_device *phydev = dev->phydev;
770-
int err = 0;
771-
772771
memset(info, 0, sizeof(*info));
773772
info->cmd = ETHTOOL_GET_TS_INFO;
774773
info->phc_index = -1;
774+
}
775+
776+
int ethtool_net_get_ts_info_by_phc(struct net_device *dev,
777+
struct kernel_ethtool_ts_info *info,
778+
struct hwtstamp_provider_desc *hwprov_desc)
779+
{
780+
const struct ethtool_ops *ops = dev->ethtool_ops;
781+
int err;
782+
783+
if (!ops->get_ts_info)
784+
return -ENODEV;
785+
786+
/* Does ptp comes from netdev */
787+
ethtool_init_tsinfo(info);
788+
info->phc_qualifier = hwprov_desc->qualifier;
789+
err = ops->get_ts_info(dev, info);
790+
if (err)
791+
return err;
792+
793+
if (info->phc_index == hwprov_desc->index &&
794+
net_support_hwtstamp_qualifier(dev, hwprov_desc->qualifier))
795+
return 0;
796+
797+
return -ENODEV;
798+
}
799+
800+
int
801+
ethtool_phy_get_ts_info_by_phc(struct net_device *dev,
802+
struct kernel_ethtool_ts_info *info,
803+
struct hwtstamp_provider_desc *hwprov_desc)
804+
{
805+
int err;
806+
807+
/* Only precise qualifier is supported in phydev */
808+
if (hwprov_desc->qualifier != HWTSTAMP_PROVIDER_QUALIFIER_PRECISE)
809+
return -ENODEV;
810+
811+
/* Look in the phy topology */
812+
if (dev->link_topo) {
813+
struct phy_device_node *pdn;
814+
unsigned long phy_index;
815+
816+
xa_for_each(&dev->link_topo->phys, phy_index, pdn) {
817+
if (!phy_has_tsinfo(pdn->phy))
818+
continue;
819+
820+
ethtool_init_tsinfo(info);
821+
err = phy_ts_info(pdn->phy, info);
822+
if (err)
823+
return err;
824+
825+
if (info->phc_index == hwprov_desc->index)
826+
return 0;
827+
}
828+
return -ENODEV;
829+
}
830+
831+
/* Look on the dev->phydev */
832+
if (phy_has_tsinfo(dev->phydev)) {
833+
ethtool_init_tsinfo(info);
834+
err = phy_ts_info(dev->phydev, info);
835+
if (err)
836+
return err;
837+
838+
if (info->phc_index == hwprov_desc->index)
839+
return 0;
840+
}
841+
842+
return -ENODEV;
843+
}
844+
845+
int ethtool_get_ts_info_by_phc(struct net_device *dev,
846+
struct kernel_ethtool_ts_info *info,
847+
struct hwtstamp_provider_desc *hwprov_desc)
848+
{
849+
int err;
775850

776-
if (phy_is_default_hwtstamp(phydev) && phy_has_tsinfo(phydev))
777-
err = phy_ts_info(phydev, info);
778-
else if (ops->get_ts_info)
779-
err = ops->get_ts_info(dev, info);
851+
err = ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc);
852+
if (err == -ENODEV)
853+
err = ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc);
780854

781855
info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE |
782856
SOF_TIMESTAMPING_SOFTWARE;
783857

784858
return err;
785859
}
786860

861+
int __ethtool_get_ts_info(struct net_device *dev,
862+
struct kernel_ethtool_ts_info *info)
863+
{
864+
struct hwtstamp_provider *hwprov;
865+
866+
hwprov = rtnl_dereference(dev->hwprov);
867+
/* No provider specified, use default behavior */
868+
if (!hwprov) {
869+
const struct ethtool_ops *ops = dev->ethtool_ops;
870+
struct phy_device *phydev = dev->phydev;
871+
int err = 0;
872+
873+
ethtool_init_tsinfo(info);
874+
if (phy_is_default_hwtstamp(phydev) &&
875+
phy_has_tsinfo(phydev))
876+
err = phy_ts_info(phydev, info);
877+
else if (ops->get_ts_info)
878+
err = ops->get_ts_info(dev, info);
879+
880+
info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE |
881+
SOF_TIMESTAMPING_SOFTWARE;
882+
883+
return err;
884+
}
885+
886+
return ethtool_get_ts_info_by_phc(dev, info, &hwprov->desc);
887+
}
888+
889+
bool net_support_hwtstamp_qualifier(struct net_device *dev,
890+
enum hwtstamp_provider_qualifier qualifier)
891+
{
892+
const struct ethtool_ops *ops = dev->ethtool_ops;
893+
894+
if (!ops)
895+
return false;
896+
897+
/* Return true with precise qualifier and with NIC without
898+
* qualifier description to not break the old behavior.
899+
*/
900+
if (!ops->supported_hwtstamp_qualifiers &&
901+
qualifier == HWTSTAMP_PROVIDER_QUALIFIER_PRECISE)
902+
return true;
903+
904+
if (ops->supported_hwtstamp_qualifiers & BIT(qualifier))
905+
return true;
906+
907+
return false;
908+
}
909+
787910
int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index)
788911
{
789912
struct kernel_ethtool_ts_info info = { };

net/ethtool/common.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct link_mode_info {
2121
};
2222

2323
struct genl_info;
24+
struct hwtstamp_provider_desc;
2425

2526
extern const char
2627
netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN];
@@ -49,6 +50,18 @@ int ethtool_check_max_channel(struct net_device *dev,
4950
struct genl_info *info);
5051
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context);
5152
int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info);
53+
int ethtool_get_ts_info_by_phc(struct net_device *dev,
54+
struct kernel_ethtool_ts_info *info,
55+
struct hwtstamp_provider_desc *hwprov_desc);
56+
int ethtool_net_get_ts_info_by_phc(struct net_device *dev,
57+
struct kernel_ethtool_ts_info *info,
58+
struct hwtstamp_provider_desc *hwprov_desc);
59+
int
60+
ethtool_phy_get_ts_info_by_phc(struct net_device *dev,
61+
struct kernel_ethtool_ts_info *info,
62+
struct hwtstamp_provider_desc *hwprov_desc);
63+
bool net_support_hwtstamp_qualifier(struct net_device *dev,
64+
enum hwtstamp_provider_qualifier qualifier);
5265

5366
extern const struct ethtool_phy_ops *ethtool_phy_ops;
5467
extern const struct ethtool_pse_ops *ethtool_pse_ops;

net/ethtool/netlink.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,9 +1074,9 @@ static const struct genl_ops ethtool_genl_ops[] = {
10741074
{
10751075
.cmd = ETHTOOL_MSG_TSINFO_GET,
10761076
.doit = ethnl_default_doit,
1077-
.start = ethnl_default_start,
1078-
.dumpit = ethnl_default_dumpit,
1079-
.done = ethnl_default_done,
1077+
.start = ethnl_tsinfo_start,
1078+
.dumpit = ethnl_tsinfo_dumpit,
1079+
.done = ethnl_tsinfo_done,
10801080
.policy = ethnl_tsinfo_get_policy,
10811081
.maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1,
10821082
},

net/ethtool/netlink.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_STATS_SRC
464464
extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
465465
extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
466466
extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1];
467-
extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1];
467+
extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1];
468468
extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1];
469469
extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1];
470470
extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1];
@@ -499,6 +499,9 @@ int ethnl_phy_start(struct netlink_callback *cb);
499499
int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
500500
int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
501501
int ethnl_phy_done(struct netlink_callback *cb);
502+
int ethnl_tsinfo_start(struct netlink_callback *cb);
503+
int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
504+
int ethnl_tsinfo_done(struct netlink_callback *cb);
502505

503506
extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
504507
extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];

net/ethtool/ts.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef _NET_ETHTOOL_TS_H
4+
#define _NET_ETHTOOL_TS_H
5+
6+
#include "netlink.h"
7+
8+
static const struct nla_policy
9+
ethnl_ts_hwtst_prov_policy[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX + 1] = {
10+
[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX] = { .type = NLA_U32 },
11+
[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER] =
12+
NLA_POLICY_MAX(NLA_U32, HWTSTAMP_PROVIDER_QUALIFIER_CNT - 1)
13+
};
14+
15+
int ts_parse_hwtst_provider(const struct nlattr *nest,
16+
struct hwtstamp_provider_desc *hwprov_desc,
17+
struct netlink_ext_ack *extack,
18+
bool *mod);
19+
20+
#endif /* _NET_ETHTOOL_TS_H */

0 commit comments

Comments
 (0)