File netlink-add-netlink-handler-for-tsinfo-T.patch of Package ethtool

From: Michal Kubecek <mkubecek@suse.cz>
Date: Wed, 22 Aug 2018 23:26:42 +0200
Subject: netlink: add netlink handler for tsinfo (-T)
Patch-mainline: Not yet, work in progress
References: none

Implement "-T" subcommand using netlink interface command
ETHNL_CMD_GET_INFO.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 common.c         |  35 ++++++++++++++++
 common.h         |   7 ++++
 ethtool.c        |  44 +--------------------
 netlink/extapi.h |   1 +
 netlink/info.c   | 101 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 146 insertions(+), 42 deletions(-)

diff --git a/common.c b/common.c
index 1428b9b674f9..9e807b1cf5b9 100644
--- a/common.c
+++ b/common.c
@@ -1,2 +1,37 @@
 #include "internal.h"
 #include "common.h"
+
+char *so_timestamping_labels[N_SOTS] = {
+	"hardware-transmit     (SOF_TIMESTAMPING_TX_HARDWARE)",
+	"software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)",
+	"hardware-receive      (SOF_TIMESTAMPING_RX_HARDWARE)",
+	"software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)",
+	"software-system-clock (SOF_TIMESTAMPING_SOFTWARE)",
+	"hardware-legacy-clock (SOF_TIMESTAMPING_SYS_HARDWARE)",
+	"hardware-raw-clock    (SOF_TIMESTAMPING_RAW_HARDWARE)",
+};
+
+char *tx_type_labels[N_TX_TYPES] = {
+	"off                   (HWTSTAMP_TX_OFF)",
+	"on                    (HWTSTAMP_TX_ON)",
+	"one-step-sync         (HWTSTAMP_TX_ONESTEP_SYNC)",
+};
+
+char *rx_filter_labels[N_RX_FILTERS] = {
+	"none                  (HWTSTAMP_FILTER_NONE)",
+	"all                   (HWTSTAMP_FILTER_ALL)",
+	"some                  (HWTSTAMP_FILTER_SOME)",
+	"ptpv1-l4-event        (HWTSTAMP_FILTER_PTP_V1_L4_EVENT)",
+	"ptpv1-l4-sync         (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)",
+	"ptpv1-l4-delay-req    (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)",
+	"ptpv2-l4-event        (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)",
+	"ptpv2-l4-sync         (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)",
+	"ptpv2-l4-delay-req    (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)",
+	"ptpv2-l2-event        (HWTSTAMP_FILTER_PTP_V2_L2_EVENT)",
+	"ptpv2-l2-sync         (HWTSTAMP_FILTER_PTP_V2_L2_SYNC)",
+	"ptpv2-l2-delay-req    (HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ)",
+	"ptpv2-event           (HWTSTAMP_FILTER_PTP_V2_EVENT)",
+	"ptpv2-sync            (HWTSTAMP_FILTER_PTP_V2_SYNC)",
+	"ptpv2-delay-req       (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)",
+	"ntp-all               (HWTSTAMP_FILTER_NTP_ALL)",
+};
diff --git a/common.h b/common.h
index 286c2055f2d7..7c08ec2d7c2f 100644
--- a/common.h
+++ b/common.h
@@ -3,4 +3,11 @@
 
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 
+#define N_SOTS 7
+extern char *so_timestamping_labels[N_SOTS];
+#define N_TX_TYPES (HWTSTAMP_TX_ONESTEP_SYNC + 1)
+extern char *tx_type_labels[N_TX_TYPES];
+#define N_RX_FILTERS (HWTSTAMP_FILTER_NTP_ALL + 1)
+extern char *rx_filter_labels[N_RX_FILTERS];
+
 #endif /* ETHTOOL_COMMON_H__ */
diff --git a/ethtool.c b/ethtool.c
index 376b350e7196..1fcd23244822 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1609,47 +1609,6 @@ static void dump_fec(u32 fec)
 		fprintf(stdout, " RS");
 }
 
