]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ethtool: add a new command for getting PHC virtual clocks
authorYangbo Lu <yangbo.lu@nxp.com>
Wed, 30 Jun 2021 08:11:56 +0000 (16:11 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Jul 2021 20:08:18 +0000 (13:08 -0700)
Add an interface for getting PHC (PTP Hardware Clock)
virtual clocks, which are based on PHC physical clock
providing hardware timestamp to network packets.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ethtool-netlink.rst
include/linux/ethtool.h
include/uapi/linux/ethtool_netlink.h
net/ethtool/Makefile
net/ethtool/common.c
net/ethtool/netlink.c
net/ethtool/netlink.h
net/ethtool/phc_vclocks.c [new file with mode: 0644]

index 6ea91e41593f7c4c016a49046195c57a03c90b5d..c86628e6a235620c175a253504ae733f390e77f0 100644 (file)
@@ -212,6 +212,7 @@ Userspace to kernel:
   ``ETHTOOL_MSG_FEC_SET``               set FEC settings
   ``ETHTOOL_MSG_MODULE_EEPROM_GET``     read SFP module EEPROM
   ``ETHTOOL_MSG_STATS_GET``             get standard statistics
+  ``ETHTOOL_MSG_PHC_VCLOCKS_GET``       get PHC virtual clocks info
   ===================================== ================================
 
 Kernel to userspace:
@@ -250,6 +251,7 @@ Kernel to userspace:
   ``ETHTOOL_MSG_FEC_NTF``                  FEC settings
   ``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY``  read SFP module EEPROM
   ``ETHTOOL_MSG_STATS_GET_REPLY``          standard statistics
+  ``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY``    PHC virtual clocks info
   ======================================== =================================
 
 ``GET`` requests are sent by userspace applications to retrieve device
@@ -1477,6 +1479,25 @@ Low and high bounds are inclusive, for example:
  etherStatsPkts512to1023Octets 512  1023
  ============================= ==== ====
 
+PHC_VCLOCKS_GET
+===============
+
+Query device PHC virtual clocks information.
+
+Request contents:
+
+  ====================================  ======  ==========================
+  ``ETHTOOL_A_PHC_VCLOCKS_HEADER``      nested  request header
+  ====================================  ======  ==========================
+
+Kernel response contents:
+
+  ====================================  ======  ==========================
+  ``ETHTOOL_A_PHC_VCLOCKS_HEADER``      nested  reply header
+  ``ETHTOOL_A_PHC_VCLOCKS_NUM``         u32     PHC virtual clocks number
+  ``ETHTOOL_A_PHC_VCLOCKS_INDEX``       s32     PHC index array
+  ====================================  ======  ==========================
+
 Request translation
 ===================
 
@@ -1575,4 +1596,5 @@ are netlink only.
   n/a                                 ``ETHTOOL_MSG_CABLE_TEST_ACT``
   n/a                                 ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``
   n/a                                 ``ETHTOOL_MSG_TUNNEL_INFO_GET``
+  n/a                                 ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
   =================================== =====================================
index 29dbb603bc915e9b30b4f5d7cf6302140537c1f5..232daaec56e44b77849702fdf70d3b291ff7a790 100644 (file)
@@ -757,6 +757,16 @@ void
 ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
                              enum ethtool_link_mode_bit_indices link_mode);
 
+/**
+ * ethtool_get_phc_vclocks - Derive phc vclocks information, and caller
+ *                           is responsible to free memory of vclock_index
+ * @dev: pointer to net_device structure
+ * @vclock_index: pointer to pointer of vclock index
+ *
+ * Return number of phc vclocks
+ */
+int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index);
+
 /**
  * ethtool_sprintf - Write formatted string to ethtool string data
  * @data: Pointer to start of string to update
index c7135c9c37a5f16351c98421da99d547b84f4c1e..b3b93710eff70b9f89c6759e5ae818f5a3203176 100644 (file)
@@ -46,6 +46,7 @@ enum {
        ETHTOOL_MSG_FEC_SET,
        ETHTOOL_MSG_MODULE_EEPROM_GET,
        ETHTOOL_MSG_STATS_GET,
+       ETHTOOL_MSG_PHC_VCLOCKS_GET,
 
        /* add new constants above here */
        __ETHTOOL_MSG_USER_CNT,
