Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 #include "netlink.h"
0004 #include "common.h"
0005 #include "bitset.h"
0006 
0007 struct debug_req_info {
0008     struct ethnl_req_info       base;
0009 };
0010 
0011 struct debug_reply_data {
0012     struct ethnl_reply_data     base;
0013     u32             msg_mask;
0014 };
0015 
0016 #define DEBUG_REPDATA(__reply_base) \
0017     container_of(__reply_base, struct debug_reply_data, base)
0018 
0019 const struct nla_policy ethnl_debug_get_policy[] = {
0020     [ETHTOOL_A_DEBUG_HEADER]    =
0021         NLA_POLICY_NESTED(ethnl_header_policy),
0022 };
0023 
0024 static int debug_prepare_data(const struct ethnl_req_info *req_base,
0025                   struct ethnl_reply_data *reply_base,
0026                   struct genl_info *info)
0027 {
0028     struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
0029     struct net_device *dev = reply_base->dev;
0030     int ret;
0031 
0032     if (!dev->ethtool_ops->get_msglevel)
0033         return -EOPNOTSUPP;
0034 
0035     ret = ethnl_ops_begin(dev);
0036     if (ret < 0)
0037         return ret;
0038     data->msg_mask = dev->ethtool_ops->get_msglevel(dev);
0039     ethnl_ops_complete(dev);
0040 
0041     return 0;
0042 }
0043 
0044 static int debug_reply_size(const struct ethnl_req_info *req_base,
0045                 const struct ethnl_reply_data *reply_base)
0046 {
0047     const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
0048     bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
0049 
0050     return ethnl_bitset32_size(&data->msg_mask, NULL, NETIF_MSG_CLASS_COUNT,
0051                    netif_msg_class_names, compact);
0052 }
0053 
0054 static int debug_fill_reply(struct sk_buff *skb,
0055                 const struct ethnl_req_info *req_base,
0056                 const struct ethnl_reply_data *reply_base)
0057 {
0058     const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
0059     bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
0060 
0061     return ethnl_put_bitset32(skb, ETHTOOL_A_DEBUG_MSGMASK, &data->msg_mask,
0062                   NULL, NETIF_MSG_CLASS_COUNT,
0063                   netif_msg_class_names, compact);
0064 }
0065 
0066 const struct ethnl_request_ops ethnl_debug_request_ops = {
0067     .request_cmd        = ETHTOOL_MSG_DEBUG_GET,
0068     .reply_cmd      = ETHTOOL_MSG_DEBUG_GET_REPLY,
0069     .hdr_attr       = ETHTOOL_A_DEBUG_HEADER,
0070     .req_info_size      = sizeof(struct debug_req_info),
0071     .reply_data_size    = sizeof(struct debug_reply_data),
0072 
0073     .prepare_data       = debug_prepare_data,
0074     .reply_size     = debug_reply_size,
0075     .fill_reply     = debug_fill_reply,
0076 };
0077 
0078 /* DEBUG_SET */
0079 
0080 const struct nla_policy ethnl_debug_set_policy[] = {
0081     [ETHTOOL_A_DEBUG_HEADER]    =
0082         NLA_POLICY_NESTED(ethnl_header_policy),
0083     [ETHTOOL_A_DEBUG_MSGMASK]   = { .type = NLA_NESTED },
0084 };
0085 
0086 int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
0087 {
0088     struct ethnl_req_info req_info = {};
0089     struct nlattr **tb = info->attrs;
0090     struct net_device *dev;
0091     bool mod = false;
0092     u32 msg_mask;
0093     int ret;
0094 
0095     ret = ethnl_parse_header_dev_get(&req_info,
0096                      tb[ETHTOOL_A_DEBUG_HEADER],
0097                      genl_info_net(info), info->extack,
0098                      true);
0099     if (ret < 0)
0100         return ret;
0101     dev = req_info.dev;
0102     ret = -EOPNOTSUPP;
0103     if (!dev->ethtool_ops->get_msglevel || !dev->ethtool_ops->set_msglevel)
0104         goto out_dev;
0105 
0106     rtnl_lock();
0107     ret = ethnl_ops_begin(dev);
0108     if (ret < 0)
0109         goto out_rtnl;
0110 
0111     msg_mask = dev->ethtool_ops->get_msglevel(dev);
0112     ret = ethnl_update_bitset32(&msg_mask, NETIF_MSG_CLASS_COUNT,
0113                     tb[ETHTOOL_A_DEBUG_MSGMASK],
0114                     netif_msg_class_names, info->extack, &mod);
0115     if (ret < 0 || !mod)
0116         goto out_ops;
0117 
0118     dev->ethtool_ops->set_msglevel(dev, msg_mask);
0119     ethtool_notify(dev, ETHTOOL_MSG_DEBUG_NTF, NULL);
0120 
0121 out_ops:
0122     ethnl_ops_complete(dev);
0123 out_rtnl:
0124     rtnl_unlock();
0125 out_dev:
0126     ethnl_parse_header_dev_put(&req_info);
0127     return ret;
0128 }