Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2021 NXP
0004  */
0005 #include "netlink.h"
0006 #include "common.h"
0007 
0008 struct phc_vclocks_req_info {
0009     struct ethnl_req_info       base;
0010 };
0011 
0012 struct phc_vclocks_reply_data {
0013     struct ethnl_reply_data     base;
0014     int             num;
0015     int             *index;
0016 };
0017 
0018 #define PHC_VCLOCKS_REPDATA(__reply_base) \
0019     container_of(__reply_base, struct phc_vclocks_reply_data, base)
0020 
0021 const struct nla_policy ethnl_phc_vclocks_get_policy[] = {
0022     [ETHTOOL_A_PHC_VCLOCKS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
0023 };
0024 
0025 static int phc_vclocks_prepare_data(const struct ethnl_req_info *req_base,
0026                     struct ethnl_reply_data *reply_base,
0027                     struct genl_info *info)
0028 {
0029     struct phc_vclocks_reply_data *data = PHC_VCLOCKS_REPDATA(reply_base);
0030     struct net_device *dev = reply_base->dev;
0031     int ret;
0032 
0033     ret = ethnl_ops_begin(dev);
0034     if (ret < 0)
0035         return ret;
0036     data->num = ethtool_get_phc_vclocks(dev, &data->index);
0037     ethnl_ops_complete(dev);
0038 
0039     return ret;
0040 }
0041 
0042 static int phc_vclocks_reply_size(const struct ethnl_req_info *req_base,
0043                   const struct ethnl_reply_data *reply_base)
0044 {
0045     const struct phc_vclocks_reply_data *data =
0046         PHC_VCLOCKS_REPDATA(reply_base);
0047     int len = 0;
0048 
0049     if (data->num > 0) {
0050         len += nla_total_size(sizeof(u32));
0051         len += nla_total_size(sizeof(s32) * data->num);
0052     }
0053 
0054     return len;
0055 }
0056 
0057 static int phc_vclocks_fill_reply(struct sk_buff *skb,
0058                   const struct ethnl_req_info *req_base,
0059                   const struct ethnl_reply_data *reply_base)
0060 {
0061     const struct phc_vclocks_reply_data *data =
0062         PHC_VCLOCKS_REPDATA(reply_base);
0063 
0064     if (data->num <= 0)
0065         return 0;
0066 
0067     if (nla_put_u32(skb, ETHTOOL_A_PHC_VCLOCKS_NUM, data->num) ||
0068         nla_put(skb, ETHTOOL_A_PHC_VCLOCKS_INDEX,
0069             sizeof(s32) * data->num, data->index))
0070         return -EMSGSIZE;
0071 
0072     return 0;
0073 }
0074 
0075 static void phc_vclocks_cleanup_data(struct ethnl_reply_data *reply_base)
0076 {
0077     const struct phc_vclocks_reply_data *data =
0078         PHC_VCLOCKS_REPDATA(reply_base);
0079 
0080     kfree(data->index);
0081 }
0082 
0083 const struct ethnl_request_ops ethnl_phc_vclocks_request_ops = {
0084     .request_cmd        = ETHTOOL_MSG_PHC_VCLOCKS_GET,
0085     .reply_cmd      = ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
0086     .hdr_attr       = ETHTOOL_A_PHC_VCLOCKS_HEADER,
0087     .req_info_size      = sizeof(struct phc_vclocks_req_info),
0088     .reply_data_size    = sizeof(struct phc_vclocks_reply_data),
0089 
0090     .prepare_data       = phc_vclocks_prepare_data,
0091     .reply_size     = phc_vclocks_reply_size,
0092     .fill_reply     = phc_vclocks_fill_reply,
0093     .cleanup_data       = phc_vclocks_cleanup_data,
0094 };