Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 #include <linux/net_tstamp.h>
0004 
0005 #include "netlink.h"
0006 #include "common.h"
0007 #include "bitset.h"
0008 
0009 struct tsinfo_req_info {
0010     struct ethnl_req_info       base;
0011 };
0012 
0013 struct tsinfo_reply_data {
0014     struct ethnl_reply_data     base;
0015     struct ethtool_ts_info      ts_info;
0016 };
0017 
0018 #define TSINFO_REPDATA(__reply_base) \
0019     container_of(__reply_base, struct tsinfo_reply_data, base)
0020 
0021 const struct nla_policy ethnl_tsinfo_get_policy[] = {
0022     [ETHTOOL_A_TSINFO_HEADER]       =
0023         NLA_POLICY_NESTED(ethnl_header_policy),
0024 };
0025 
0026 static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
0027                    struct ethnl_reply_data *reply_base,
0028                    struct genl_info *info)
0029 {
0030     struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
0031     struct net_device *dev = reply_base->dev;
0032     int ret;
0033 
0034     ret = ethnl_ops_begin(dev);
0035     if (ret < 0)
0036         return ret;
0037     ret = __ethtool_get_ts_info(dev, &data->ts_info);
0038     ethnl_ops_complete(dev);
0039 
0040     return ret;
0041 }
0042 
0043 static int tsinfo_reply_size(const struct ethnl_req_info *req_base,
0044                  const struct ethnl_reply_data *reply_base)
0045 {
0046     const struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
0047     bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
0048     const struct ethtool_ts_info *ts_info = &data->ts_info;
0049     int len = 0;
0050     int ret;
0051 
0052     BUILD_BUG_ON(__SOF_TIMESTAMPING_CNT > 32);
0053     BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32);
0054     BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32);
0055 
0056     if (ts_info->so_timestamping) {
0057         ret = ethnl_bitset32_size(&ts_info->so_timestamping, NULL,
0058                       __SOF_TIMESTAMPING_CNT,
0059                       sof_timestamping_names, compact);
0060         if (ret < 0)
0061             return ret;
0062         len += ret; /* _TSINFO_TIMESTAMPING */
0063     }
0064     if (ts_info->tx_types) {
0065         ret = ethnl_bitset32_size(&ts_info->tx_types, NULL,
0066                       __HWTSTAMP_TX_CNT,
0067                       ts_tx_type_names, compact);
0068         if (ret < 0)
0069             return ret;
0070         len += ret; /* _TSINFO_TX_TYPES */
0071     }
0072     if (ts_info->rx_filters) {
0073         ret = ethnl_bitset32_size(&ts_info->rx_filters, NULL,
0074                       __HWTSTAMP_FILTER_CNT,
0075                       ts_rx_filter_names, compact);
0076         if (ret < 0)
0077             return ret;
0078         len += ret; /* _TSINFO_RX_FILTERS */
0079     }
0080     if (ts_info->phc_index >= 0)
0081         len += nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */
0082 
0083     return len;
0084 }
0085 
0086 static int tsinfo_fill_reply(struct sk_buff *skb,
0087                  const struct ethnl_req_info *req_base,
0088                  const struct ethnl_reply_data *reply_base)
0089 {
0090     const struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
0091     bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
0092     const struct ethtool_ts_info *ts_info = &data->ts_info;
0093     int ret;
0094 
0095     if (ts_info->so_timestamping) {
0096         ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_TIMESTAMPING,
0097                      &ts_info->so_timestamping, NULL,
0098                      __SOF_TIMESTAMPING_CNT,
0099                      sof_timestamping_names, compact);
0100         if (ret < 0)
0101             return ret;
0102     }
0103     if (ts_info->tx_types) {
0104         ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_TX_TYPES,
0105                      &ts_info->tx_types, NULL,
0106                      __HWTSTAMP_TX_CNT,
0107                      ts_tx_type_names, compact);
0108         if (ret < 0)
0109             return ret;
0110     }
0111     if (ts_info->rx_filters) {
0112         ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSINFO_RX_FILTERS,
0113                      &ts_info->rx_filters, NULL,
0114                      __HWTSTAMP_FILTER_CNT,
0115                      ts_rx_filter_names, compact);
0116         if (ret < 0)
0117             return ret;
0118     }
0119     if (ts_info->phc_index >= 0 &&
0120         nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index))
0121         return -EMSGSIZE;
0122 
0123     return 0;
0124 }
0125 
0126 const struct ethnl_request_ops ethnl_tsinfo_request_ops = {
0127     .request_cmd        = ETHTOOL_MSG_TSINFO_GET,
0128     .reply_cmd      = ETHTOOL_MSG_TSINFO_GET_REPLY,
0129     .hdr_attr       = ETHTOOL_A_TSINFO_HEADER,
0130     .req_info_size      = sizeof(struct tsinfo_req_info),
0131     .reply_data_size    = sizeof(struct tsinfo_reply_data),
0132 
0133     .prepare_data       = tsinfo_prepare_data,
0134     .reply_size     = tsinfo_reply_size,
0135     .fill_reply     = tsinfo_fill_reply,
0136 };