xref: /openbmc/linux/net/ethtool/phc_vclocks.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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