1c156174aSYangbo Lu // SPDX-License-Identifier: GPL-2.0-only
2c156174aSYangbo Lu /*
3c156174aSYangbo Lu * Copyright 2021 NXP
4c156174aSYangbo Lu */
5c156174aSYangbo Lu #include "netlink.h"
6c156174aSYangbo Lu #include "common.h"
7c156174aSYangbo Lu
8c156174aSYangbo Lu struct phc_vclocks_req_info {
9c156174aSYangbo Lu struct ethnl_req_info base;
10c156174aSYangbo Lu };
11c156174aSYangbo Lu
12c156174aSYangbo Lu struct phc_vclocks_reply_data {
13c156174aSYangbo Lu struct ethnl_reply_data base;
14c156174aSYangbo Lu int num;
15c156174aSYangbo Lu int *index;
16c156174aSYangbo Lu };
17c156174aSYangbo Lu
18c156174aSYangbo Lu #define PHC_VCLOCKS_REPDATA(__reply_base) \
19c156174aSYangbo Lu container_of(__reply_base, struct phc_vclocks_reply_data, base)
20c156174aSYangbo Lu
21c156174aSYangbo Lu const struct nla_policy ethnl_phc_vclocks_get_policy[] = {
22c156174aSYangbo Lu [ETHTOOL_A_PHC_VCLOCKS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
23c156174aSYangbo Lu };
24c156174aSYangbo Lu
phc_vclocks_prepare_data(const struct ethnl_req_info * req_base,struct ethnl_reply_data * reply_base,const struct genl_info * info)25c156174aSYangbo Lu static int phc_vclocks_prepare_data(const struct ethnl_req_info *req_base,
26c156174aSYangbo Lu struct ethnl_reply_data *reply_base,
27*f946270dSJakub Kicinski const struct genl_info *info)
28c156174aSYangbo Lu {
29c156174aSYangbo Lu struct phc_vclocks_reply_data *data = PHC_VCLOCKS_REPDATA(reply_base);
30c156174aSYangbo Lu struct net_device *dev = reply_base->dev;
31c156174aSYangbo Lu int ret;
32c156174aSYangbo Lu
33c156174aSYangbo Lu ret = ethnl_ops_begin(dev);
34c156174aSYangbo Lu if (ret < 0)
35c156174aSYangbo Lu return ret;
36c156174aSYangbo Lu data->num = ethtool_get_phc_vclocks(dev, &data->index);
37c156174aSYangbo Lu ethnl_ops_complete(dev);
38c156174aSYangbo Lu
39c156174aSYangbo Lu return ret;
40c156174aSYangbo Lu }
41c156174aSYangbo Lu
phc_vclocks_reply_size(const struct ethnl_req_info * req_base,const struct ethnl_reply_data * reply_base)42c156174aSYangbo Lu static int phc_vclocks_reply_size(const struct ethnl_req_info *req_base,
43c156174aSYangbo Lu const struct ethnl_reply_data *reply_base)
44c156174aSYangbo Lu {
45c156174aSYangbo Lu const struct phc_vclocks_reply_data *data =
46c156174aSYangbo Lu PHC_VCLOCKS_REPDATA(reply_base);
47c156174aSYangbo Lu int len = 0;
48c156174aSYangbo Lu
49c156174aSYangbo Lu if (data->num > 0) {
50c156174aSYangbo Lu len += nla_total_size(sizeof(u32));
51c156174aSYangbo Lu len += nla_total_size(sizeof(s32) * data->num);
52c156174aSYangbo Lu }
53c156174aSYangbo Lu
54c156174aSYangbo Lu return len;
55c156174aSYangbo Lu }
56c156174aSYangbo Lu
phc_vclocks_fill_reply(struct sk_buff * skb,const struct ethnl_req_info * req_base,const struct ethnl_reply_data * reply_base)57c156174aSYangbo Lu static int phc_vclocks_fill_reply(struct sk_buff *skb,
58c156174aSYangbo Lu const struct ethnl_req_info *req_base,
59c156174aSYangbo Lu const struct ethnl_reply_data *reply_base)
60c156174aSYangbo Lu {
61c156174aSYangbo Lu const struct phc_vclocks_reply_data *data =
62c156174aSYangbo Lu PHC_VCLOCKS_REPDATA(reply_base);
63c156174aSYangbo Lu
64c156174aSYangbo Lu if (data->num <= 0)
65c156174aSYangbo Lu return 0;
66c156174aSYangbo Lu
67c156174aSYangbo Lu if (nla_put_u32(skb, ETHTOOL_A_PHC_VCLOCKS_NUM, data->num) ||
68c156174aSYangbo Lu nla_put(skb, ETHTOOL_A_PHC_VCLOCKS_INDEX,
69c156174aSYangbo Lu sizeof(s32) * data->num, data->index))
70c156174aSYangbo Lu return -EMSGSIZE;
71c156174aSYangbo Lu
72c156174aSYangbo Lu return 0;
73c156174aSYangbo Lu }
74c156174aSYangbo Lu
phc_vclocks_cleanup_data(struct ethnl_reply_data * reply_base)75c156174aSYangbo Lu static void phc_vclocks_cleanup_data(struct ethnl_reply_data *reply_base)
76c156174aSYangbo Lu {
77c156174aSYangbo Lu const struct phc_vclocks_reply_data *data =
78c156174aSYangbo Lu PHC_VCLOCKS_REPDATA(reply_base);
79c156174aSYangbo Lu
80c156174aSYangbo Lu kfree(data->index);
81c156174aSYangbo Lu }
82c156174aSYangbo Lu
83c156174aSYangbo Lu const struct ethnl_request_ops ethnl_phc_vclocks_request_ops = {
84c156174aSYangbo Lu .request_cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET,
85c156174aSYangbo Lu .reply_cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
86c156174aSYangbo Lu .hdr_attr = ETHTOOL_A_PHC_VCLOCKS_HEADER,
87c156174aSYangbo Lu .req_info_size = sizeof(struct phc_vclocks_req_info),
88c156174aSYangbo Lu .reply_data_size = sizeof(struct phc_vclocks_reply_data),
89c156174aSYangbo Lu
90c156174aSYangbo Lu .prepare_data = phc_vclocks_prepare_data,
91c156174aSYangbo Lu .reply_size = phc_vclocks_reply_size,
92c156174aSYangbo Lu .fill_reply = phc_vclocks_fill_reply,
93c156174aSYangbo Lu .cleanup_data = phc_vclocks_cleanup_data,
94c156174aSYangbo Lu };
95