1 // SPDX-License-Identifier: GPL-2.0-only
7 struct linkmodes_req_info
{
8 struct ethnl_req_info base
;
11 struct linkmodes_reply_data
{
12 struct ethnl_reply_data base
;
13 struct ethtool_link_ksettings ksettings
;
14 struct ethtool_link_settings
*lsettings
;
18 #define LINKMODES_REPDATA(__reply_base) \
19 container_of(__reply_base, struct linkmodes_reply_data, base)
21 const struct nla_policy ethnl_linkmodes_get_policy
[] = {
22 [ETHTOOL_A_LINKMODES_HEADER
] =
23 NLA_POLICY_NESTED(ethnl_header_policy
),
26 static int linkmodes_prepare_data(const struct ethnl_req_info
*req_base
,
27 struct ethnl_reply_data
*reply_base
,
28 struct genl_info
*info
)
30 struct linkmodes_reply_data
*data
= LINKMODES_REPDATA(reply_base
);
31 struct net_device
*dev
= reply_base
->dev
;
34 data
->lsettings
= &data
->ksettings
.base
;
36 ret
= ethnl_ops_begin(dev
);
40 ret
= __ethtool_get_link_ksettings(dev
, &data
->ksettings
);
41 if (ret
< 0 && info
) {
42 GENL_SET_ERR_MSG(info
, "failed to retrieve link settings");
47 bitmap_empty(data
->ksettings
.link_modes
.lp_advertising
,
48 __ETHTOOL_LINK_MODE_MASK_NBITS
);
51 ethnl_ops_complete(dev
);
55 static int linkmodes_reply_size(const struct ethnl_req_info
*req_base
,
56 const struct ethnl_reply_data
*reply_base
)
58 const struct linkmodes_reply_data
*data
= LINKMODES_REPDATA(reply_base
);
59 const struct ethtool_link_ksettings
*ksettings
= &data
->ksettings
;
60 const struct ethtool_link_settings
*lsettings
= &ksettings
->base
;
61 bool compact
= req_base
->flags
& ETHTOOL_FLAG_COMPACT_BITSETS
;
64 len
= nla_total_size(sizeof(u8
)) /* LINKMODES_AUTONEG */
65 + nla_total_size(sizeof(u32
)) /* LINKMODES_SPEED */
66 + nla_total_size(sizeof(u8
)) /* LINKMODES_DUPLEX */
68 ret
= ethnl_bitset_size(ksettings
->link_modes
.advertising
,
69 ksettings
->link_modes
.supported
,
70 __ETHTOOL_LINK_MODE_MASK_NBITS
,
71 link_mode_names
, compact
);
75 if (!data
->peer_empty
) {
76 ret
= ethnl_bitset_size(ksettings
->link_modes
.lp_advertising
,
77 NULL
, __ETHTOOL_LINK_MODE_MASK_NBITS
,
78 link_mode_names
, compact
);
84 if (lsettings
->master_slave_cfg
!= MASTER_SLAVE_CFG_UNSUPPORTED
)
85 len
+= nla_total_size(sizeof(u8
));
87 if (lsettings
->master_slave_state
!= MASTER_SLAVE_STATE_UNSUPPORTED
)
88 len
+= nla_total_size(sizeof(u8
));
93 static int linkmodes_fill_reply(struct sk_buff
*skb
,
94 const struct ethnl_req_info
*req_base
,
95 const struct ethnl_reply_data
*reply_base
)
97 const struct linkmodes_reply_data
*data
= LINKMODES_REPDATA(reply_base
);
98 const struct ethtool_link_ksettings
*ksettings
= &data
->ksettings
;
99 const struct ethtool_link_settings
*lsettings
= &ksettings
->base
;
100 bool compact
= req_base
->flags
& ETHTOOL_FLAG_COMPACT_BITSETS
;
103 if (nla_put_u8(skb
, ETHTOOL_A_LINKMODES_AUTONEG
, lsettings
->autoneg
))
106 ret
= ethnl_put_bitset(skb
, ETHTOOL_A_LINKMODES_OURS
,
107 ksettings
->link_modes
.advertising
,
108 ksettings
->link_modes
.supported
,
109 __ETHTOOL_LINK_MODE_MASK_NBITS
, link_mode_names
,
113 if (!data
->peer_empty
) {
114 ret
= ethnl_put_bitset(skb
, ETHTOOL_A_LINKMODES_PEER
,
115 ksettings
->link_modes
.lp_advertising
,
116 NULL
, __ETHTOOL_LINK_MODE_MASK_NBITS
,
117 link_mode_names
, compact
);
122 if (nla_put_u32(skb
, ETHTOOL_A_LINKMODES_SPEED
, lsettings
->speed
) ||
123 nla_put_u8(skb
, ETHTOOL_A_LINKMODES_DUPLEX
, lsettings
->duplex
))
126 if (lsettings
->master_slave_cfg
!= MASTER_SLAVE_CFG_UNSUPPORTED
&&
127 nla_put_u8(skb
, ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG
,
128 lsettings
->master_slave_cfg
))
131 if (lsettings
->master_slave_state
!= MASTER_SLAVE_STATE_UNSUPPORTED
&&
132 nla_put_u8(skb
, ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE
,
133 lsettings
->master_slave_state
))
139 const struct ethnl_request_ops ethnl_linkmodes_request_ops
= {
140 .request_cmd
= ETHTOOL_MSG_LINKMODES_GET
,
141 .reply_cmd
= ETHTOOL_MSG_LINKMODES_GET_REPLY
,
142 .hdr_attr
= ETHTOOL_A_LINKMODES_HEADER
,
143 .req_info_size
= sizeof(struct linkmodes_req_info
),
144 .reply_data_size
= sizeof(struct linkmodes_reply_data
),
146 .prepare_data
= linkmodes_prepare_data
,
147 .reply_size
= linkmodes_reply_size
,
148 .fill_reply
= linkmodes_fill_reply
,
153 struct link_mode_info
{
158 #define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \
159 [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \
160 .speed = SPEED_ ## _speed, \
161 .duplex = __DUPLEX_ ## _duplex \
163 #define __DUPLEX_Half DUPLEX_HALF
164 #define __DUPLEX_Full DUPLEX_FULL
165 #define __DEFINE_SPECIAL_MODE_PARAMS(_mode) \
166 [ETHTOOL_LINK_MODE_ ## _mode ## _BIT] = { \
167 .speed = SPEED_UNKNOWN, \
168 .duplex = DUPLEX_UNKNOWN, \
171 static const struct link_mode_info link_mode_params
[] = {
172 __DEFINE_LINK_MODE_PARAMS(10, T
, Half
),
173 __DEFINE_LINK_MODE_PARAMS(10, T
, Full
),
174 __DEFINE_LINK_MODE_PARAMS(100, T
, Half
),
175 __DEFINE_LINK_MODE_PARAMS(100, T
, Full
),
176 __DEFINE_LINK_MODE_PARAMS(1000, T
, Half
),
177 __DEFINE_LINK_MODE_PARAMS(1000, T
, Full
),
178 __DEFINE_SPECIAL_MODE_PARAMS(Autoneg
),
179 __DEFINE_SPECIAL_MODE_PARAMS(TP
),
180 __DEFINE_SPECIAL_MODE_PARAMS(AUI
),
181 __DEFINE_SPECIAL_MODE_PARAMS(MII
),
182 __DEFINE_SPECIAL_MODE_PARAMS(FIBRE
),
183 __DEFINE_SPECIAL_MODE_PARAMS(BNC
),
184 __DEFINE_LINK_MODE_PARAMS(10000, T
, Full
),
185 __DEFINE_SPECIAL_MODE_PARAMS(Pause
),
186 __DEFINE_SPECIAL_MODE_PARAMS(Asym_Pause
),
187 __DEFINE_LINK_MODE_PARAMS(2500, X
, Full
),
188 __DEFINE_SPECIAL_MODE_PARAMS(Backplane
),
189 __DEFINE_LINK_MODE_PARAMS(1000, KX
, Full
),
190 __DEFINE_LINK_MODE_PARAMS(10000, KX4
, Full
),
191 __DEFINE_LINK_MODE_PARAMS(10000, KR
, Full
),
192 [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT
] = {
193 .speed
= SPEED_10000
,
194 .duplex
= DUPLEX_FULL
,
196 __DEFINE_LINK_MODE_PARAMS(20000, MLD2
, Full
),
197 __DEFINE_LINK_MODE_PARAMS(20000, KR2
, Full
),
198 __DEFINE_LINK_MODE_PARAMS(40000, KR4
, Full
),
199 __DEFINE_LINK_MODE_PARAMS(40000, CR4
, Full
),
200 __DEFINE_LINK_MODE_PARAMS(40000, SR4
, Full
),
201 __DEFINE_LINK_MODE_PARAMS(40000, LR4
, Full
),
202 __DEFINE_LINK_MODE_PARAMS(56000, KR4
, Full
),
203 __DEFINE_LINK_MODE_PARAMS(56000, CR4
, Full
),
204 __DEFINE_LINK_MODE_PARAMS(56000, SR4
, Full
),
205 __DEFINE_LINK_MODE_PARAMS(56000, LR4
, Full
),
206 __DEFINE_LINK_MODE_PARAMS(25000, CR
, Full
),
207 __DEFINE_LINK_MODE_PARAMS(25000, KR
, Full
),
208 __DEFINE_LINK_MODE_PARAMS(25000, SR
, Full
),
209 __DEFINE_LINK_MODE_PARAMS(50000, CR2
, Full
),
210 __DEFINE_LINK_MODE_PARAMS(50000, KR2
, Full
),
211 __DEFINE_LINK_MODE_PARAMS(100000, KR4
, Full
),
212 __DEFINE_LINK_MODE_PARAMS(100000, SR4
, Full
),
213 __DEFINE_LINK_MODE_PARAMS(100000, CR4
, Full
),
214 __DEFINE_LINK_MODE_PARAMS(100000, LR4_ER4
, Full
),
215 __DEFINE_LINK_MODE_PARAMS(50000, SR2
, Full
),
216 __DEFINE_LINK_MODE_PARAMS(1000, X
, Full
),
217 __DEFINE_LINK_MODE_PARAMS(10000, CR
, Full
),
218 __DEFINE_LINK_MODE_PARAMS(10000, SR
, Full
),
219 __DEFINE_LINK_MODE_PARAMS(10000, LR
, Full
),
220 __DEFINE_LINK_MODE_PARAMS(10000, LRM
, Full
),
221 __DEFINE_LINK_MODE_PARAMS(10000, ER
, Full
),
222 __DEFINE_LINK_MODE_PARAMS(2500, T
, Full
),
223 __DEFINE_LINK_MODE_PARAMS(5000, T
, Full
),
224 __DEFINE_SPECIAL_MODE_PARAMS(FEC_NONE
),
225 __DEFINE_SPECIAL_MODE_PARAMS(FEC_RS
),
226 __DEFINE_SPECIAL_MODE_PARAMS(FEC_BASER
),
227 __DEFINE_LINK_MODE_PARAMS(50000, KR
, Full
),
228 __DEFINE_LINK_MODE_PARAMS(50000, SR
, Full
),
229 __DEFINE_LINK_MODE_PARAMS(50000, CR
, Full
),
230 __DEFINE_LINK_MODE_PARAMS(50000, LR_ER_FR
, Full
),
231 __DEFINE_LINK_MODE_PARAMS(50000, DR
, Full
),
232 __DEFINE_LINK_MODE_PARAMS(100000, KR2
, Full
),
233 __DEFINE_LINK_MODE_PARAMS(100000, SR2
, Full
),
234 __DEFINE_LINK_MODE_PARAMS(100000, CR2
, Full
),
235 __DEFINE_LINK_MODE_PARAMS(100000, LR2_ER2_FR2
, Full
),
236 __DEFINE_LINK_MODE_PARAMS(100000, DR2
, Full
),
237 __DEFINE_LINK_MODE_PARAMS(200000, KR4
, Full
),
238 __DEFINE_LINK_MODE_PARAMS(200000, SR4
, Full
),
239 __DEFINE_LINK_MODE_PARAMS(200000, LR4_ER4_FR4
, Full
),
240 __DEFINE_LINK_MODE_PARAMS(200000, DR4
, Full
),
241 __DEFINE_LINK_MODE_PARAMS(200000, CR4
, Full
),
242 __DEFINE_LINK_MODE_PARAMS(100, T1
, Full
),
243 __DEFINE_LINK_MODE_PARAMS(1000, T1
, Full
),
244 __DEFINE_LINK_MODE_PARAMS(400000, KR8
, Full
),
245 __DEFINE_LINK_MODE_PARAMS(400000, SR8
, Full
),
246 __DEFINE_LINK_MODE_PARAMS(400000, LR8_ER8_FR8
, Full
),
247 __DEFINE_LINK_MODE_PARAMS(400000, DR8
, Full
),
248 __DEFINE_LINK_MODE_PARAMS(400000, CR8
, Full
),
249 __DEFINE_SPECIAL_MODE_PARAMS(FEC_LLRS
),
250 __DEFINE_LINK_MODE_PARAMS(100000, KR
, Full
),
251 __DEFINE_LINK_MODE_PARAMS(100000, SR
, Full
),
252 __DEFINE_LINK_MODE_PARAMS(100000, LR_ER_FR
, Full
),
253 __DEFINE_LINK_MODE_PARAMS(100000, DR
, Full
),
254 __DEFINE_LINK_MODE_PARAMS(100000, CR
, Full
),
255 __DEFINE_LINK_MODE_PARAMS(200000, KR2
, Full
),
256 __DEFINE_LINK_MODE_PARAMS(200000, SR2
, Full
),
257 __DEFINE_LINK_MODE_PARAMS(200000, LR2_ER2_FR2
, Full
),
258 __DEFINE_LINK_MODE_PARAMS(200000, DR2
, Full
),
259 __DEFINE_LINK_MODE_PARAMS(200000, CR2
, Full
),
260 __DEFINE_LINK_MODE_PARAMS(400000, KR4
, Full
),
261 __DEFINE_LINK_MODE_PARAMS(400000, SR4
, Full
),
262 __DEFINE_LINK_MODE_PARAMS(400000, LR4_ER4_FR4
, Full
),
263 __DEFINE_LINK_MODE_PARAMS(400000, DR4
, Full
),
264 __DEFINE_LINK_MODE_PARAMS(400000, CR4
, Full
),
265 __DEFINE_LINK_MODE_PARAMS(100, FX
, Half
),
266 __DEFINE_LINK_MODE_PARAMS(100, FX
, Full
),
269 const struct nla_policy ethnl_linkmodes_set_policy
[] = {
270 [ETHTOOL_A_LINKMODES_HEADER
] =
271 NLA_POLICY_NESTED(ethnl_header_policy
),
272 [ETHTOOL_A_LINKMODES_AUTONEG
] = { .type
= NLA_U8
},
273 [ETHTOOL_A_LINKMODES_OURS
] = { .type
= NLA_NESTED
},
274 [ETHTOOL_A_LINKMODES_SPEED
] = { .type
= NLA_U32
},
275 [ETHTOOL_A_LINKMODES_DUPLEX
] = { .type
= NLA_U8
},
276 [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG
] = { .type
= NLA_U8
},
279 /* Set advertised link modes to all supported modes matching requested speed
280 * and duplex values. Called when autonegotiation is on, speed or duplex is
281 * requested but no link mode change. This is done in userspace with ioctl()
282 * interface, move it into kernel for netlink.
283 * Returns true if advertised modes bitmap was modified.
285 static bool ethnl_auto_linkmodes(struct ethtool_link_ksettings
*ksettings
,
286 bool req_speed
, bool req_duplex
)
288 unsigned long *advertising
= ksettings
->link_modes
.advertising
;
289 unsigned long *supported
= ksettings
->link_modes
.supported
;
290 DECLARE_BITMAP(old_adv
, __ETHTOOL_LINK_MODE_MASK_NBITS
);
293 BUILD_BUG_ON(ARRAY_SIZE(link_mode_params
) !=
294 __ETHTOOL_LINK_MODE_MASK_NBITS
);
296 bitmap_copy(old_adv
, advertising
, __ETHTOOL_LINK_MODE_MASK_NBITS
);
298 for (i
= 0; i
< __ETHTOOL_LINK_MODE_MASK_NBITS
; i
++) {
299 const struct link_mode_info
*info
= &link_mode_params
[i
];
301 if (info
->speed
== SPEED_UNKNOWN
)
303 if (test_bit(i
, supported
) &&
304 (!req_speed
|| info
->speed
== ksettings
->base
.speed
) &&
305 (!req_duplex
|| info
->duplex
== ksettings
->base
.duplex
))
306 set_bit(i
, advertising
);
308 clear_bit(i
, advertising
);
311 return !bitmap_equal(old_adv
, advertising
,
312 __ETHTOOL_LINK_MODE_MASK_NBITS
);
315 static bool ethnl_validate_master_slave_cfg(u8 cfg
)
318 case MASTER_SLAVE_CFG_MASTER_PREFERRED
:
319 case MASTER_SLAVE_CFG_SLAVE_PREFERRED
:
320 case MASTER_SLAVE_CFG_MASTER_FORCE
:
321 case MASTER_SLAVE_CFG_SLAVE_FORCE
:
328 static int ethnl_update_linkmodes(struct genl_info
*info
, struct nlattr
**tb
,
329 struct ethtool_link_ksettings
*ksettings
,
332 struct ethtool_link_settings
*lsettings
= &ksettings
->base
;
333 bool req_speed
, req_duplex
;
334 const struct nlattr
*master_slave_cfg
;
337 master_slave_cfg
= tb
[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG
];
338 if (master_slave_cfg
) {
339 u8 cfg
= nla_get_u8(master_slave_cfg
);
341 if (lsettings
->master_slave_cfg
== MASTER_SLAVE_CFG_UNSUPPORTED
) {
342 NL_SET_ERR_MSG_ATTR(info
->extack
, master_slave_cfg
,
343 "master/slave configuration not supported by device");
347 if (!ethnl_validate_master_slave_cfg(cfg
)) {
348 NL_SET_ERR_MSG_ATTR(info
->extack
, master_slave_cfg
,
349 "master/slave value is invalid");
355 req_speed
= tb
[ETHTOOL_A_LINKMODES_SPEED
];
356 req_duplex
= tb
[ETHTOOL_A_LINKMODES_DUPLEX
];
358 ethnl_update_u8(&lsettings
->autoneg
, tb
[ETHTOOL_A_LINKMODES_AUTONEG
],
360 ret
= ethnl_update_bitset(ksettings
->link_modes
.advertising
,
361 __ETHTOOL_LINK_MODE_MASK_NBITS
,
362 tb
[ETHTOOL_A_LINKMODES_OURS
], link_mode_names
,
366 ethnl_update_u32(&lsettings
->speed
, tb
[ETHTOOL_A_LINKMODES_SPEED
],
368 ethnl_update_u8(&lsettings
->duplex
, tb
[ETHTOOL_A_LINKMODES_DUPLEX
],
370 ethnl_update_u8(&lsettings
->master_slave_cfg
, master_slave_cfg
, mod
);
372 if (!tb
[ETHTOOL_A_LINKMODES_OURS
] && lsettings
->autoneg
&&
373 (req_speed
|| req_duplex
) &&
374 ethnl_auto_linkmodes(ksettings
, req_speed
, req_duplex
))
380 int ethnl_set_linkmodes(struct sk_buff
*skb
, struct genl_info
*info
)
382 struct ethtool_link_ksettings ksettings
= {};
383 struct ethnl_req_info req_info
= {};
384 struct nlattr
**tb
= info
->attrs
;
385 struct net_device
*dev
;
389 ret
= ethnl_parse_header_dev_get(&req_info
,
390 tb
[ETHTOOL_A_LINKMODES_HEADER
],
391 genl_info_net(info
), info
->extack
,
397 if (!dev
->ethtool_ops
->get_link_ksettings
||
398 !dev
->ethtool_ops
->set_link_ksettings
)
402 ret
= ethnl_ops_begin(dev
);
406 ret
= __ethtool_get_link_ksettings(dev
, &ksettings
);
408 GENL_SET_ERR_MSG(info
, "failed to retrieve link settings");
412 ret
= ethnl_update_linkmodes(info
, tb
, &ksettings
, &mod
);
417 ret
= dev
->ethtool_ops
->set_link_ksettings(dev
, &ksettings
);
419 GENL_SET_ERR_MSG(info
, "link settings update failed");
421 ethtool_notify(dev
, ETHTOOL_MSG_LINKMODES_NTF
, NULL
);
425 ethnl_ops_complete(dev
);