-#define N_SOTS 7
-
-static char *so_timestamping_labels[N_SOTS] = {
-	"hardware-transmit     (SOF_TIMESTAMPING_TX_HARDWARE)",
-	"software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)",
-	"hardware-receive      (SOF_TIMESTAMPING_RX_HARDWARE)",
-	"software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)",
-	"software-system-clock (SOF_TIMESTAMPING_SOFTWARE)",
-	"hardware-legacy-clock (SOF_TIMESTAMPING_SYS_HARDWARE)",
-	"hardware-raw-clock    (SOF_TIMESTAMPING_RAW_HARDWARE)",
-};
-
-#define N_TX_TYPES (HWTSTAMP_TX_ONESTEP_SYNC + 1)
-
-static char *tx_type_labels[N_TX_TYPES] = {
-	"off                   (HWTSTAMP_TX_OFF)",
-	"on                    (HWTSTAMP_TX_ON)",
-	"one-step-sync         (HWTSTAMP_TX_ONESTEP_SYNC)",
-};
-
-#define N_RX_FILTERS (HWTSTAMP_FILTER_NTP_ALL + 1)
-
-static char *rx_filter_labels[N_RX_FILTERS] = {
-	"none                  (HWTSTAMP_FILTER_NONE)",
-	"all                   (HWTSTAMP_FILTER_ALL)",
-	"some                  (HWTSTAMP_FILTER_SOME)",
-	"ptpv1-l4-event        (HWTSTAMP_FILTER_PTP_V1_L4_EVENT)",
-	"ptpv1-l4-sync         (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)",
-	"ptpv1-l4-delay-req    (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)",
-	"ptpv2-l4-event        (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)",
-	"ptpv2-l4-sync         (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)",
-	"ptpv2-l4-delay-req    (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)",
-	"ptpv2-l2-event        (HWTSTAMP_FILTER_PTP_V2_L2_EVENT)",
-	"ptpv2-l2-sync         (HWTSTAMP_FILTER_PTP_V2_L2_SYNC)",
-	"ptpv2-l2-delay-req    (HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ)",
-	"ptpv2-event           (HWTSTAMP_FILTER_PTP_V2_EVENT)",
-	"ptpv2-sync            (HWTSTAMP_FILTER_PTP_V2_SYNC)",
-	"ptpv2-delay-req       (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)",
-	"ntp-all               (HWTSTAMP_FILTER_NTP_ALL)",
-};
-
 static int dump_tsinfo(const struct ethtool_ts_info *info)
 {
 	int i;
@@ -5062,6 +5021,7 @@ static int show_usage(struct cmd_context *ctx);
  */
 #define nl_gdrv		NULL
 #define nl_permaddr	NULL
+#define nl_tsinfo	NULL
 #endif
 
 static const struct option {
@@ -5190,7 +5150,7 @@ static const struct option {
 	  "			[ context %d ]\n"
 	  "			[ loc %d]] |\n"
 	  "		delete %d\n" },
-	{ "-T|--show-time-stamping", 1, do_tsinfo, NULL,
+	{ "-T|--show-time-stamping", 1, do_tsinfo, nl_tsinfo,
 	  "Show time stamping capabilities" },
 	{ "-x|--show-rxfh-indir|--show-rxfh", 1, do_grxfh, NULL,
 	  "Show Rx flow hash indirection table and/or RSS hash key",
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 3e3a03894e99..0de6cbd653cc 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -15,6 +15,7 @@ int netlink_done(struct cmd_context *ctx);
 
 int nl_gdrv(struct cmd_context *ctx);
 int nl_permaddr(struct cmd_context *ctx);
+int nl_tsinfo(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void monitor_usage();
diff --git a/netlink/info.c b/netlink/info.c
index fda8b6a76bf4..0631809194be 100644
--- a/netlink/info.c
+++ b/netlink/info.c
@@ -3,6 +3,8 @@
 
 #include "../internal.h"
 #include "netlink.h"
+#include "common.h"
+#include "strset.h"
 
 static int show_drvinfo(struct nl_context *nlctx, const struct nlattr *nest)
 {
@@ -77,6 +79,91 @@ static int show_permaddr(struct nl_context *nlctx, const struct nlattr *nest)
 	return MNL_CB_OK;
 }
 
+static void show_one_ts_flag(unsigned int idx, const char *name, bool val,
+			     void *data)
+{
+	if (val)
+		printf("\t%s\n",
+		       idx < N_SOTS ? so_timestamping_labels[idx] : name);
+}
+
+static void show_one_tx_type(unsigned int idx, const char *name, bool val,
+			     void *data)
+{
+	if (val)
+		printf("\t%s\n",
+		       idx < N_TX_TYPES ? tx_type_labels[idx] : name);
+}
+
+static void show_one_rx_filter(unsigned int idx, const char *name, bool val,
+			       void *data)
+{
+	if (val)
+		printf("\t%s\n",
+		       idx < N_RX_FILTERS ? rx_filter_labels[idx] : name);
+}
+
+static int show_tsinfo(struct nl_context *nlctx, const struct nlattr *nest)
+{
+	const struct nlattr *tb[ETHA_TSINFO_MAX + 1] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	int ret;
+
+	if (!nest)
+		return -EOPNOTSUPP;
+	ret = mnl_attr_parse_nested(nest, attr_cb, &tb_info);
+	if (ret < 0)
+		return ret;
+
+	if (nlctx->is_dump || nlctx->is_monitor)
+		putchar('\n');
+	printf("\nTime stamping parameters for %s:\n", nlctx->devname);
+
+	if (tb[ETHA_TSINFO_TIMESTAMPING]) {
+		printf("Capabilities:");
+		if (bitset_is_empty(tb[ETHA_TSINFO_TIMESTAMPING], false, &ret))
+			fputs(" none\n", stdout);
+		else {
+			fputc('\n', stdout);
+			walk_bitset(tb[ETHA_TSINFO_TIMESTAMPING],
+				    global_stringset(ETH_SS_TSTAMP_SOF),
+				    show_one_ts_flag, NULL);
+		}
+	}
+
+	printf("PTP Hardware Clock: ");
+	if (tb[ETHA_TSINFO_PHC_INDEX])
+		printf("%u\n", mnl_attr_get_u32(tb[ETHA_TSINFO_PHC_INDEX]));
+	else
+		printf("none\n");
+
+	if (tb[ETHA_TSINFO_TX_TYPES]) {
+		printf("Hardware Transmit Timestamp Modes:");
+		if (bitset_is_empty(tb[ETHA_TSINFO_TX_TYPES], false, &ret)) {
+			fputs(" none\n", stdout);
+		} else {
+			fputc('\n', stdout);
+			walk_bitset(tb[ETHA_TSINFO_TX_TYPES],
+				    global_stringset(ETH_SS_TSTAMP_TX_TYPE),
+				    show_one_tx_type, NULL);
+		}
+	}
+
+	if (tb[ETHA_TSINFO_RX_FILTERS]) {
+		printf("Hardware Receive Filter Modes:");
+		if (bitset_is_empty(tb[ETHA_TSINFO_TX_TYPES], false, &ret)) {
+			fputs(" none\n", stdout);
+		} else {
+			fputc('\n', stdout);
+			walk_bitset(tb[ETHA_TSINFO_RX_FILTERS],
+				    global_stringset(ETH_SS_TSTAMP_RX_FILTER),
+				    show_one_rx_filter, NULL);
+		}
+	}
+
+	return MNL_CB_OK;
+}
+
 int info_reply_cb(const struct nlmsghdr *nlhdr, void *data)
 {
 	const struct nlattr *tb[ETHA_INFO_MAX + 1] = {};
@@ -109,6 +196,15 @@ int info_reply_cb(const struct nlmsghdr *nlhdr, void *data)
 			return MNL_CB_ERROR;
 		}
 	}
+	if (mask_ok(nlctx, ETH_INFO_IM_TSINFO)) {
+		ret = show_tsinfo(nlctx, tb[ETHA_INFO_TSINFO]);
+		if ((ret < 0) && show_only(nlctx, ETH_INFO_IM_TSINFO)) {
+			nlctx->exit_code = 1;
+			errno = -ret;
+			perror("Cannot get device time stamping settings");
+			return MNL_CB_ERROR;
+		}
+	}
 
 	return MNL_CB_OK;
 }
@@ -134,3 +230,8 @@ int nl_permaddr(struct cmd_context *ctx)
 {
 	return info_request(ctx, ETH_INFO_IM_PERMADDR);
 }
+
+int nl_tsinfo(struct cmd_context *ctx)
+{
+	return info_request(ctx, ETH_INFO_IM_TSINFO);
+}
-- 
2.19.0