^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/net_tstamp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "bitset.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) struct tsinfo_req_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) struct ethnl_req_info base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct tsinfo_reply_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct ethnl_reply_data base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct ethtool_ts_info ts_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define TSINFO_REPDATA(__reply_base) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) container_of(__reply_base, struct tsinfo_reply_data, base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) const struct nla_policy ethnl_tsinfo_get_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) [ETHTOOL_A_TSINFO_HEADER] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) NLA_POLICY_NESTED(ethnl_header_policy),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct ethnl_reply_data *reply_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct net_device *dev = reply_base->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ret = ethnl_ops_begin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ret = __ethtool_get_ts_info(dev, &data->ts_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ethnl_ops_complete(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int tsinfo_reply_size(const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct ethnl_reply_data *reply_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) const struct ethtool_ts_info *ts_info = &data->ts_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) BUILD_BUG_ON(__SOF_TIMESTAMPING_CNT > 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (ts_info->so_timestamping) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ret = ethnl_bitset32_size(&ts_info->so_timestamping, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __SOF_TIMESTAMPING_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) sof_timestamping_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) len += ret; /* _TSINFO_TIMESTAMPING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (ts_info->tx_types) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = ethnl_bitset32_size(&ts_info->tx_types, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) __HWTSTAMP_TX_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ts_tx_type_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) len += ret; /* _TSINFO_TX_TYPES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (ts_info->rx_filters) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ret = ethnl_bitset32_size(&ts_info->rx_filters, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) __HWTSTAMP_FILTER_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ts_rx_filter_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) len += ret; /* _TSINFO_RX_FILTERS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (ts_info->phc_index >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) len += nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int tsinfo_fill_reply(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) const struct ethnl_req_info *req_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) const struct ethnl_reply_data *reply_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) const struct ethtool_ts_info *ts_info = &data->ts_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (ts_info->so_timestamping) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_TIMESTAMPING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) &ts_info->so_timestamping, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) __SOF_TIMESTAMPING_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) sof_timestamping_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (ts_info->tx_types) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_TX_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) &ts_info->tx_types, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __HWTSTAMP_TX_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ts_tx_type_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (ts_info->rx_filters) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_RX_FILTERS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) &ts_info->rx_filters, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) __HWTSTAMP_FILTER_CNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ts_rx_filter_names, compact);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (ts_info->phc_index >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const struct ethnl_request_ops ethnl_tsinfo_request_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .request_cmd = ETHTOOL_MSG_TSINFO_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .hdr_attr = ETHTOOL_A_TSINFO_HEADER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .req_info_size = sizeof(struct tsinfo_req_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .reply_data_size = sizeof(struct tsinfo_reply_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .prepare_data = tsinfo_prepare_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .reply_size = tsinfo_reply_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .fill_reply = tsinfo_fill_reply,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };