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