0001
0002
0003
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 };