Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/ethtool/debug.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
3
#include "netlink.h"
4
#include "common.h"
5
#include "bitset.h"
6
7
struct debug_req_info {
8
struct ethnl_req_info base;
9
};
10
11
struct debug_reply_data {
12
struct ethnl_reply_data base;
13
u32 msg_mask;
14
};
15
16
#define DEBUG_REPDATA(__reply_base) \
17
container_of(__reply_base, struct debug_reply_data, base)
18
19
const struct nla_policy ethnl_debug_get_policy[] = {
20
[ETHTOOL_A_DEBUG_HEADER] =
21
NLA_POLICY_NESTED(ethnl_header_policy),
22
};
23
24
static int debug_prepare_data(const struct ethnl_req_info *req_base,
25
struct ethnl_reply_data *reply_base,
26
const struct genl_info *info)
27
{
28
struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
29
struct net_device *dev = reply_base->dev;
30
int ret;
31
32
if (!dev->ethtool_ops->get_msglevel)
33
return -EOPNOTSUPP;
34
35
ret = ethnl_ops_begin(dev);
36
if (ret < 0)
37
return ret;
38
data->msg_mask = dev->ethtool_ops->get_msglevel(dev);
39
ethnl_ops_complete(dev);
40
41
return 0;
42
}
43
44
static int debug_reply_size(const struct ethnl_req_info *req_base,
45
const struct ethnl_reply_data *reply_base)
46
{
47
const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
48
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
49
50
return ethnl_bitset32_size(&data->msg_mask, NULL, NETIF_MSG_CLASS_COUNT,
51
netif_msg_class_names, compact);
52
}
53
54
static int debug_fill_reply(struct sk_buff *skb,
55
const struct ethnl_req_info *req_base,
56
const struct ethnl_reply_data *reply_base)
57
{
58
const struct debug_reply_data *data = DEBUG_REPDATA(reply_base);
59
bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
60
61
return ethnl_put_bitset32(skb, ETHTOOL_A_DEBUG_MSGMASK, &data->msg_mask,
62
NULL, NETIF_MSG_CLASS_COUNT,
63
netif_msg_class_names, compact);
64
}
65
66
/* DEBUG_SET */
67
68
const struct nla_policy ethnl_debug_set_policy[] = {
69
[ETHTOOL_A_DEBUG_HEADER] =
70
NLA_POLICY_NESTED(ethnl_header_policy),
71
[ETHTOOL_A_DEBUG_MSGMASK] = { .type = NLA_NESTED },
72
};
73
74
static int
75
ethnl_set_debug_validate(struct ethnl_req_info *req_info,
76
struct genl_info *info)
77
{
78
const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
79
80
return ops->get_msglevel && ops->set_msglevel ? 1 : -EOPNOTSUPP;
81
}
82
83
static int
84
ethnl_set_debug(struct ethnl_req_info *req_info, struct genl_info *info)
85
{
86
struct net_device *dev = req_info->dev;
87
struct nlattr **tb = info->attrs;
88
bool mod = false;
89
u32 msg_mask;
90
int ret;
91
92
msg_mask = dev->ethtool_ops->get_msglevel(dev);
93
ret = ethnl_update_bitset32(&msg_mask, NETIF_MSG_CLASS_COUNT,
94
tb[ETHTOOL_A_DEBUG_MSGMASK],
95
netif_msg_class_names, info->extack, &mod);
96
if (ret < 0 || !mod)
97
return ret;
98
99
dev->ethtool_ops->set_msglevel(dev, msg_mask);
100
return 1;
101
}
102
103
const struct ethnl_request_ops ethnl_debug_request_ops = {
104
.request_cmd = ETHTOOL_MSG_DEBUG_GET,
105
.reply_cmd = ETHTOOL_MSG_DEBUG_GET_REPLY,
106
.hdr_attr = ETHTOOL_A_DEBUG_HEADER,
107
.req_info_size = sizeof(struct debug_req_info),
108
.reply_data_size = sizeof(struct debug_reply_data),
109
110
.prepare_data = debug_prepare_data,
111
.reply_size = debug_reply_size,
112
.fill_reply = debug_fill_reply,
113
114
.set_validate = ethnl_set_debug_validate,
115
.set = ethnl_set_debug,
116
.set_ntf_cmd = ETHTOOL_MSG_DEBUG_NTF,
117
};
118
119