162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2021 NXP 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include "netlink.h" 662306a36Sopenharmony_ci#include "common.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_cistruct phc_vclocks_req_info { 962306a36Sopenharmony_ci struct ethnl_req_info base; 1062306a36Sopenharmony_ci}; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct phc_vclocks_reply_data { 1362306a36Sopenharmony_ci struct ethnl_reply_data base; 1462306a36Sopenharmony_ci int num; 1562306a36Sopenharmony_ci int *index; 1662306a36Sopenharmony_ci}; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define PHC_VCLOCKS_REPDATA(__reply_base) \ 1962306a36Sopenharmony_ci container_of(__reply_base, struct phc_vclocks_reply_data, base) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciconst struct nla_policy ethnl_phc_vclocks_get_policy[] = { 2262306a36Sopenharmony_ci [ETHTOOL_A_PHC_VCLOCKS_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int phc_vclocks_prepare_data(const struct ethnl_req_info *req_base, 2662306a36Sopenharmony_ci struct ethnl_reply_data *reply_base, 2762306a36Sopenharmony_ci const struct genl_info *info) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct phc_vclocks_reply_data *data = PHC_VCLOCKS_REPDATA(reply_base); 3062306a36Sopenharmony_ci struct net_device *dev = reply_base->dev; 3162306a36Sopenharmony_ci int ret; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci ret = ethnl_ops_begin(dev); 3462306a36Sopenharmony_ci if (ret < 0) 3562306a36Sopenharmony_ci return ret; 3662306a36Sopenharmony_ci data->num = ethtool_get_phc_vclocks(dev, &data->index); 3762306a36Sopenharmony_ci ethnl_ops_complete(dev); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci return ret; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic int phc_vclocks_reply_size(const struct ethnl_req_info *req_base, 4362306a36Sopenharmony_ci const struct ethnl_reply_data *reply_base) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci const struct phc_vclocks_reply_data *data = 4662306a36Sopenharmony_ci PHC_VCLOCKS_REPDATA(reply_base); 4762306a36Sopenharmony_ci int len = 0; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (data->num > 0) { 5062306a36Sopenharmony_ci len += nla_total_size(sizeof(u32)); 5162306a36Sopenharmony_ci len += nla_total_size(sizeof(s32) * data->num); 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return len; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic int phc_vclocks_fill_reply(struct sk_buff *skb, 5862306a36Sopenharmony_ci const struct ethnl_req_info *req_base, 5962306a36Sopenharmony_ci const struct ethnl_reply_data *reply_base) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci const struct phc_vclocks_reply_data *data = 6262306a36Sopenharmony_ci PHC_VCLOCKS_REPDATA(reply_base); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (data->num <= 0) 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (nla_put_u32(skb, ETHTOOL_A_PHC_VCLOCKS_NUM, data->num) || 6862306a36Sopenharmony_ci nla_put(skb, ETHTOOL_A_PHC_VCLOCKS_INDEX, 6962306a36Sopenharmony_ci sizeof(s32) * data->num, data->index)) 7062306a36Sopenharmony_ci return -EMSGSIZE; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void phc_vclocks_cleanup_data(struct ethnl_reply_data *reply_base) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci const struct phc_vclocks_reply_data *data = 7862306a36Sopenharmony_ci PHC_VCLOCKS_REPDATA(reply_base); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci kfree(data->index); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciconst struct ethnl_request_ops ethnl_phc_vclocks_request_ops = { 8462306a36Sopenharmony_ci .request_cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET, 8562306a36Sopenharmony_ci .reply_cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY, 8662306a36Sopenharmony_ci .hdr_attr = ETHTOOL_A_PHC_VCLOCKS_HEADER, 8762306a36Sopenharmony_ci .req_info_size = sizeof(struct phc_vclocks_req_info), 8862306a36Sopenharmony_ci .reply_data_size = sizeof(struct phc_vclocks_reply_data), 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci .prepare_data = phc_vclocks_prepare_data, 9162306a36Sopenharmony_ci .reply_size = phc_vclocks_reply_size, 9262306a36Sopenharmony_ci .fill_reply = phc_vclocks_fill_reply, 9362306a36Sopenharmony_ci .cleanup_data = phc_vclocks_cleanup_data, 9462306a36Sopenharmony_ci}; 95