1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <net/xdp_sock_drv.h>
8 struct channels_req_info
{
9 struct ethnl_req_info base
;
12 struct channels_reply_data
{
13 struct ethnl_reply_data base
;
14 struct ethtool_channels channels
;
17 #define CHANNELS_REPDATA(__reply_base) \
18 container_of(__reply_base, struct channels_reply_data, base)
20 const struct nla_policy ethnl_channels_get_policy
[] = {
21 [ETHTOOL_A_CHANNELS_HEADER
] =
22 NLA_POLICY_NESTED(ethnl_header_policy
),
25 static int channels_prepare_data(const struct ethnl_req_info
*req_base
,
26 struct ethnl_reply_data
*reply_base
,
27 const struct genl_info
*info
)
29 struct channels_reply_data
*data
= CHANNELS_REPDATA(reply_base
);
30 struct net_device
*dev
= reply_base
->dev
;
33 if (!dev
->ethtool_ops
->get_channels
)
35 ret
= ethnl_ops_begin(dev
);
38 dev
->ethtool_ops
->get_channels(dev
, &data
->channels
);
39 ethnl_ops_complete(dev
);
44 static int channels_reply_size(const struct ethnl_req_info
*req_base
,
45 const struct ethnl_reply_data
*reply_base
)
47 return nla_total_size(sizeof(u32
)) + /* _CHANNELS_RX_MAX */
48 nla_total_size(sizeof(u32
)) + /* _CHANNELS_TX_MAX */
49 nla_total_size(sizeof(u32
)) + /* _CHANNELS_OTHER_MAX */
50 nla_total_size(sizeof(u32
)) + /* _CHANNELS_COMBINED_MAX */
51 nla_total_size(sizeof(u32
)) + /* _CHANNELS_RX_COUNT */
52 nla_total_size(sizeof(u32
)) + /* _CHANNELS_TX_COUNT */
53 nla_total_size(sizeof(u32
)) + /* _CHANNELS_OTHER_COUNT */
54 nla_total_size(sizeof(u32
)); /* _CHANNELS_COMBINED_COUNT */
57 static int channels_fill_reply(struct sk_buff
*skb
,
58 const struct ethnl_req_info
*req_base
,
59 const struct ethnl_reply_data
*reply_base
)
61 const struct channels_reply_data
*data
= CHANNELS_REPDATA(reply_base
);
62 const struct ethtool_channels
*channels
= &data
->channels
;
64 if ((channels
->max_rx
&&
65 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_RX_MAX
,
67 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_RX_COUNT
,
68 channels
->rx_count
))) ||
70 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_TX_MAX
,
72 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_TX_COUNT
,
73 channels
->tx_count
))) ||
74 (channels
->max_other
&&
75 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_OTHER_MAX
,
76 channels
->max_other
) ||
77 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_OTHER_COUNT
,
78 channels
->other_count
))) ||
79 (channels
->max_combined
&&
80 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_COMBINED_MAX
,
81 channels
->max_combined
) ||
82 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_COMBINED_COUNT
,
83 channels
->combined_count
))))
91 const struct nla_policy ethnl_channels_set_policy
[] = {
92 [ETHTOOL_A_CHANNELS_HEADER
] =
93 NLA_POLICY_NESTED(ethnl_header_policy
),
94 [ETHTOOL_A_CHANNELS_RX_COUNT
] = { .type
= NLA_U32
},
95 [ETHTOOL_A_CHANNELS_TX_COUNT
] = { .type
= NLA_U32
},
96 [ETHTOOL_A_CHANNELS_OTHER_COUNT
] = { .type
= NLA_U32
},
97 [ETHTOOL_A_CHANNELS_COMBINED_COUNT
] = { .type
= NLA_U32
},
101 ethnl_set_channels_validate(struct ethnl_req_info
*req_info
,
102 struct genl_info
*info
)
104 const struct ethtool_ops
*ops
= req_info
->dev
->ethtool_ops
;
106 return ops
->get_channels
&& ops
->set_channels
? 1 : -EOPNOTSUPP
;
110 ethnl_set_channels(struct ethnl_req_info
*req_info
, struct genl_info
*info
)
112 unsigned int from_channel
, old_total
, i
;
113 bool mod
= false, mod_combined
= false;
114 struct net_device
*dev
= req_info
->dev
;
115 struct ethtool_channels channels
= {};
116 struct nlattr
**tb
= info
->attrs
;
120 dev
->ethtool_ops
->get_channels(dev
, &channels
);
121 old_total
= channels
.combined_count
+
122 max(channels
.rx_count
, channels
.tx_count
);
124 ethnl_update_u32(&channels
.rx_count
, tb
[ETHTOOL_A_CHANNELS_RX_COUNT
],
126 ethnl_update_u32(&channels
.tx_count
, tb
[ETHTOOL_A_CHANNELS_TX_COUNT
],
128 ethnl_update_u32(&channels
.other_count
,
129 tb
[ETHTOOL_A_CHANNELS_OTHER_COUNT
], &mod
);
130 ethnl_update_u32(&channels
.combined_count
,
131 tb
[ETHTOOL_A_CHANNELS_COMBINED_COUNT
], &mod_combined
);
136 /* ensure new channel counts are within limits */
137 if (channels
.rx_count
> channels
.max_rx
)
138 err_attr
= ETHTOOL_A_CHANNELS_RX_COUNT
;
139 else if (channels
.tx_count
> channels
.max_tx
)
140 err_attr
= ETHTOOL_A_CHANNELS_TX_COUNT
;
141 else if (channels
.other_count
> channels
.max_other
)
142 err_attr
= ETHTOOL_A_CHANNELS_OTHER_COUNT
;
143 else if (channels
.combined_count
> channels
.max_combined
)
144 err_attr
= ETHTOOL_A_CHANNELS_COMBINED_COUNT
;
148 NL_SET_ERR_MSG_ATTR(info
->extack
, tb
[err_attr
],
149 "requested channel count exceeds maximum");
153 /* ensure there is at least one RX and one TX channel */
154 if (!channels
.combined_count
&& !channels
.rx_count
)
155 err_attr
= ETHTOOL_A_CHANNELS_RX_COUNT
;
156 else if (!channels
.combined_count
&& !channels
.tx_count
)
157 err_attr
= ETHTOOL_A_CHANNELS_TX_COUNT
;
162 err_attr
= ETHTOOL_A_CHANNELS_COMBINED_COUNT
;
163 NL_SET_ERR_MSG_ATTR(info
->extack
, tb
[err_attr
],
164 "requested channel counts would result in no RX or TX channel being configured");
168 ret
= ethtool_check_max_channel(dev
, channels
, info
);
172 /* Disabling channels, query zero-copy AF_XDP sockets */
173 from_channel
= channels
.combined_count
+
174 min(channels
.rx_count
, channels
.tx_count
);
175 for (i
= from_channel
; i
< old_total
; i
++)
176 if (xsk_get_pool_from_qid(dev
, i
)) {
177 GENL_SET_ERR_MSG(info
, "requested channel counts are too low for existing zerocopy AF_XDP sockets");
181 ret
= dev
->ethtool_ops
->set_channels(dev
, &channels
);
182 return ret
< 0 ? ret
: 1;
185 const struct ethnl_request_ops ethnl_channels_request_ops
= {
186 .request_cmd
= ETHTOOL_MSG_CHANNELS_GET
,
187 .reply_cmd
= ETHTOOL_MSG_CHANNELS_GET_REPLY
,
188 .hdr_attr
= ETHTOOL_A_CHANNELS_HEADER
,
189 .req_info_size
= sizeof(struct channels_req_info
),
190 .reply_data_size
= sizeof(struct channels_reply_data
),
192 .prepare_data
= channels_prepare_data
,
193 .reply_size
= channels_reply_size
,
194 .fill_reply
= channels_fill_reply
,
196 .set_validate
= ethnl_set_channels_validate
,
197 .set
= ethnl_set_channels
,
198 .set_ntf_cmd
= ETHTOOL_MSG_CHANNELS_NTF
,