1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix |
3 | * Copyright (C) 2006 Andrey Volkov, Varma Electronics |
4 | * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> |
5 | * Copyright (C) 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr> |
6 | */ |
7 | |
8 | #include <linux/can/dev.h> |
9 | #include <net/rtnetlink.h> |
10 | |
11 | static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { |
12 | [IFLA_CAN_STATE] = { .type = NLA_U32 }, |
13 | [IFLA_CAN_CTRLMODE] = { .len = sizeof(struct can_ctrlmode) }, |
14 | [IFLA_CAN_RESTART_MS] = { .type = NLA_U32 }, |
15 | [IFLA_CAN_RESTART] = { .type = NLA_U32 }, |
16 | [IFLA_CAN_BITTIMING] = { .len = sizeof(struct can_bittiming) }, |
17 | [IFLA_CAN_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, |
18 | [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, |
19 | [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) }, |
20 | [IFLA_CAN_DATA_BITTIMING] = { .len = sizeof(struct can_bittiming) }, |
21 | [IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, |
22 | [IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, |
23 | [IFLA_CAN_TDC] = { .type = NLA_NESTED }, |
24 | [IFLA_CAN_CTRLMODE_EXT] = { .type = NLA_NESTED }, |
25 | }; |
26 | |
27 | static const struct nla_policy can_tdc_policy[IFLA_CAN_TDC_MAX + 1] = { |
28 | [IFLA_CAN_TDC_TDCV_MIN] = { .type = NLA_U32 }, |
29 | [IFLA_CAN_TDC_TDCV_MAX] = { .type = NLA_U32 }, |
30 | [IFLA_CAN_TDC_TDCO_MIN] = { .type = NLA_U32 }, |
31 | [IFLA_CAN_TDC_TDCO_MAX] = { .type = NLA_U32 }, |
32 | [IFLA_CAN_TDC_TDCF_MIN] = { .type = NLA_U32 }, |
33 | [IFLA_CAN_TDC_TDCF_MAX] = { .type = NLA_U32 }, |
34 | [IFLA_CAN_TDC_TDCV] = { .type = NLA_U32 }, |
35 | [IFLA_CAN_TDC_TDCO] = { .type = NLA_U32 }, |
36 | [IFLA_CAN_TDC_TDCF] = { .type = NLA_U32 }, |
37 | }; |
38 | |
39 | static int can_validate_bittiming(const struct can_bittiming *bt, |
40 | struct netlink_ext_ack *extack) |
41 | { |
42 | /* sample point is in one-tenth of a percent */ |
43 | if (bt->sample_point >= 1000) { |
44 | NL_SET_ERR_MSG(extack, "sample point must be between 0 and 100%" ); |
45 | |
46 | return -EINVAL; |
47 | } |
48 | |
49 | return 0; |
50 | } |
51 | |
52 | static int can_validate(struct nlattr *tb[], struct nlattr *data[], |
53 | struct netlink_ext_ack *extack) |
54 | { |
55 | bool is_can_fd = false; |
56 | int err; |
57 | |
58 | /* Make sure that valid CAN FD configurations always consist of |
59 | * - nominal/arbitration bittiming |
60 | * - data bittiming |
61 | * - control mode with CAN_CTRLMODE_FD set |
62 | * - TDC parameters are coherent (details below) |
63 | */ |
64 | |
65 | if (!data) |
66 | return 0; |
67 | |
68 | if (data[IFLA_CAN_BITTIMING]) { |
69 | struct can_bittiming bt; |
70 | |
71 | memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); |
72 | err = can_validate_bittiming(bt: &bt, extack); |
73 | if (err) |
74 | return err; |
75 | } |
76 | |
77 | if (data[IFLA_CAN_CTRLMODE]) { |
78 | struct can_ctrlmode *cm = nla_data(nla: data[IFLA_CAN_CTRLMODE]); |
79 | u32 tdc_flags = cm->flags & CAN_CTRLMODE_TDC_MASK; |
80 | |
81 | is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD; |
82 | |
83 | /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */ |
84 | if (tdc_flags == CAN_CTRLMODE_TDC_MASK) |
85 | return -EOPNOTSUPP; |
86 | /* If one of the CAN_CTRLMODE_TDC_* flag is set then |
87 | * TDC must be set and vice-versa |
88 | */ |
89 | if (!!tdc_flags != !!data[IFLA_CAN_TDC]) |
90 | return -EOPNOTSUPP; |
91 | /* If providing TDC parameters, at least TDCO is |
92 | * needed. TDCV is needed if and only if |
93 | * CAN_CTRLMODE_TDC_MANUAL is set |
94 | */ |
95 | if (data[IFLA_CAN_TDC]) { |
96 | struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; |
97 | |
98 | err = nla_parse_nested(tb: tb_tdc, maxtype: IFLA_CAN_TDC_MAX, |
99 | nla: data[IFLA_CAN_TDC], |
100 | policy: can_tdc_policy, extack); |
101 | if (err) |
102 | return err; |
103 | |
104 | if (tb_tdc[IFLA_CAN_TDC_TDCV]) { |
105 | if (tdc_flags & CAN_CTRLMODE_TDC_AUTO) |
106 | return -EOPNOTSUPP; |
107 | } else { |
108 | if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL) |
109 | return -EOPNOTSUPP; |
110 | } |
111 | |
112 | if (!tb_tdc[IFLA_CAN_TDC_TDCO]) |
113 | return -EOPNOTSUPP; |
114 | } |
115 | } |
116 | |
117 | if (is_can_fd) { |
118 | if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING]) |
119 | return -EOPNOTSUPP; |
120 | } |
121 | |
122 | if (data[IFLA_CAN_DATA_BITTIMING] || data[IFLA_CAN_TDC]) { |
123 | if (!is_can_fd) |
124 | return -EOPNOTSUPP; |
125 | } |
126 | |
127 | if (data[IFLA_CAN_DATA_BITTIMING]) { |
128 | struct can_bittiming bt; |
129 | |
130 | memcpy(&bt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), sizeof(bt)); |
131 | err = can_validate_bittiming(bt: &bt, extack); |
132 | if (err) |
133 | return err; |
134 | } |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla, |
140 | struct netlink_ext_ack *extack) |
141 | { |
142 | struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; |
143 | struct can_tdc tdc = { 0 }; |
144 | const struct can_tdc_const *tdc_const = priv->tdc_const; |
145 | int err; |
146 | |
147 | if (!tdc_const || !can_tdc_is_enabled(priv)) |
148 | return -EOPNOTSUPP; |
149 | |
150 | err = nla_parse_nested(tb: tb_tdc, maxtype: IFLA_CAN_TDC_MAX, nla, |
151 | policy: can_tdc_policy, extack); |
152 | if (err) |
153 | return err; |
154 | |
155 | if (tb_tdc[IFLA_CAN_TDC_TDCV]) { |
156 | u32 tdcv = nla_get_u32(nla: tb_tdc[IFLA_CAN_TDC_TDCV]); |
157 | |
158 | if (tdcv < tdc_const->tdcv_min || tdcv > tdc_const->tdcv_max) |
159 | return -EINVAL; |
160 | |
161 | tdc.tdcv = tdcv; |
162 | } |
163 | |
164 | if (tb_tdc[IFLA_CAN_TDC_TDCO]) { |
165 | u32 tdco = nla_get_u32(nla: tb_tdc[IFLA_CAN_TDC_TDCO]); |
166 | |
167 | if (tdco < tdc_const->tdco_min || tdco > tdc_const->tdco_max) |
168 | return -EINVAL; |
169 | |
170 | tdc.tdco = tdco; |
171 | } |
172 | |
173 | if (tb_tdc[IFLA_CAN_TDC_TDCF]) { |
174 | u32 tdcf = nla_get_u32(nla: tb_tdc[IFLA_CAN_TDC_TDCF]); |
175 | |
176 | if (tdcf < tdc_const->tdcf_min || tdcf > tdc_const->tdcf_max) |
177 | return -EINVAL; |
178 | |
179 | tdc.tdcf = tdcf; |
180 | } |
181 | |
182 | priv->tdc = tdc; |
183 | |
184 | return 0; |
185 | } |
186 | |
187 | static int can_changelink(struct net_device *dev, struct nlattr *tb[], |
188 | struct nlattr *data[], |
189 | struct netlink_ext_ack *extack) |
190 | { |
191 | struct can_priv *priv = netdev_priv(dev); |
192 | u32 tdc_mask = 0; |
193 | int err; |
194 | |
195 | /* We need synchronization with dev->stop() */ |
196 | ASSERT_RTNL(); |
197 | |
198 | if (data[IFLA_CAN_BITTIMING]) { |
199 | struct can_bittiming bt; |
200 | |
201 | /* Do not allow changing bittiming while running */ |
202 | if (dev->flags & IFF_UP) |
203 | return -EBUSY; |
204 | |
205 | /* Calculate bittiming parameters based on |
206 | * bittiming_const if set, otherwise pass bitrate |
207 | * directly via do_set_bitrate(). Bail out if neither |
208 | * is given. |
209 | */ |
210 | if (!priv->bittiming_const && !priv->do_set_bittiming && |
211 | !priv->bitrate_const) |
212 | return -EOPNOTSUPP; |
213 | |
214 | memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt)); |
215 | err = can_get_bittiming(dev, bt: &bt, |
216 | btc: priv->bittiming_const, |
217 | bitrate_const: priv->bitrate_const, |
218 | bitrate_const_cnt: priv->bitrate_const_cnt, |
219 | extack); |
220 | if (err) |
221 | return err; |
222 | |
223 | if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) { |
224 | NL_SET_ERR_MSG_FMT(extack, |
225 | "arbitration bitrate %u bps surpasses transceiver capabilities of %u bps" , |
226 | bt.bitrate, priv->bitrate_max); |
227 | return -EINVAL; |
228 | } |
229 | |
230 | memcpy(&priv->bittiming, &bt, sizeof(bt)); |
231 | |
232 | if (priv->do_set_bittiming) { |
233 | /* Finally, set the bit-timing registers */ |
234 | err = priv->do_set_bittiming(dev); |
235 | if (err) |
236 | return err; |
237 | } |
238 | } |
239 | |
240 | if (data[IFLA_CAN_CTRLMODE]) { |
241 | struct can_ctrlmode *cm; |
242 | u32 ctrlstatic; |
243 | u32 maskedflags; |
244 | |
245 | /* Do not allow changing controller mode while running */ |
246 | if (dev->flags & IFF_UP) |
247 | return -EBUSY; |
248 | cm = nla_data(nla: data[IFLA_CAN_CTRLMODE]); |
249 | ctrlstatic = can_get_static_ctrlmode(priv); |
250 | maskedflags = cm->flags & cm->mask; |
251 | |
252 | /* check whether provided bits are allowed to be passed */ |
253 | if (maskedflags & ~(priv->ctrlmode_supported | ctrlstatic)) |
254 | return -EOPNOTSUPP; |
255 | |
256 | /* do not check for static fd-non-iso if 'fd' is disabled */ |
257 | if (!(maskedflags & CAN_CTRLMODE_FD)) |
258 | ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO; |
259 | |
260 | /* make sure static options are provided by configuration */ |
261 | if ((maskedflags & ctrlstatic) != ctrlstatic) |
262 | return -EOPNOTSUPP; |
263 | |
264 | /* clear bits to be modified and copy the flag values */ |
265 | priv->ctrlmode &= ~cm->mask; |
266 | priv->ctrlmode |= maskedflags; |
267 | |
268 | /* CAN_CTRLMODE_FD can only be set when driver supports FD */ |
269 | if (priv->ctrlmode & CAN_CTRLMODE_FD) { |
270 | dev->mtu = CANFD_MTU; |
271 | } else { |
272 | dev->mtu = CAN_MTU; |
273 | memset(&priv->data_bittiming, 0, |
274 | sizeof(priv->data_bittiming)); |
275 | priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; |
276 | memset(&priv->tdc, 0, sizeof(priv->tdc)); |
277 | } |
278 | |
279 | tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK; |
280 | /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually |
281 | * exclusive: make sure to turn the other one off |
282 | */ |
283 | if (tdc_mask) |
284 | priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK; |
285 | } |
286 | |
287 | if (data[IFLA_CAN_RESTART_MS]) { |
288 | /* Do not allow changing restart delay while running */ |
289 | if (dev->flags & IFF_UP) |
290 | return -EBUSY; |
291 | priv->restart_ms = nla_get_u32(nla: data[IFLA_CAN_RESTART_MS]); |
292 | } |
293 | |
294 | if (data[IFLA_CAN_RESTART]) { |
295 | /* Do not allow a restart while not running */ |
296 | if (!(dev->flags & IFF_UP)) |
297 | return -EINVAL; |
298 | err = can_restart_now(dev); |
299 | if (err) |
300 | return err; |
301 | } |
302 | |
303 | if (data[IFLA_CAN_DATA_BITTIMING]) { |
304 | struct can_bittiming dbt; |
305 | |
306 | /* Do not allow changing bittiming while running */ |
307 | if (dev->flags & IFF_UP) |
308 | return -EBUSY; |
309 | |
310 | /* Calculate bittiming parameters based on |
311 | * data_bittiming_const if set, otherwise pass bitrate |
312 | * directly via do_set_bitrate(). Bail out if neither |
313 | * is given. |
314 | */ |
315 | if (!priv->data_bittiming_const && !priv->do_set_data_bittiming && |
316 | !priv->data_bitrate_const) |
317 | return -EOPNOTSUPP; |
318 | |
319 | memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), |
320 | sizeof(dbt)); |
321 | err = can_get_bittiming(dev, bt: &dbt, |
322 | btc: priv->data_bittiming_const, |
323 | bitrate_const: priv->data_bitrate_const, |
324 | bitrate_const_cnt: priv->data_bitrate_const_cnt, |
325 | extack); |
326 | if (err) |
327 | return err; |
328 | |
329 | if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) { |
330 | NL_SET_ERR_MSG_FMT(extack, |
331 | "CANFD data bitrate %u bps surpasses transceiver capabilities of %u bps" , |
332 | dbt.bitrate, priv->bitrate_max); |
333 | return -EINVAL; |
334 | } |
335 | |
336 | memset(&priv->tdc, 0, sizeof(priv->tdc)); |
337 | if (data[IFLA_CAN_TDC]) { |
338 | /* TDC parameters are provided: use them */ |
339 | err = can_tdc_changelink(priv, nla: data[IFLA_CAN_TDC], |
340 | extack); |
341 | if (err) { |
342 | priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; |
343 | return err; |
344 | } |
345 | } else if (!tdc_mask) { |
346 | /* Neither of TDC parameters nor TDC flags are |
347 | * provided: do calculation |
348 | */ |
349 | can_calc_tdco(tdc: &priv->tdc, tdc_const: priv->tdc_const, dbt: &dbt, |
350 | ctrlmode: &priv->ctrlmode, ctrlmode_supported: priv->ctrlmode_supported); |
351 | } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly |
352 | * turned off. TDC is disabled: do nothing |
353 | */ |
354 | |
355 | memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); |
356 | |
357 | if (priv->do_set_data_bittiming) { |
358 | /* Finally, set the bit-timing registers */ |
359 | err = priv->do_set_data_bittiming(dev); |
360 | if (err) |
361 | return err; |
362 | } |
363 | } |
364 | |
365 | if (data[IFLA_CAN_TERMINATION]) { |
366 | const u16 termval = nla_get_u16(nla: data[IFLA_CAN_TERMINATION]); |
367 | const unsigned int num_term = priv->termination_const_cnt; |
368 | unsigned int i; |
369 | |
370 | if (!priv->do_set_termination) |
371 | return -EOPNOTSUPP; |
372 | |
373 | /* check whether given value is supported by the interface */ |
374 | for (i = 0; i < num_term; i++) { |
375 | if (termval == priv->termination_const[i]) |
376 | break; |
377 | } |
378 | if (i >= num_term) |
379 | return -EINVAL; |
380 | |
381 | /* Finally, set the termination value */ |
382 | err = priv->do_set_termination(dev, termval); |
383 | if (err) |
384 | return err; |
385 | |
386 | priv->termination = termval; |
387 | } |
388 | |
389 | return 0; |
390 | } |
391 | |
392 | static size_t can_tdc_get_size(const struct net_device *dev) |
393 | { |
394 | struct can_priv *priv = netdev_priv(dev); |
395 | size_t size; |
396 | |
397 | if (!priv->tdc_const) |
398 | return 0; |
399 | |
400 | size = nla_total_size(payload: 0); /* nest IFLA_CAN_TDC */ |
401 | if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL) { |
402 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCV_MIN */ |
403 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCV_MAX */ |
404 | } |
405 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCO_MIN */ |
406 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCO_MAX */ |
407 | if (priv->tdc_const->tdcf_max) { |
408 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCF_MIN */ |
409 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCF_MAX */ |
410 | } |
411 | |
412 | if (can_tdc_is_enabled(priv)) { |
413 | if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL || |
414 | priv->do_get_auto_tdcv) |
415 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCV */ |
416 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCO */ |
417 | if (priv->tdc_const->tdcf_max) |
418 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_TDCF */ |
419 | } |
420 | |
421 | return size; |
422 | } |
423 | |
424 | static size_t can_ctrlmode_ext_get_size(void) |
425 | { |
426 | return nla_total_size(payload: 0) + /* nest IFLA_CAN_CTRLMODE_EXT */ |
427 | nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_CTRLMODE_SUPPORTED */ |
428 | } |
429 | |
430 | static size_t can_get_size(const struct net_device *dev) |
431 | { |
432 | struct can_priv *priv = netdev_priv(dev); |
433 | size_t size = 0; |
434 | |
435 | if (priv->bittiming.bitrate) /* IFLA_CAN_BITTIMING */ |
436 | size += nla_total_size(payload: sizeof(struct can_bittiming)); |
437 | if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ |
438 | size += nla_total_size(payload: sizeof(struct can_bittiming_const)); |
439 | size += nla_total_size(payload: sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */ |
440 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_STATE */ |
441 | size += nla_total_size(payload: sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */ |
442 | size += nla_total_size(payload: sizeof(u32)); /* IFLA_CAN_RESTART_MS */ |
443 | if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ |
444 | size += nla_total_size(payload: sizeof(struct can_berr_counter)); |
445 | if (priv->data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */ |
446 | size += nla_total_size(payload: sizeof(struct can_bittiming)); |
447 | if (priv->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */ |
448 | size += nla_total_size(payload: sizeof(struct can_bittiming_const)); |
449 | if (priv->termination_const) { |
450 | size += nla_total_size(payload: sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */ |
451 | size += nla_total_size(payload: sizeof(*priv->termination_const) * /* IFLA_CAN_TERMINATION_CONST */ |
452 | priv->termination_const_cnt); |
453 | } |
454 | if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */ |
455 | size += nla_total_size(payload: sizeof(*priv->bitrate_const) * |
456 | priv->bitrate_const_cnt); |
457 | if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */ |
458 | size += nla_total_size(payload: sizeof(*priv->data_bitrate_const) * |
459 | priv->data_bitrate_const_cnt); |
460 | size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ |
461 | size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ |
462 | size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */ |
463 | |
464 | return size; |
465 | } |
466 | |
467 | static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev) |
468 | { |
469 | struct nlattr *nest; |
470 | struct can_priv *priv = netdev_priv(dev); |
471 | struct can_tdc *tdc = &priv->tdc; |
472 | const struct can_tdc_const *tdc_const = priv->tdc_const; |
473 | |
474 | if (!tdc_const) |
475 | return 0; |
476 | |
477 | nest = nla_nest_start(skb, attrtype: IFLA_CAN_TDC); |
478 | if (!nest) |
479 | return -EMSGSIZE; |
480 | |
481 | if (priv->ctrlmode_supported & CAN_CTRLMODE_TDC_MANUAL && |
482 | (nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCV_MIN, value: tdc_const->tdcv_min) || |
483 | nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCV_MAX, value: tdc_const->tdcv_max))) |
484 | goto err_cancel; |
485 | if (nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCO_MIN, value: tdc_const->tdco_min) || |
486 | nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCO_MAX, value: tdc_const->tdco_max)) |
487 | goto err_cancel; |
488 | if (tdc_const->tdcf_max && |
489 | (nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCF_MIN, value: tdc_const->tdcf_min) || |
490 | nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCF_MAX, value: tdc_const->tdcf_max))) |
491 | goto err_cancel; |
492 | |
493 | if (can_tdc_is_enabled(priv)) { |
494 | u32 tdcv; |
495 | int err = -EINVAL; |
496 | |
497 | if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) { |
498 | tdcv = tdc->tdcv; |
499 | err = 0; |
500 | } else if (priv->do_get_auto_tdcv) { |
501 | err = priv->do_get_auto_tdcv(dev, &tdcv); |
502 | } |
503 | if (!err && nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCV, value: tdcv)) |
504 | goto err_cancel; |
505 | if (nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCO, value: tdc->tdco)) |
506 | goto err_cancel; |
507 | if (tdc_const->tdcf_max && |
508 | nla_put_u32(skb, attrtype: IFLA_CAN_TDC_TDCF, value: tdc->tdcf)) |
509 | goto err_cancel; |
510 | } |
511 | |
512 | nla_nest_end(skb, start: nest); |
513 | return 0; |
514 | |
515 | err_cancel: |
516 | nla_nest_cancel(skb, start: nest); |
517 | return -EMSGSIZE; |
518 | } |
519 | |
520 | static int can_ctrlmode_ext_fill_info(struct sk_buff *skb, |
521 | const struct can_priv *priv) |
522 | { |
523 | struct nlattr *nest; |
524 | |
525 | nest = nla_nest_start(skb, attrtype: IFLA_CAN_CTRLMODE_EXT); |
526 | if (!nest) |
527 | return -EMSGSIZE; |
528 | |
529 | if (nla_put_u32(skb, attrtype: IFLA_CAN_CTRLMODE_SUPPORTED, |
530 | value: priv->ctrlmode_supported)) { |
531 | nla_nest_cancel(skb, start: nest); |
532 | return -EMSGSIZE; |
533 | } |
534 | |
535 | nla_nest_end(skb, start: nest); |
536 | return 0; |
537 | } |
538 | |
539 | static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) |
540 | { |
541 | struct can_priv *priv = netdev_priv(dev); |
542 | struct can_ctrlmode cm = {.flags = priv->ctrlmode}; |
543 | struct can_berr_counter bec = { }; |
544 | enum can_state state = priv->state; |
545 | |
546 | if (priv->do_get_state) |
547 | priv->do_get_state(dev, &state); |
548 | |
549 | if ((priv->bittiming.bitrate != CAN_BITRATE_UNSET && |
550 | priv->bittiming.bitrate != CAN_BITRATE_UNKNOWN && |
551 | nla_put(skb, attrtype: IFLA_CAN_BITTIMING, |
552 | attrlen: sizeof(priv->bittiming), data: &priv->bittiming)) || |
553 | |
554 | (priv->bittiming_const && |
555 | nla_put(skb, attrtype: IFLA_CAN_BITTIMING_CONST, |
556 | attrlen: sizeof(*priv->bittiming_const), data: priv->bittiming_const)) || |
557 | |
558 | nla_put(skb, attrtype: IFLA_CAN_CLOCK, attrlen: sizeof(priv->clock), data: &priv->clock) || |
559 | nla_put_u32(skb, attrtype: IFLA_CAN_STATE, value: state) || |
560 | nla_put(skb, attrtype: IFLA_CAN_CTRLMODE, attrlen: sizeof(cm), data: &cm) || |
561 | nla_put_u32(skb, attrtype: IFLA_CAN_RESTART_MS, value: priv->restart_ms) || |
562 | |
563 | (priv->do_get_berr_counter && |
564 | !priv->do_get_berr_counter(dev, &bec) && |
565 | nla_put(skb, attrtype: IFLA_CAN_BERR_COUNTER, attrlen: sizeof(bec), data: &bec)) || |
566 | |
567 | (priv->data_bittiming.bitrate && |
568 | nla_put(skb, attrtype: IFLA_CAN_DATA_BITTIMING, |
569 | attrlen: sizeof(priv->data_bittiming), data: &priv->data_bittiming)) || |
570 | |
571 | (priv->data_bittiming_const && |
572 | nla_put(skb, attrtype: IFLA_CAN_DATA_BITTIMING_CONST, |
573 | attrlen: sizeof(*priv->data_bittiming_const), |
574 | data: priv->data_bittiming_const)) || |
575 | |
576 | (priv->termination_const && |
577 | (nla_put_u16(skb, attrtype: IFLA_CAN_TERMINATION, value: priv->termination) || |
578 | nla_put(skb, attrtype: IFLA_CAN_TERMINATION_CONST, |
579 | attrlen: sizeof(*priv->termination_const) * |
580 | priv->termination_const_cnt, |
581 | data: priv->termination_const))) || |
582 | |
583 | (priv->bitrate_const && |
584 | nla_put(skb, attrtype: IFLA_CAN_BITRATE_CONST, |
585 | attrlen: sizeof(*priv->bitrate_const) * |
586 | priv->bitrate_const_cnt, |
587 | data: priv->bitrate_const)) || |
588 | |
589 | (priv->data_bitrate_const && |
590 | nla_put(skb, attrtype: IFLA_CAN_DATA_BITRATE_CONST, |
591 | attrlen: sizeof(*priv->data_bitrate_const) * |
592 | priv->data_bitrate_const_cnt, |
593 | data: priv->data_bitrate_const)) || |
594 | |
595 | (nla_put(skb, attrtype: IFLA_CAN_BITRATE_MAX, |
596 | attrlen: sizeof(priv->bitrate_max), |
597 | data: &priv->bitrate_max)) || |
598 | |
599 | can_tdc_fill_info(skb, dev) || |
600 | |
601 | can_ctrlmode_ext_fill_info(skb, priv) |
602 | ) |
603 | |
604 | return -EMSGSIZE; |
605 | |
606 | return 0; |
607 | } |
608 | |
609 | static size_t can_get_xstats_size(const struct net_device *dev) |
610 | { |
611 | return sizeof(struct can_device_stats); |
612 | } |
613 | |
614 | static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev) |
615 | { |
616 | struct can_priv *priv = netdev_priv(dev); |
617 | |
618 | if (nla_put(skb, attrtype: IFLA_INFO_XSTATS, |
619 | attrlen: sizeof(priv->can_stats), data: &priv->can_stats)) |
620 | goto nla_put_failure; |
621 | return 0; |
622 | |
623 | nla_put_failure: |
624 | return -EMSGSIZE; |
625 | } |
626 | |
627 | static int can_newlink(struct net *src_net, struct net_device *dev, |
628 | struct nlattr *tb[], struct nlattr *data[], |
629 | struct netlink_ext_ack *extack) |
630 | { |
631 | return -EOPNOTSUPP; |
632 | } |
633 | |
634 | static void can_dellink(struct net_device *dev, struct list_head *head) |
635 | { |
636 | } |
637 | |
638 | struct rtnl_link_ops can_link_ops __read_mostly = { |
639 | .kind = "can" , |
640 | .netns_refund = true, |
641 | .maxtype = IFLA_CAN_MAX, |
642 | .policy = can_policy, |
643 | .setup = can_setup, |
644 | .validate = can_validate, |
645 | .newlink = can_newlink, |
646 | .changelink = can_changelink, |
647 | .dellink = can_dellink, |
648 | .get_size = can_get_size, |
649 | .fill_info = can_fill_info, |
650 | .get_xstats_size = can_get_xstats_size, |
651 | .fill_xstats = can_fill_xstats, |
652 | }; |
653 | |
654 | int can_netlink_register(void) |
655 | { |
656 | return rtnl_link_register(ops: &can_link_ops); |
657 | } |
658 | |
659 | void can_netlink_unregister(void) |
660 | { |
661 | rtnl_link_unregister(ops: &can_link_ops); |
662 | } |
663 | |