@@ -88,6 +89,7 @@ enum {
        ETHTOOL_MSG_FEC_NTF,
        ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
        ETHTOOL_MSG_STATS_GET_REPLY,
+       ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
 
        /* add new constants above here */
        __ETHTOOL_MSG_KERNEL_CNT,
@@ -440,6 +442,19 @@ enum {
        ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
 };
 
+/* PHC VCLOCKS */
+
+enum {
+       ETHTOOL_A_PHC_VCLOCKS_UNSPEC,
+       ETHTOOL_A_PHC_VCLOCKS_HEADER,                   /* nest - _A_HEADER_* */
+       ETHTOOL_A_PHC_VCLOCKS_NUM,                      /* u32 */
+       ETHTOOL_A_PHC_VCLOCKS_INDEX,                    /* array, s32 */
+
+       /* add new constants above here */
+       __ETHTOOL_A_PHC_VCLOCKS_CNT,
+       ETHTOOL_A_PHC_VCLOCKS_MAX = (__ETHTOOL_A_PHC_VCLOCKS_CNT - 1)
+};
+
 /* CABLE TEST */
 
 enum {
index 723c9a8a8cdf1064478a4c9f73ef1b62ba743139..0a19470efbfb9ce4bd8769300dece981412edee1 100644 (file)
@@ -7,4 +7,4 @@ obj-$(CONFIG_ETHTOOL_NETLINK)   += ethtool_nl.o
 ethtool_nl-y   := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \
                   linkstate.o debug.o wol.o features.o privflags.o rings.o \
                   channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
-                  tunnels.o fec.o eeprom.o stats.o
+                  tunnels.o fec.o eeprom.o stats.o phc_vclocks.o
index f9dcbad84788b5417ff6ccf571be81231f863b4f..798231b076768668586f7ee877482d9110c7010d 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/rtnetlink.h>
+#include <linux/ptp_clock_kernel.h>
 
 #include "common.h"
 
@@ -554,6 +555,18 @@ int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
        return 0;
 }
 
+int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index)
+{
+       struct ethtool_ts_info info = { };
+       int num = 0;
+
+       if (!__ethtool_get_ts_info(dev, &info))
+               num = ptp_get_vclocks_index(info.phc_index, vclock_index);
+
+       return num;
+}
+EXPORT_SYMBOL(ethtool_get_phc_vclocks);
+
 const struct ethtool_phy_ops *ethtool_phy_ops;
 
 void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops)
index a7346346114f4aae8dd90576fee190794dbc2b54..73e0f5b626bfba4d5b575470a7e69a0039882ce8 100644 (file)
@@ -248,6 +248,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
        [ETHTOOL_MSG_TSINFO_GET]        = &ethnl_tsinfo_request_ops,
        [ETHTOOL_MSG_MODULE_EEPROM_GET] = &ethnl_module_eeprom_request_ops,
        [ETHTOOL_MSG_STATS_GET]         = &ethnl_stats_request_ops,
+       [ETHTOOL_MSG_PHC_VCLOCKS_GET]   = &ethnl_phc_vclocks_request_ops,
 };
 
 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -958,6 +959,15 @@ static const struct genl_ops ethtool_genl_ops[] = {
                .policy = ethnl_stats_get_policy,
                .maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1,
        },
+       {
+               .cmd    = ETHTOOL_MSG_PHC_VCLOCKS_GET,
+               .doit   = ethnl_default_doit,
+               .start  = ethnl_default_start,
+               .dumpit = ethnl_default_dumpit,
+               .done   = ethnl_default_done,
+               .policy = ethnl_phc_vclocks_get_policy,
+               .maxattr = ARRAY_SIZE(ethnl_phc_vclocks_get_policy) - 1,
+       },
 };
 
 static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
index 3e25a47fd482d87b895183fd3976abd4b1c2ab37..3fc395c867021919c114cbbb878b06b20e6a33a9 100644 (file)
@@ -347,6 +347,7 @@ extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
 extern const struct ethnl_request_ops ethnl_fec_request_ops;
 extern const struct ethnl_request_ops ethnl_module_eeprom_request_ops;
 extern const struct ethnl_request_ops ethnl_stats_request_ops;
