Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/devlink/dev.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4
* Copyright (c) 2016 Jiri Pirko <[email protected]>
5
*/
6
7
#include <linux/device.h>
8
#include <net/genetlink.h>
9
#include <net/sock.h>
10
#include "devl_internal.h"
11
12
struct devlink_info_req {
13
struct sk_buff *msg;
14
void (*version_cb)(const char *version_name,
15
enum devlink_info_version_type version_type,
16
void *version_cb_priv);
17
void *version_cb_priv;
18
};
19
20
struct devlink_reload_combination {
21
enum devlink_reload_action action;
22
enum devlink_reload_limit limit;
23
};
24
25
static const struct devlink_reload_combination devlink_reload_invalid_combinations[] = {
26
{
27
/* can't reinitialize driver with no down time */
28
.action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
29
.limit = DEVLINK_RELOAD_LIMIT_NO_RESET,
30
},
31
};
32
33
static bool
34
devlink_reload_combination_is_invalid(enum devlink_reload_action action,
35
enum devlink_reload_limit limit)
36
{
37
int i;
38
39
for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)
40
if (devlink_reload_invalid_combinations[i].action == action &&
41
devlink_reload_invalid_combinations[i].limit == limit)
42
return true;
43
return false;
44
}
45
46
static bool
47
devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
48
{
49
return test_bit(action, &devlink->ops->reload_actions);
50
}
51
52
static bool
53
devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_limit limit)
54
{
55
return test_bit(limit, &devlink->ops->reload_limits);
56
}
57
58
static int devlink_reload_stat_put(struct sk_buff *msg,
59
enum devlink_reload_limit limit, u32 value)
60
{
61
struct nlattr *reload_stats_entry;
62
63
reload_stats_entry = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS_ENTRY);
64
if (!reload_stats_entry)
65
return -EMSGSIZE;
66
67
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
68
nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
69
goto nla_put_failure;
70
nla_nest_end(msg, reload_stats_entry);
71
return 0;
72
73
nla_put_failure:
74
nla_nest_cancel(msg, reload_stats_entry);
75
return -EMSGSIZE;
76
}
77
78
static int
79
devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote)
80
{
81
struct nlattr *reload_stats_attr, *act_info, *act_stats;
82
int i, j, stat_idx;
83
u32 value;
84
85
if (!is_remote)
86
reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS);
87
else
88
reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_REMOTE_RELOAD_STATS);
89
90
if (!reload_stats_attr)
91
return -EMSGSIZE;
92
93
for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
94
if ((!is_remote &&
95
!devlink_reload_action_is_supported(devlink, i)) ||
96
i == DEVLINK_RELOAD_ACTION_UNSPEC)
97
continue;
98
act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO);
99
if (!act_info)
100
goto nla_put_failure;
101
102
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i))
103
goto action_info_nest_cancel;
104
act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS);
105
if (!act_stats)
106
goto action_info_nest_cancel;
107
108
for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
109
/* Remote stats are shown even if not locally supported.
110
* Stats of actions with unspecified limit are shown
111
* though drivers don't need to register unspecified
112
* limit.
113
*/
114
if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
115
!devlink_reload_limit_is_supported(devlink, j)) ||
116
devlink_reload_combination_is_invalid(i, j))
117
continue;
118
119
stat_idx = j * __DEVLINK_RELOAD_ACTION_MAX + i;
120
if (!is_remote)
121
value = devlink->stats.reload_stats[stat_idx];
122
else
123
value = devlink->stats.remote_reload_stats[stat_idx];
124
if (devlink_reload_stat_put(msg, j, value))
125
goto action_stats_nest_cancel;
126
}
127
nla_nest_end(msg, act_stats);
128
nla_nest_end(msg, act_info);
129
}
130
nla_nest_end(msg, reload_stats_attr);
131
return 0;
132
133
action_stats_nest_cancel:
134
nla_nest_cancel(msg, act_stats);
135
action_info_nest_cancel:
136
nla_nest_cancel(msg, act_info);
137
nla_put_failure:
138
nla_nest_cancel(msg, reload_stats_attr);
139
return -EMSGSIZE;
140
}
141
142
static int devlink_nl_nested_fill(struct sk_buff *msg, struct devlink *devlink)
143
{
144
unsigned long rel_index;
145
void *unused;
146
int err;
147
148
xa_for_each(&devlink->nested_rels, rel_index, unused) {
149
err = devlink_rel_devlink_handle_put(msg, devlink,
150
rel_index,
151
DEVLINK_ATTR_NESTED_DEVLINK,
152
NULL);
153
if (err)
154
return err;
155
}
156
return 0;
157
}
158
159
static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
160
enum devlink_command cmd, u32 portid,
161
u32 seq, int flags)
162
{
163
struct nlattr *dev_stats;
164
void *hdr;
165
166
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
167
if (!hdr)
168
return -EMSGSIZE;
169
170
if (devlink_nl_put_handle(msg, devlink))
171
goto nla_put_failure;
172
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
173
goto nla_put_failure;
174
175
dev_stats = nla_nest_start(msg, DEVLINK_ATTR_DEV_STATS);
176
if (!dev_stats)
177
goto nla_put_failure;
178
179
if (devlink_reload_stats_put(msg, devlink, false))
180
goto dev_stats_nest_cancel;
181
if (devlink_reload_stats_put(msg, devlink, true))
182
goto dev_stats_nest_cancel;
183
184
nla_nest_end(msg, dev_stats);
185
186
if (devlink_nl_nested_fill(msg, devlink))
187
goto nla_put_failure;
188
189
genlmsg_end(msg, hdr);
190
return 0;
191
192
dev_stats_nest_cancel:
193
nla_nest_cancel(msg, dev_stats);
194
nla_put_failure:
195
genlmsg_cancel(msg, hdr);
196
return -EMSGSIZE;
197
}
198
199
static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
200
{
201
struct sk_buff *msg;
202
int err;
203
204
WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
205
WARN_ON(!devl_is_registered(devlink));
206
207
if (!devlink_nl_notify_need(devlink))
208
return;
209
210
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
211
if (!msg)
212
return;
213
214
err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
215
if (err) {
216
nlmsg_free(msg);
217
return;
218
}
219
220
devlink_nl_notify_send(devlink, msg);
221
}
222
223
int devlink_nl_get_doit(struct sk_buff *skb, struct genl_info *info)
224
{
225
struct devlink *devlink = info->user_ptr[0];
226
struct sk_buff *msg;
227
int err;
228
229
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
230
if (!msg)
231
return -ENOMEM;
232
233
err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
234
info->snd_portid, info->snd_seq, 0);
235
if (err) {
236
nlmsg_free(msg);
237
return err;
238
}
239
240
return genlmsg_reply(msg, info);
241
}
242
243
static int
244
devlink_nl_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
245
struct netlink_callback *cb, int flags)
246
{
247
return devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
248
NETLINK_CB(cb->skb).portid,
249
cb->nlh->nlmsg_seq, flags);
250
}
251
252
int devlink_nl_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb)
253
{
254
return devlink_nl_dumpit(msg, cb, devlink_nl_get_dump_one);
255
}
256
257
static void devlink_rel_notify_cb(struct devlink *devlink, u32 obj_index)
258
{
259
devlink_notify(devlink, DEVLINK_CMD_NEW);
260
}
261
262
static void devlink_rel_cleanup_cb(struct devlink *devlink, u32 obj_index,
263
u32 rel_index)
264
{
265
xa_erase(&devlink->nested_rels, rel_index);
266
}
267
268
int devl_nested_devlink_set(struct devlink *devlink,
269
struct devlink *nested_devlink)
270
{
271
u32 rel_index;
272
int err;
273
274
err = devlink_rel_nested_in_add(&rel_index, devlink->index, 0,
275
devlink_rel_notify_cb,
276
devlink_rel_cleanup_cb,
277
nested_devlink);
278
if (err)
279
return err;
280
return xa_insert(&devlink->nested_rels, rel_index,
281
xa_mk_value(0), GFP_KERNEL);
282
}
283
EXPORT_SYMBOL_GPL(devl_nested_devlink_set);
284
285
void devlink_notify_register(struct devlink *devlink)
286
{
287
devlink_notify(devlink, DEVLINK_CMD_NEW);
288
devlink_linecards_notify_register(devlink);
289
devlink_ports_notify_register(devlink);
290
devlink_trap_policers_notify_register(devlink);
291
devlink_trap_groups_notify_register(devlink);
292
devlink_traps_notify_register(devlink);
293
devlink_rates_notify_register(devlink);
294
devlink_regions_notify_register(devlink);
295
devlink_params_notify_register(devlink);
296
}
297
298
void devlink_notify_unregister(struct devlink *devlink)
299
{
300
devlink_params_notify_unregister(devlink);
301
devlink_regions_notify_unregister(devlink);
302
devlink_rates_notify_unregister(devlink);
303
devlink_traps_notify_unregister(devlink);
304
devlink_trap_groups_notify_unregister(devlink);
305
devlink_trap_policers_notify_unregister(devlink);
306
devlink_ports_notify_unregister(devlink);
307
devlink_linecards_notify_unregister(devlink);
308
devlink_notify(devlink, DEVLINK_CMD_DEL);
309
}
310
311
static void devlink_reload_failed_set(struct devlink *devlink,
312
bool reload_failed)
313
{
314
if (devlink->reload_failed == reload_failed)
315
return;
316
devlink->reload_failed = reload_failed;
317
devlink_notify(devlink, DEVLINK_CMD_NEW);
318
}
319
320
bool devlink_is_reload_failed(const struct devlink *devlink)
321
{
322
return devlink->reload_failed;
323
}
324
EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
325
326
static void
327
__devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
328
enum devlink_reload_limit limit, u32 actions_performed)
329
{
330
unsigned long actions = actions_performed;
331
int stat_idx;
332
int action;
333
334
for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
335
stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
336
reload_stats[stat_idx]++;
337
}
338
devlink_notify(devlink, DEVLINK_CMD_NEW);
339
}
340
341
static void
342
devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
343
u32 actions_performed)
344
{
345
__devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
346
actions_performed);
347
}
348
349
/**
350
* devlink_remote_reload_actions_performed - Update devlink on reload actions
351
* performed which are not a direct result of devlink reload call.
352
*
353
* This should be called by a driver after performing reload actions in case it was not
354
* a result of devlink reload call. For example fw_activate was performed as a result
355
* of devlink reload triggered fw_activate on another host.
356
* The motivation for this function is to keep data on reload actions performed on this
357
* function whether it was done due to direct devlink reload call or not.
358
*
359
* @devlink: devlink
360
* @limit: reload limit
361
* @actions_performed: bitmask of actions performed
362
*/
363
void devlink_remote_reload_actions_performed(struct devlink *devlink,
364
enum devlink_reload_limit limit,
365
u32 actions_performed)
366
{
367
if (WARN_ON(!actions_performed ||
368
actions_performed & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
369
actions_performed >= BIT(__DEVLINK_RELOAD_ACTION_MAX) ||
370
limit > DEVLINK_RELOAD_LIMIT_MAX))
371
return;
372
373
__devlink_reload_stats_update(devlink, devlink->stats.remote_reload_stats, limit,
374
actions_performed);
375
}
376
EXPORT_SYMBOL_GPL(devlink_remote_reload_actions_performed);
377
378
static struct net *devlink_netns_get(struct sk_buff *skb,
379
struct genl_info *info)
380
{
381
struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID];
382
struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD];
383
struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID];
384
struct net *net;
385
386
if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) {
387
NL_SET_ERR_MSG(info->extack, "multiple netns identifying attributes specified");
388
return ERR_PTR(-EINVAL);
389
}
390
391
if (netns_pid_attr) {
392
net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr));
393
} else if (netns_fd_attr) {
394
net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr));
395
} else if (netns_id_attr) {
396
net = get_net_ns_by_id(sock_net(skb->sk),
397
nla_get_u32(netns_id_attr));
398
if (!net)
399
net = ERR_PTR(-EINVAL);
400
} else {
401
WARN_ON(1);
402
net = ERR_PTR(-EINVAL);
403
}
404
if (IS_ERR(net)) {
405
NL_SET_ERR_MSG(info->extack, "Unknown network namespace");
406
return ERR_PTR(-EINVAL);
407
}
408
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
409
put_net(net);
410
return ERR_PTR(-EPERM);
411
}
412
return net;
413
}
414
415
static void devlink_reload_netns_change(struct devlink *devlink,
416
struct net *curr_net,
417
struct net *dest_net)
418
{
419
/* Userspace needs to be notified about devlink objects
420
* removed from original and entering new network namespace.
421
* The rest of the devlink objects are re-created during
422
* reload process so the notifications are generated separatelly.
423
*/
424
devlink_notify_unregister(devlink);
425
write_pnet(&devlink->_net, dest_net);
426
devlink_notify_register(devlink);
427
devlink_rel_nested_in_notify(devlink);
428
}
429
430
static void devlink_reload_reinit_sanity_check(struct devlink *devlink)
431
{
432
WARN_ON(!list_empty(&devlink->trap_policer_list));
433
WARN_ON(!list_empty(&devlink->trap_group_list));
434
WARN_ON(!list_empty(&devlink->trap_list));
435
WARN_ON(!list_empty(&devlink->dpipe_table_list));
436
WARN_ON(!list_empty(&devlink->sb_list));
437
WARN_ON(!list_empty(&devlink->rate_list));
438
WARN_ON(!list_empty(&devlink->linecard_list));
439
WARN_ON(!xa_empty(&devlink->ports));
440
}
441
442
int devlink_reload(struct devlink *devlink, struct net *dest_net,
443
enum devlink_reload_action action,
444
enum devlink_reload_limit limit,
445
u32 *actions_performed, struct netlink_ext_ack *extack)
446
{
447
u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
448
struct net *curr_net;
449
int err;
450
451
/* Make sure the reload operations are invoked with the device lock
452
* held to allow drivers to trigger functionality that expects it
453
* (e.g., PCI reset) and to close possible races between these
454
* operations and probe/remove.
455
*/
456
device_lock_assert(devlink->dev);
457
458
memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
459
sizeof(remote_reload_stats));
460
461
err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
462
if (err)
463
return err;
464
465
curr_net = devlink_net(devlink);
466
if (dest_net && !net_eq(dest_net, curr_net))
467
devlink_reload_netns_change(devlink, curr_net, dest_net);
468
469
if (action == DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
470
devlink_params_driverinit_load_new(devlink);
471
devlink_reload_reinit_sanity_check(devlink);
472
}
473
474
err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
475
devlink_reload_failed_set(devlink, !!err);
476
if (err)
477
return err;
478
479
WARN_ON(!(*actions_performed & BIT(action)));
480
/* Catch driver on updating the remote action within devlink reload */
481
WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
482
sizeof(remote_reload_stats)));
483
devlink_reload_stats_update(devlink, limit, *actions_performed);
484
return 0;
485
}
486
487
static int
488
devlink_nl_reload_actions_performed_snd(struct devlink *devlink, u32 actions_performed,
489
enum devlink_command cmd, struct genl_info *info)
490
{
491
struct sk_buff *msg;
492
void *hdr;
493
494
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
495
if (!msg)
496
return -ENOMEM;
497
498
hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &devlink_nl_family, 0, cmd);
499
if (!hdr)
500
goto free_msg;
501
502
if (devlink_nl_put_handle(msg, devlink))
503
goto nla_put_failure;
504
505
if (nla_put_bitfield32(msg, DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, actions_performed,
506
actions_performed))
507
goto nla_put_failure;
508
genlmsg_end(msg, hdr);
509
510
return genlmsg_reply(msg, info);
511
512
nla_put_failure:
513
genlmsg_cancel(msg, hdr);
514
free_msg:
515
nlmsg_free(msg);
516
return -EMSGSIZE;
517
}
518
519
int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info)
520
{
521
struct devlink *devlink = info->user_ptr[0];
522
enum devlink_reload_action action;
523
enum devlink_reload_limit limit;
524
struct net *dest_net = NULL;
525
u32 actions_performed;
526
int err;
527
528
err = devlink_resources_validate(devlink, NULL, info);
529
if (err) {
530
NL_SET_ERR_MSG(info->extack, "resources size validation failed");
531
return err;
532
}
533
534
action = nla_get_u8_default(info->attrs[DEVLINK_ATTR_RELOAD_ACTION],
535
DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
536
537
if (!devlink_reload_action_is_supported(devlink, action)) {
538
NL_SET_ERR_MSG(info->extack, "Requested reload action is not supported by the driver");
539
return -EOPNOTSUPP;
540
}
541
542
limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
543
if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
544
struct nla_bitfield32 limits;
545
u32 limits_selected;
546
547
limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
548
limits_selected = limits.value & limits.selector;
549
if (!limits_selected) {
550
NL_SET_ERR_MSG(info->extack, "Invalid limit selected");
551
return -EINVAL;
552
}
553
for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
554
if (limits_selected & BIT(limit))
555
break;
556
/* UAPI enables multiselection, but currently it is not used */
557
if (limits_selected != BIT(limit)) {
558
NL_SET_ERR_MSG(info->extack, "Multiselection of limit is not supported");
559
return -EOPNOTSUPP;
560
}
561
if (!devlink_reload_limit_is_supported(devlink, limit)) {
562
NL_SET_ERR_MSG(info->extack, "Requested limit is not supported by the driver");
563
return -EOPNOTSUPP;
564
}
565
if (devlink_reload_combination_is_invalid(action, limit)) {
566
NL_SET_ERR_MSG(info->extack, "Requested limit is invalid for this action");
567
return -EINVAL;
568
}
569
}
570
if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
571
info->attrs[DEVLINK_ATTR_NETNS_FD] ||
572
info->attrs[DEVLINK_ATTR_NETNS_ID]) {
573
dest_net = devlink_netns_get(skb, info);
574
if (IS_ERR(dest_net))
575
return PTR_ERR(dest_net);
576
if (!net_eq(dest_net, devlink_net(devlink)) &&
577
action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) {
578
NL_SET_ERR_MSG_MOD(info->extack,
579
"Changing namespace is only supported for reinit action");
580
return -EOPNOTSUPP;
581
}
582
}
583
584
err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
585
586
if (dest_net)
587
put_net(dest_net);
588
589
if (err)
590
return err;
591
/* For backward compatibility generate reply only if attributes used by user */
592
if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
593
return 0;
594
595
return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
596
DEVLINK_CMD_RELOAD, info);
597
}
598
599
bool devlink_reload_actions_valid(const struct devlink_ops *ops)
600
{
601
const struct devlink_reload_combination *comb;
602
int i;
603
604
if (!devlink_reload_supported(ops)) {
605
if (WARN_ON(ops->reload_actions))
606
return false;
607
return true;
608
}
609
610
if (WARN_ON(!ops->reload_actions ||
611
ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
612
ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
613
return false;
614
615
if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
616
ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
617
return false;
618
619
for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++) {
620
comb = &devlink_reload_invalid_combinations[i];
621
if (ops->reload_actions == BIT(comb->action) &&
622
ops->reload_limits == BIT(comb->limit))
623
return false;
624
}
625
return true;
626
}
627
628
static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
629
enum devlink_command cmd, u32 portid,
630
u32 seq, int flags)
631
{
632
const struct devlink_ops *ops = devlink->ops;
633
enum devlink_eswitch_encap_mode encap_mode;
634
u8 inline_mode;
635
void *hdr;
636
int err = 0;
637
u16 mode;
638
639
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
640
if (!hdr)
641
return -EMSGSIZE;
642
643
err = devlink_nl_put_handle(msg, devlink);
644
if (err)
645
goto nla_put_failure;
646
647
if (ops->eswitch_mode_get) {
648
err = ops->eswitch_mode_get(devlink, &mode);
649
if (err)
650
goto nla_put_failure;
651
err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
652
if (err)
653
goto nla_put_failure;
654
}
655
656
if (ops->eswitch_inline_mode_get) {
657
err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
658
if (err)
659
goto nla_put_failure;
660
err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
661
inline_mode);
662
if (err)
663
goto nla_put_failure;
664
}
665
666
if (ops->eswitch_encap_mode_get) {
667
err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
668
if (err)
669
goto nla_put_failure;
670
err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
671
if (err)
672
goto nla_put_failure;
673
}
674
675
genlmsg_end(msg, hdr);
676
return 0;
677
678
nla_put_failure:
679
genlmsg_cancel(msg, hdr);
680
return err;
681
}
682
683
int devlink_nl_eswitch_get_doit(struct sk_buff *skb, struct genl_info *info)
684
{
685
struct devlink *devlink = info->user_ptr[0];
686
struct sk_buff *msg;
687
int err;
688
689
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
690
if (!msg)
691
return -ENOMEM;
692
693
err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
694
info->snd_portid, info->snd_seq, 0);
695
696
if (err) {
697
nlmsg_free(msg);
698
return err;
699
}
700
701
return genlmsg_reply(msg, info);
702
}
703
704
int devlink_nl_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info)
705
{
706
struct devlink *devlink = info->user_ptr[0];
707
const struct devlink_ops *ops = devlink->ops;
708
enum devlink_eswitch_encap_mode encap_mode;
709
u8 inline_mode;
710
int err = 0;
711
u16 mode;
712
713
if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
714
if (!ops->eswitch_mode_set)
715
return -EOPNOTSUPP;
716
mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
717
err = devlink_rate_nodes_check(devlink, mode, info->extack);
718
if (err)
719
return err;
720
err = ops->eswitch_mode_set(devlink, mode, info->extack);
721
if (err)
722
return err;
723
}
724
725
if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
726
if (!ops->eswitch_inline_mode_set)
727
return -EOPNOTSUPP;
728
inline_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
729
err = ops->eswitch_inline_mode_set(devlink, inline_mode,
730
info->extack);
731
if (err)
732
return err;
733
}
734
735
if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
736
if (!ops->eswitch_encap_mode_set)
737
return -EOPNOTSUPP;
738
encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
739
err = ops->eswitch_encap_mode_set(devlink, encap_mode,
740
info->extack);
741
if (err)
742
return err;
743
}
744
745
return 0;
746
}
747
748
int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
749
{
750
if (!req->msg)
751
return 0;
752
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
753
}
754
EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
755
756
int devlink_info_board_serial_number_put(struct devlink_info_req *req,
757
const char *bsn)
758
{
759
if (!req->msg)
760
return 0;
761
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
762
bsn);
763
}
764
EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
765
766
static int devlink_info_version_put(struct devlink_info_req *req, int attr,
767
const char *version_name,
768
const char *version_value,
769
enum devlink_info_version_type version_type)
770
{
771
struct nlattr *nest;
772
int err;
773
774
if (req->version_cb)
775
req->version_cb(version_name, version_type,
776
req->version_cb_priv);
777
778
if (!req->msg || !*version_value)
779
return 0;
780
781
nest = nla_nest_start_noflag(req->msg, attr);
782
if (!nest)
783
return -EMSGSIZE;
784
785
err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
786
version_name);
787
if (err)
788
goto nla_put_failure;
789
790
err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
791
version_value);
792
if (err)
793
goto nla_put_failure;
794
795
nla_nest_end(req->msg, nest);
796
797
return 0;
798
799
nla_put_failure:
800
nla_nest_cancel(req->msg, nest);
801
return err;
802
}
803
804
int devlink_info_version_fixed_put(struct devlink_info_req *req,
805
const char *version_name,
806
const char *version_value)
807
{
808
return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
809
version_name, version_value,
810
DEVLINK_INFO_VERSION_TYPE_NONE);
811
}
812
EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
813
814
int devlink_info_version_stored_put(struct devlink_info_req *req,
815
const char *version_name,
816
const char *version_value)
817
{
818
return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
819
version_name, version_value,
820
DEVLINK_INFO_VERSION_TYPE_NONE);
821
}
822
EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
823
824
int devlink_info_version_stored_put_ext(struct devlink_info_req *req,
825
const char *version_name,
826
const char *version_value,
827
enum devlink_info_version_type version_type)
828
{
829
return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
830
version_name, version_value,
831
version_type);
832
}
833
EXPORT_SYMBOL_GPL(devlink_info_version_stored_put_ext);
834
835
int devlink_info_version_running_put(struct devlink_info_req *req,
836
const char *version_name,
837
const char *version_value)
838
{
839
return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
840
version_name, version_value,
841
DEVLINK_INFO_VERSION_TYPE_NONE);
842
}
843
EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
844
845
int devlink_info_version_running_put_ext(struct devlink_info_req *req,
846
const char *version_name,
847
const char *version_value,
848
enum devlink_info_version_type version_type)
849
{
850
return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
851
version_name, version_value,
852
version_type);
853
}
854
EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
855
856
static int devlink_nl_driver_info_get(struct device_driver *drv,
857
struct devlink_info_req *req)
858
{
859
if (!drv)
860
return 0;
861
862
if (drv->name[0])
863
return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME,
864
drv->name);
865
866
return 0;
867
}
868
869
static int
870
devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
871
enum devlink_command cmd, u32 portid,
872
u32 seq, int flags, struct netlink_ext_ack *extack)
873
{
874
struct device *dev = devlink_to_dev(devlink);
875
struct devlink_info_req req = {};
876
void *hdr;
877
int err;
878
879
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
880
if (!hdr)
881
return -EMSGSIZE;
882
883
err = -EMSGSIZE;
884
if (devlink_nl_put_handle(msg, devlink))
885
goto err_cancel_msg;
886
887
req.msg = msg;
888
if (devlink->ops->info_get) {
889
err = devlink->ops->info_get(devlink, &req, extack);
890
if (err)
891
goto err_cancel_msg;
892
}
893
894
err = devlink_nl_driver_info_get(dev->driver, &req);
895
if (err)
896
goto err_cancel_msg;
897
898
genlmsg_end(msg, hdr);
899
return 0;
900
901
err_cancel_msg:
902
genlmsg_cancel(msg, hdr);
903
return err;
904
}
905
906
int devlink_nl_info_get_doit(struct sk_buff *skb, struct genl_info *info)
907
{
908
struct devlink *devlink = info->user_ptr[0];
909
struct sk_buff *msg;
910
int err;
911
912
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
913
if (!msg)
914
return -ENOMEM;
915
916
err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
917
info->snd_portid, info->snd_seq, 0,
918
info->extack);
919
if (err) {
920
nlmsg_free(msg);
921
return err;
922
}
923
924
return genlmsg_reply(msg, info);
925
}
926
927
static int
928
devlink_nl_info_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
929
struct netlink_callback *cb, int flags)
930
{
931
int err;
932
933
err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
934
NETLINK_CB(cb->skb).portid,
935
cb->nlh->nlmsg_seq, flags,
936
cb->extack);
937
if (err == -EOPNOTSUPP)
938
err = 0;
939
return err;
940
}
941
942
int devlink_nl_info_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb)
943
{
944
return devlink_nl_dumpit(msg, cb, devlink_nl_info_get_dump_one);
945
}
946
947
static int devlink_nl_flash_update_fill(struct sk_buff *msg,
948
struct devlink *devlink,
949
enum devlink_command cmd,
950
struct devlink_flash_notify *params)
951
{
952
void *hdr;
953
954
hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
955
if (!hdr)
956
return -EMSGSIZE;
957
958
if (devlink_nl_put_handle(msg, devlink))
959
goto nla_put_failure;
960
961
if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
962
goto out;
963
964
if (params->status_msg &&
965
nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
966
params->status_msg))
967
goto nla_put_failure;
968
if (params->component &&
969
nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
970
params->component))
971
goto nla_put_failure;
972
if (devlink_nl_put_u64(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
973
params->done))
974
goto nla_put_failure;
975
if (devlink_nl_put_u64(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
976
params->total))
977
goto nla_put_failure;
978
if (devlink_nl_put_u64(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,
979
params->timeout))
980
goto nla_put_failure;
981
982
out:
983
genlmsg_end(msg, hdr);
984
return 0;
985
986
nla_put_failure:
987
genlmsg_cancel(msg, hdr);
988
return -EMSGSIZE;
989
}
990
991
static void __devlink_flash_update_notify(struct devlink *devlink,
992
enum devlink_command cmd,
993
struct devlink_flash_notify *params)
994
{
995
struct sk_buff *msg;
996
int err;
997
998
WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
999
cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
1000
cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
1001
1002
if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
1003
return;
1004
1005
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1006
if (!msg)
1007
return;
1008
1009
err = devlink_nl_flash_update_fill(msg, devlink, cmd, params);
1010
if (err)
1011
goto out_free_msg;
1012
1013
devlink_nl_notify_send(devlink, msg);
1014
return;
1015
1016
out_free_msg:
1017
nlmsg_free(msg);
1018
}
1019
1020
static void devlink_flash_update_begin_notify(struct devlink *devlink)
1021
{
1022
struct devlink_flash_notify params = {};
1023
1024
__devlink_flash_update_notify(devlink,
1025
DEVLINK_CMD_FLASH_UPDATE,
1026
&params);
1027
}
1028
1029
static void devlink_flash_update_end_notify(struct devlink *devlink)
1030
{
1031
struct devlink_flash_notify params = {};
1032
1033
__devlink_flash_update_notify(devlink,
1034
DEVLINK_CMD_FLASH_UPDATE_END,
1035
&params);
1036
}
1037
1038
void devlink_flash_update_status_notify(struct devlink *devlink,
1039
const char *status_msg,
1040
const char *component,
1041
unsigned long done,
1042
unsigned long total)
1043
{
1044
struct devlink_flash_notify params = {
1045
.status_msg = status_msg,
1046
.component = component,
1047
.done = done,
1048
.total = total,
1049
};
1050
1051
__devlink_flash_update_notify(devlink,
1052
DEVLINK_CMD_FLASH_UPDATE_STATUS,
1053
&params);
1054
}
1055
EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
1056
1057
void devlink_flash_update_timeout_notify(struct devlink *devlink,
1058
const char *status_msg,
1059
const char *component,
1060
unsigned long timeout)
1061
{
1062
struct devlink_flash_notify params = {
1063
.status_msg = status_msg,
1064
.component = component,
1065
.timeout = timeout,
1066
};
1067
1068
__devlink_flash_update_notify(devlink,
1069
DEVLINK_CMD_FLASH_UPDATE_STATUS,
1070
&params);
1071
}
1072
EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);
1073
1074
struct devlink_flash_component_lookup_ctx {
1075
const char *lookup_name;
1076
bool lookup_name_found;
1077
};
1078
1079
static void
1080
devlink_flash_component_lookup_cb(const char *version_name,
1081
enum devlink_info_version_type version_type,
1082
void *version_cb_priv)
1083
{
1084
struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;
1085
1086
if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
1087
lookup_ctx->lookup_name_found)
1088
return;
1089
1090
lookup_ctx->lookup_name_found =
1091
!strcmp(lookup_ctx->lookup_name, version_name);
1092
}
1093
1094
static int devlink_flash_component_get(struct devlink *devlink,
1095
struct nlattr *nla_component,
1096
const char **p_component,
1097
struct netlink_ext_ack *extack)
1098
{
1099
struct devlink_flash_component_lookup_ctx lookup_ctx = {};
1100
struct devlink_info_req req = {};
1101
const char *component;
1102
int ret;
1103
1104
if (!nla_component)
1105
return 0;
1106
1107
component = nla_data(nla_component);
1108
1109
if (!devlink->ops->info_get) {
1110
NL_SET_ERR_MSG_ATTR(extack, nla_component,
1111
"component update is not supported by this device");
1112
return -EOPNOTSUPP;
1113
}
1114
1115
lookup_ctx.lookup_name = component;
1116
req.version_cb = devlink_flash_component_lookup_cb;
1117
req.version_cb_priv = &lookup_ctx;
1118
1119
ret = devlink->ops->info_get(devlink, &req, NULL);
1120
if (ret)
1121
return ret;
1122
1123
if (!lookup_ctx.lookup_name_found) {
1124
NL_SET_ERR_MSG_ATTR(extack, nla_component,
1125
"selected component is not supported by this device");
1126
return -EINVAL;
1127
}
1128
*p_component = component;
1129
return 0;
1130
}
1131
1132
int devlink_nl_flash_update_doit(struct sk_buff *skb, struct genl_info *info)
1133
{
1134
struct nlattr *nla_overwrite_mask, *nla_file_name;
1135
struct devlink_flash_update_params params = {};
1136
struct devlink *devlink = info->user_ptr[0];
1137
const char *file_name;
1138
u32 supported_params;
1139
int ret;
1140
1141
if (!devlink->ops->flash_update)
1142
return -EOPNOTSUPP;
1143
1144
if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
1145
return -EINVAL;
1146
1147
ret = devlink_flash_component_get(devlink,
1148
info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
1149
&params.component, info->extack);
1150
if (ret)
1151
return ret;
1152
1153
supported_params = devlink->ops->supported_flash_update_params;
1154
1155
nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
1156
if (nla_overwrite_mask) {
1157
struct nla_bitfield32 sections;
1158
1159
if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) {
1160
NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask,
1161
"overwrite settings are not supported by this device");
1162
return -EOPNOTSUPP;
1163
}
1164
sections = nla_get_bitfield32(nla_overwrite_mask);
1165
params.overwrite_mask = sections.value & sections.selector;
1166
}
1167
1168
nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
1169
file_name = nla_data(nla_file_name);
1170
ret = request_firmware(&params.fw, file_name, devlink->dev);
1171
if (ret) {
1172
NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name,
1173
"failed to locate the requested firmware file");
1174
return ret;
1175
}
1176
1177
devlink_flash_update_begin_notify(devlink);
1178
ret = devlink->ops->flash_update(devlink, &params, info->extack);
1179
devlink_flash_update_end_notify(devlink);
1180
1181
release_firmware(params.fw);
1182
1183
return ret;
1184
}
1185
1186
static void __devlink_compat_running_version(struct devlink *devlink,
1187
char *buf, size_t len)
1188
{
1189
struct devlink_info_req req = {};
1190
const struct nlattr *nlattr;
1191
struct sk_buff *msg;
1192
int rem, err;
1193
1194
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1195
if (!msg)
1196
return;
1197
1198
req.msg = msg;
1199
err = devlink->ops->info_get(devlink, &req, NULL);
1200
if (err)
1201
goto free_msg;
1202
1203
nla_for_each_attr_type(nlattr, DEVLINK_ATTR_INFO_VERSION_RUNNING,
1204
(void *)msg->data, msg->len, rem) {
1205
const struct nlattr *kv;
1206
int rem_kv;
1207
1208
nla_for_each_nested_type(kv, DEVLINK_ATTR_INFO_VERSION_VALUE,
1209
nlattr, rem_kv) {
1210
strlcat(buf, nla_data(kv), len);
1211
strlcat(buf, " ", len);
1212
}
1213
}
1214
free_msg:
1215
nlmsg_consume(msg);
1216
}
1217
1218
void devlink_compat_running_version(struct devlink *devlink,
1219
char *buf, size_t len)
1220
{
1221
if (!devlink->ops->info_get)
1222
return;
1223
1224
devl_lock(devlink);
1225
if (devl_is_registered(devlink))
1226
__devlink_compat_running_version(devlink, buf, len);
1227
devl_unlock(devlink);
1228
}
1229
1230
int devlink_compat_flash_update(struct devlink *devlink, const char *file_name)
1231
{
1232
struct devlink_flash_update_params params = {};
1233
int ret;
1234
1235
devl_lock(devlink);
1236
if (!devl_is_registered(devlink)) {
1237
ret = -ENODEV;
1238
goto out_unlock;
1239
}
1240
1241
if (!devlink->ops->flash_update) {
1242
ret = -EOPNOTSUPP;
1243
goto out_unlock;
1244
}
1245
1246
ret = request_firmware(&params.fw, file_name, devlink->dev);
1247
if (ret)
1248
goto out_unlock;
1249
1250
devlink_flash_update_begin_notify(devlink);
1251
ret = devlink->ops->flash_update(devlink, &params, NULL);
1252
devlink_flash_update_end_notify(devlink);
1253
1254
release_firmware(params.fw);
1255
out_unlock:
1256
devl_unlock(devlink);
1257
1258
return ret;
1259
}
1260
1261
static int
1262
devlink_nl_selftests_fill(struct sk_buff *msg, struct devlink *devlink,
1263
u32 portid, u32 seq, int flags,
1264
struct netlink_ext_ack *extack)
1265
{
1266
struct nlattr *selftests;
1267
void *hdr;
1268
int err;
1269
int i;
1270
1271
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags,
1272
DEVLINK_CMD_SELFTESTS_GET);
1273
if (!hdr)
1274
return -EMSGSIZE;
1275
1276
err = -EMSGSIZE;
1277
if (devlink_nl_put_handle(msg, devlink))
1278
goto err_cancel_msg;
1279
1280
selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
1281
if (!selftests)
1282
goto err_cancel_msg;
1283
1284
for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
1285
i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
1286
if (devlink->ops->selftest_check(devlink, i, extack)) {
1287
err = nla_put_flag(msg, i);
1288
if (err)
1289
goto err_cancel_msg;
1290
}
1291
}
1292
1293
nla_nest_end(msg, selftests);
1294
genlmsg_end(msg, hdr);
1295
return 0;
1296
1297
err_cancel_msg:
1298
genlmsg_cancel(msg, hdr);
1299
return err;
1300
}
1301
1302
int devlink_nl_selftests_get_doit(struct sk_buff *skb, struct genl_info *info)
1303
{
1304
struct devlink *devlink = info->user_ptr[0];
1305
struct sk_buff *msg;
1306
int err;
1307
1308
if (!devlink->ops->selftest_check)
1309
return -EOPNOTSUPP;
1310
1311
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1312
if (!msg)
1313
return -ENOMEM;
1314
1315
err = devlink_nl_selftests_fill(msg, devlink, info->snd_portid,
1316
info->snd_seq, 0, info->extack);
1317
if (err) {
1318
nlmsg_free(msg);
1319
return err;
1320
}
1321
1322
return genlmsg_reply(msg, info);
1323
}
1324
1325
static int devlink_nl_selftests_get_dump_one(struct sk_buff *msg,
1326
struct devlink *devlink,
1327
struct netlink_callback *cb,
1328
int flags)
1329
{
1330
if (!devlink->ops->selftest_check)
1331
return 0;
1332
1333
return devlink_nl_selftests_fill(msg, devlink,
1334
NETLINK_CB(cb->skb).portid,
1335
cb->nlh->nlmsg_seq, flags,
1336
cb->extack);
1337
}
1338
1339
int devlink_nl_selftests_get_dumpit(struct sk_buff *skb,
1340
struct netlink_callback *cb)
1341
{
1342
return devlink_nl_dumpit(skb, cb, devlink_nl_selftests_get_dump_one);
1343
}
1344
1345
static int devlink_selftest_result_put(struct sk_buff *skb, unsigned int id,
1346
enum devlink_selftest_status test_status)
1347
{
1348
struct nlattr *result_attr;
1349
1350
result_attr = nla_nest_start(skb, DEVLINK_ATTR_SELFTEST_RESULT);
1351
if (!result_attr)
1352
return -EMSGSIZE;
1353
1354
if (nla_put_u32(skb, DEVLINK_ATTR_SELFTEST_RESULT_ID, id) ||
1355
nla_put_u8(skb, DEVLINK_ATTR_SELFTEST_RESULT_STATUS,
1356
test_status))
1357
goto nla_put_failure;
1358
1359
nla_nest_end(skb, result_attr);
1360
return 0;
1361
1362
nla_put_failure:
1363
nla_nest_cancel(skb, result_attr);
1364
return -EMSGSIZE;
1365
}
1366
1367
static const struct nla_policy devlink_selftest_nl_policy[DEVLINK_ATTR_SELFTEST_ID_MAX + 1] = {
1368
[DEVLINK_ATTR_SELFTEST_ID_FLASH] = { .type = NLA_FLAG },
1369
};
1370
1371
int devlink_nl_selftests_run_doit(struct sk_buff *skb, struct genl_info *info)
1372
{
1373
struct nlattr *tb[DEVLINK_ATTR_SELFTEST_ID_MAX + 1];
1374
struct devlink *devlink = info->user_ptr[0];
1375
struct nlattr *attrs, *selftests;
1376
struct sk_buff *msg;
1377
void *hdr;
1378
int err;
1379
int i;
1380
1381
if (!devlink->ops->selftest_run || !devlink->ops->selftest_check)
1382
return -EOPNOTSUPP;
1383
1384
if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SELFTESTS))
1385
return -EINVAL;
1386
1387
attrs = info->attrs[DEVLINK_ATTR_SELFTESTS];
1388
1389
err = nla_parse_nested(tb, DEVLINK_ATTR_SELFTEST_ID_MAX, attrs,
1390
devlink_selftest_nl_policy, info->extack);
1391
if (err < 0)
1392
return err;
1393
1394
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1395
if (!msg)
1396
return -ENOMEM;
1397
1398
err = -EMSGSIZE;
1399
hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
1400
&devlink_nl_family, 0, DEVLINK_CMD_SELFTESTS_RUN);
1401
if (!hdr)
1402
goto free_msg;
1403
1404
if (devlink_nl_put_handle(msg, devlink))
1405
goto genlmsg_cancel;
1406
1407
selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
1408
if (!selftests)
1409
goto genlmsg_cancel;
1410
1411
for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
1412
i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
1413
enum devlink_selftest_status test_status;
1414
1415
if (nla_get_flag(tb[i])) {
1416
if (!devlink->ops->selftest_check(devlink, i,
1417
info->extack)) {
1418
if (devlink_selftest_result_put(msg, i,
1419
DEVLINK_SELFTEST_STATUS_SKIP))
1420
goto selftests_nest_cancel;
1421
continue;
1422
}
1423
1424
test_status = devlink->ops->selftest_run(devlink, i,
1425
info->extack);
1426
if (devlink_selftest_result_put(msg, i, test_status))
1427
goto selftests_nest_cancel;
1428
}
1429
}
1430
1431
nla_nest_end(msg, selftests);
1432
genlmsg_end(msg, hdr);
1433
return genlmsg_reply(msg, info);
1434
1435
selftests_nest_cancel:
1436
nla_nest_cancel(msg, selftests);
1437
genlmsg_cancel:
1438
genlmsg_cancel(msg, hdr);
1439
free_msg:
1440
nlmsg_free(msg);
1441
return err;
1442
}
1443
1444