Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp2520664ybb; Fri, 27 Mar 2020 07:10:00 -0700 (PDT) X-Google-Smtp-Source: ADFU+vszxaPWrDFO49H2TeGZ02iJhKCLBle2hl4Mz7dW4rBlm/r0vRZECXo32t1nrS+Yq16d5Le3 X-Received: by 2002:aca:488a:: with SMTP id v132mr4150370oia.166.1585318200124; Fri, 27 Mar 2020 07:10:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585318200; cv=none; d=google.com; s=arc-20160816; b=Yh8laI3t/IpzGJiERMlV07PjnJ97frkomkvkQsjWwIAszsy6BbvZkmCiGe9YxnnmAV RPGdBmjhHaGwpmSrYHH5BC0pJvKgBeCbOyL9pcX3JAy7sZmsqHoNgmSgnFSbLAxp714n HZg/IGANNwumtigigv32H93otB7czAUU6IzHWSNZI35wq3pNYVDdEk0tzOWFIgnaflUZ BW/CuueELPPMr69nzT9bKy2BsDtJBcwnNOOzB736lRr1UnJ4kHWPoAkOiuzYrB2ahfvp juh7VhMbaifbG/IY+Ih5Lebtt83oEh8gYJIqTJPt9ECSIct02SCNwOVkteY4zseLfY0r oHxA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:cc:to:subject:from:references :in-reply-to:message-id; bh=bXcfrW/dWpTR3ewFQiaS46oXYq1utb+Y2LSMKcDlw0w=; b=bcc8PBmhYi3WR4+hl4zZZanOAncnl1MsXkbtGbzXmDNVEC7rWsEO95Wa7lxpLSEgxT GSX1gin7+gdVTcJ0r8o9I8xGlSwgOdCk45pM8Ol3ug6BxH7RHYu521zaP9G+N62d+JAq +1UHQDuHWWYQLJl1XoZhzOmEry65NghZRRkRxAMd5YXeW7ufm47A3MYBDlWhRp/zpL09 kgdr77tSWdsPM+4Vw0JBXInqxdXxh5DIcmkp1gtlY3or4gUzy/oqbmez6UqPuu7vqSfr 3H8e+zZu5qLqzQDLI9VntSBQRERJzNTuI3mCpa4iINZ08ratS1axS48B7HjcPzaZTM/u kmRQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z65si2429349otb.197.2020.03.27.07.09.45; Fri, 27 Mar 2020 07:10:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727922AbgC0OIW (ORCPT + 99 others); Fri, 27 Mar 2020 10:08:22 -0400 Received: from mx2.suse.de ([195.135.220.15]:41656 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726333AbgC0OIV (ORCPT ); Fri, 27 Mar 2020 10:08:21 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 9FD11B269; Fri, 27 Mar 2020 14:08:18 +0000 (UTC) Received: by unicorn.suse.cz (Postfix, from userid 1000) id A0D45E009C; Fri, 27 Mar 2020 15:08:17 +0100 (CET) Message-Id: <5a3af8d892cafe9d9a2dc367e9ae463691261305.1585316159.git.mkubecek@suse.cz> In-Reply-To: References: From: Michal Kubecek Subject: [PATCH net-next v2 12/12] ethtool: provide timestamping information with TIMESTAMP_GET request To: David Miller , Jakub Kicinski , netdev@vger.kernel.org Cc: Jiri Pirko , Andrew Lunn , Florian Fainelli , John Linville , Johannes Berg , Richard Cochran , linux-kernel@vger.kernel.org Date: Fri, 27 Mar 2020 15:08:17 +0100 (CET) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement TIMESTAMP_GET request to get timestamping information for a network device. This is traditionally available via ETHTOOL_GET_TS_INFO ioctl request. Move part of ethtool_get_ts_info() into common.c so that ioctl and netlink code use the same logic to get timestamping information from the device. Signed-off-by: Michal Kubecek --- Documentation/networking/ethtool-netlink.rst | 30 +++- include/uapi/linux/ethtool_netlink.h | 17 +++ net/ethtool/Makefile | 2 +- net/ethtool/common.c | 21 +++ net/ethtool/common.h | 1 + net/ethtool/ioctl.c | 23 +-- net/ethtool/netlink.c | 8 ++ net/ethtool/netlink.h | 1 + net/ethtool/timestamp.c | 143 +++++++++++++++++++ 9 files changed, 225 insertions(+), 21 deletions(-) create mode 100644 net/ethtool/timestamp.c diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index f1950a0a6c93..478196b36be6 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -203,6 +203,7 @@ Userspace to kernel: ``ETHTOOL_MSG_PAUSE_SET`` set pause parameters ``ETHTOOL_MSG_EEE_GET`` get EEE settings ``ETHTOOL_MSG_EEE_SET`` set EEE settings + ``ETHTOOL_MSG_TIMESTAMP_GET`` get timestamping info ===================================== ================================ Kernel to userspace: @@ -233,6 +234,7 @@ Kernel to userspace: ``ETHTOOL_MSG_PAUSE_NTF`` pause parameters ``ETHTOOL_MSG_EEE_GET_REPLY`` EEE settings ``ETHTOOL_MSG_EEE_NTF`` EEE settings + ``ETHTOOL_MSG_TIMESTAMP_GET_REPLY`` timestamping info ===================================== ================================= ``GET`` requests are sent by userspace applications to retrieve device @@ -928,6 +930,32 @@ but only first 32 can be set at the moment as that is what the ``ethtool_ops`` callback supports. +TIMESTAMP_GET +============= + +Gets timestamping information like ``ETHTOOL_GET_TS_INFO`` ioctl request. + +Request contents: + + ===================================== ====== ========================== + ``ETHTOOL_A_TIMESTAMP_HEADER`` nested request header + ===================================== ====== ========================== + +Kernel response contents: + + ===================================== ====== ========================== + ``ETHTOOL_A_TIMESTAMP_HEADER`` nested request header + ``ETHTOOL_A_TIMESTAMP_TIMESTAMPING`` bitset SO_TIMESTAMPING flags + ``ETHTOOL_A_TIMESTAMP_TX_TYPES`` bitset supported Tx types + ``ETHTOOL_A_TIMESTAMP_RX_FILTERS`` bitset supported Rx filters + ``ETHTOOL_A_TIMESTAMP_PHC_INDEX`` u32 PTP hw clock index + ===================================== ====== ========================== + +``ETHTOOL_A_TIMESTAMP_PHC_INDEX`` is absent if there is no associated PHC +(there is no special value for this case). The bitset attributes are omitted +if they would be empty (no bit set). + + Request translation =================== @@ -1003,7 +1031,7 @@ have their netlink replacement yet. ``ETHTOOL_SET_DUMP`` n/a ``ETHTOOL_GET_DUMP_FLAG`` n/a ``ETHTOOL_GET_DUMP_DATA`` n/a - ``ETHTOOL_GET_TS_INFO`` n/a + ``ETHTOOL_GET_TS_INFO`` ``ETHTOOL_MSG_TIMESTAMP_GET`` ``ETHTOOL_GMODULEINFO`` n/a ``ETHTOOL_GMODULEEEPROM`` n/a ``ETHTOOL_GEEE`` ``ETHTOOL_MSG_EEE_GET`` diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index bacdd5363510..3db2732592b3 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -38,6 +38,7 @@ enum { ETHTOOL_MSG_PAUSE_SET, ETHTOOL_MSG_EEE_GET, ETHTOOL_MSG_EEE_SET, + ETHTOOL_MSG_TIMESTAMP_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -72,6 +73,7 @@ enum { ETHTOOL_MSG_PAUSE_NTF, ETHTOOL_MSG_EEE_GET_REPLY, ETHTOOL_MSG_EEE_NTF, + ETHTOOL_MSG_TIMESTAMP_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -386,6 +388,21 @@ enum { ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1) }; +/* TIMESTAMP */ + +enum { + ETHTOOL_A_TIMESTAMP_UNSPEC, + ETHTOOL_A_TIMESTAMP_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_TIMESTAMP_TIMESTAMPING, /* bitset */ + ETHTOOL_A_TIMESTAMP_TX_TYPES, /* bitset */ + ETHTOOL_A_TIMESTAMP_RX_FILTERS, /* bitset */ + ETHTOOL_A_TIMESTAMP_PHC_INDEX, /* u32 */ + + /* add new constants above here */ + __ETHTOOL_A_TIMESTAMP_CNT, + ETHTOOL_A_TIMESTAMP_MAX = (__ETHTOOL_A_TIMESTAMP_CNT - 1) +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index a790f408aa5d..17da981bdea7 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -6,4 +6,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 + channels.o coalesce.o pause.o eee.o timestamp.o diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 6faa1e0f99a4..9b03ca6c5a6e 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include +#include #include "common.h" @@ -349,3 +350,23 @@ int ethtool_check_ops(const struct ethtool_ops *ops) */ return 0; } + +int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + struct phy_device *phydev = dev->phydev; + + memset(info, 0, sizeof(*info)); + info->cmd = ETHTOOL_GET_TS_INFO; + + if (phy_has_tsinfo(phydev)) + return phy_ts_info(phydev, info); + if (ops->get_ts_info) + return ops->get_ts_info(dev, info); + + info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + + return 0; +} diff --git a/net/ethtool/common.h b/net/ethtool/common.h index c54c8d57fd8f..a62f68ccc43a 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -35,5 +35,6 @@ bool convert_legacy_settings_to_link_ksettings( struct ethtool_link_ksettings *link_ksettings, const struct ethtool_cmd *legacy_settings); int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max); +int __ethtool_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info); #endif /* _ETHTOOL_COMMON_H */ diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 05a2bf64a96b..89d0b1827aaf 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -2140,32 +2140,17 @@ static int ethtool_get_dump_data(struct net_device *dev, static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr) { - int err = 0; struct ethtool_ts_info info; - const struct ethtool_ops *ops = dev->ethtool_ops; - struct phy_device *phydev = dev->phydev; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GET_TS_INFO; - - if (phy_has_tsinfo(phydev)) { - err = phy_ts_info(phydev, &info); - } else if (ops->get_ts_info) { - err = ops->get_ts_info(dev, &info); - } else { - info.so_timestamping = - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE; - info.phc_index = -1; - } + int err; + err = __ethtool_get_ts_info(dev, &info); if (err) return err; if (copy_to_user(useraddr, &info, sizeof(info))) - err = -EFAULT; + return -EFAULT; - return err; + return 0; } static int __ethtool_get_module_info(struct net_device *dev, diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index e525c7b8ba4d..25422ff0b87d 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -230,6 +230,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_COALESCE_GET] = ðnl_coalesce_request_ops, [ETHTOOL_MSG_PAUSE_GET] = ðnl_pause_request_ops, [ETHTOOL_MSG_EEE_GET] = ðnl_eee_request_ops, + [ETHTOOL_MSG_TIMESTAMP_GET] = ðnl_timestamp_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -831,6 +832,13 @@ static const struct genl_ops ethtool_genl_ops[] = { .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_eee, }, + { + .cmd = ETHTOOL_MSG_TIMESTAMP_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index a251957d535e..a8dbb2943940 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -344,6 +344,7 @@ extern const struct ethnl_request_ops ethnl_channels_request_ops; extern const struct ethnl_request_ops ethnl_coalesce_request_ops; extern const struct ethnl_request_ops ethnl_pause_request_ops; extern const struct ethnl_request_ops ethnl_eee_request_ops; +extern const struct ethnl_request_ops ethnl_timestamp_request_ops; 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/timestamp.c b/net/ethtool/timestamp.c new file mode 100644 index 000000000000..30e6118acdaf --- /dev/null +++ b/net/ethtool/timestamp.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include + +#include "netlink.h" +#include "common.h" +#include "bitset.h" + +struct timestamp_req_info { + struct ethnl_req_info base; +}; + +struct timestamp_reply_data { + struct ethnl_reply_data base; + struct ethtool_ts_info ts_info; +}; + +#define TIMESTAMP_REPDATA(__reply_base) \ + container_of(__reply_base, struct timestamp_reply_data, base) + +static const struct nla_policy +timestamp_get_policy[ETHTOOL_A_TIMESTAMP_MAX + 1] = { + [ETHTOOL_A_TIMESTAMP_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_TIMESTAMP_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_TIMESTAMP_TIMESTAMPING] = { .type = NLA_REJECT }, + [ETHTOOL_A_TIMESTAMP_TX_TYPES] = { .type = NLA_REJECT }, + [ETHTOOL_A_TIMESTAMP_RX_FILTERS] = { .type = NLA_REJECT }, + [ETHTOOL_A_TIMESTAMP_PHC_INDEX] = { .type = NLA_REJECT }, +}; + +static int timestamp_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct timestamp_reply_data *data = TIMESTAMP_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + int ret; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + ret = __ethtool_get_ts_info(dev, &data->ts_info); + ethnl_ops_complete(dev); + + return ret; +} + +static int timestamp_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct timestamp_reply_data *data = TIMESTAMP_REPDATA(reply_base); + bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + const struct ethtool_ts_info *ts_info = &data->ts_info; + int len = 0; + int ret; + + BUILD_BUG_ON(__SOF_TIMESTAMPING_CNT > 32); + BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32); + BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32); + + if (ts_info->so_timestamping) { + ret = ethnl_bitset32_size(&ts_info->so_timestamping, NULL, + __SOF_TIMESTAMPING_CNT, + sof_timestamping_names, compact); + if (ret < 0) + return ret; + len += ret; /* _TIMESTAMP_TIMESTAMPING */ + } + if (ts_info->tx_types) { + ret = ethnl_bitset32_size(&ts_info->tx_types, NULL, + __HWTSTAMP_TX_CNT, + ts_tx_type_names, compact); + if (ret < 0) + return ret; + len += ret; /* _TIMESTAMP_TX_TYPES */ + } + if (ts_info->rx_filters) { + ret = ethnl_bitset32_size(&ts_info->rx_filters, NULL, + __HWTSTAMP_FILTER_CNT, + ts_rx_filter_names, compact); + if (ret < 0) + return ret; + len += ret; /* _TIMESTAMP_RX_FILTERS */ + } + if (ts_info->phc_index >= 0) + len += nla_total_size(sizeof(u32)); /* _TIMESTAMP_PHC_INDEX */ + + return len; +} + +static int timestamp_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct timestamp_reply_data *data = TIMESTAMP_REPDATA(reply_base); + bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + const struct ethtool_ts_info *ts_info = &data->ts_info; + int ret; + + if (ts_info->so_timestamping) { + ret = ethnl_put_bitset32(skb, ETHTOOL_A_TIMESTAMP_TIMESTAMPING, + &ts_info->so_timestamping, NULL, + __SOF_TIMESTAMPING_CNT, + sof_timestamping_names, compact); + if (ret < 0) + return ret; + } + if (ts_info->tx_types) { + ret = ethnl_put_bitset32(skb, ETHTOOL_A_TIMESTAMP_TX_TYPES, + &ts_info->tx_types, NULL, + __HWTSTAMP_TX_CNT, + ts_tx_type_names, compact); + if (ret < 0) + return ret; + } + if (ts_info->rx_filters) { + ret = ethnl_put_bitset32(skb, ETHTOOL_A_TIMESTAMP_RX_FILTERS, + &ts_info->rx_filters, NULL, + __HWTSTAMP_FILTER_CNT, + ts_rx_filter_names, compact); + if (ret < 0) + return ret; + } + if (ts_info->phc_index >= 0 && + nla_put_u32(skb, ETHTOOL_A_TIMESTAMP_PHC_INDEX, ts_info->phc_index)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_timestamp_request_ops = { + .request_cmd = ETHTOOL_MSG_TIMESTAMP_GET, + .reply_cmd = ETHTOOL_MSG_TIMESTAMP_GET_REPLY, + .hdr_attr = ETHTOOL_A_TIMESTAMP_HEADER, + .max_attr = ETHTOOL_A_TIMESTAMP_MAX, + .req_info_size = sizeof(struct timestamp_req_info), + .reply_data_size = sizeof(struct timestamp_reply_data), + .request_policy = timestamp_get_policy, + + .prepare_data = timestamp_prepare_data, + .reply_size = timestamp_reply_size, + .fill_reply = timestamp_fill_reply, +}; -- 2.25.1