+extern const struct ethnl_request_ops ethnl_phc_vclocks_request_ops;
 
 extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
 extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
@@ -382,6 +383,7 @@ extern const struct nla_policy ethnl_fec_get_policy[ETHTOOL_A_FEC_HEADER + 1];
 extern const struct nla_policy ethnl_fec_set_policy[ETHTOOL_A_FEC_AUTO + 1];
 extern const struct nla_policy ethnl_module_eeprom_get_policy[ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS + 1];
 extern const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1];
+extern const struct nla_policy ethnl_phc_vclocks_get_policy[ETHTOOL_A_PHC_VCLOCKS_HEADER + 1];
 
 int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
 int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
diff --git a/net/ethtool/phc_vclocks.c b/net/ethtool/phc_vclocks.c
new file mode 100644 (file)
index 0000000..637b2f5
--- /dev/null
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2021 NXP
+ */
+#include "netlink.h"
+#include "common.h"
+
+struct phc_vclocks_req_info {
+       struct ethnl_req_info           base;
+};
+
+struct phc_vclocks_reply_data {
+       struct ethnl_reply_data         base;
+       int                             num;
+       int                             *index;
+};
+
+#define PHC_VCLOCKS_REPDATA(__reply_base) \
+       container_of(__reply_base, struct phc_vclocks_reply_data, base)
+
+const struct nla_policy ethnl_phc_vclocks_get_policy[] = {
+       [ETHTOOL_A_PHC_VCLOCKS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
+};
+
+static int phc_vclocks_prepare_data(const struct ethnl_req_info *req_base,
+                                   struct ethnl_reply_data *reply_base,
+                                   struct genl_info *info)
+{
+       struct phc_vclocks_reply_data *data = PHC_VCLOCKS_REPDATA(reply_base);
+       struct net_device *dev = reply_base->dev;
+       int ret;
+
+       ret = ethnl_ops_begin(dev);
+       if (ret < 0)
+               return ret;
+       data->num = ethtool_get_phc_vclocks(dev, &data->index);
+       ethnl_ops_complete(dev);
+
+       return ret;
+}
+
+static int phc_vclocks_reply_size(const struct ethnl_req_info *req_base,
+                                 const struct ethnl_reply_data *reply_base)
+{
+       const struct phc_vclocks_reply_data *data =
+               PHC_VCLOCKS_REPDATA(reply_base);
+       int len = 0;
+
+       if (data->num > 0) {
+               len += nla_total_size(sizeof(u32));
+               len += nla_total_size(sizeof(s32) * data->num);
+       }
+
+       return len;
+}
+
+static int phc_vclocks_fill_reply(struct sk_buff *skb,
+                                 const struct ethnl_req_info *req_base,
+                                 const struct ethnl_reply_data *reply_base)
+{
+       const struct phc_vclocks_reply_data *data =
+               PHC_VCLOCKS_REPDATA(reply_base);
+
+       if (data->num <= 0)
+               return 0;
+
+       if (nla_put_u32(skb, ETHTOOL_A_PHC_VCLOCKS_NUM, data->num) ||
+           nla_put(skb, ETHTOOL_A_PHC_VCLOCKS_INDEX,
+                   sizeof(s32) * data->num, data->index))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static void phc_vclocks_cleanup_data(struct ethnl_reply_data *reply_base)
+{
+       const struct phc_vclocks_reply_data *data =
+               PHC_VCLOCKS_REPDATA(reply_base);
+
+       kfree(data->index);
+}
+
+const struct ethnl_request_ops ethnl_phc_vclocks_request_ops = {
+       .request_cmd            = ETHTOOL_MSG_PHC_VCLOCKS_GET,
+       .reply_cmd              = ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
+       .hdr_attr               = ETHTOOL_A_PHC_VCLOCKS_HEADER,
+       .req_info_size          = sizeof(struct phc_vclocks_req_info),
+       .reply_data_size        = sizeof(struct phc_vclocks_reply_data),
+
+       .prepare_data           = phc_vclocks_prepare_data,
+       .reply_size             = phc_vclocks_reply_size,
+       .fill_reply             = phc_vclocks_fill_reply,
+       .cleanup_data           = phc_vclocks_cleanup_data,
+};