1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * net/core/devlink.c - Network physical/parent device Netlink interface
4 *
5 * Heavily inspired by net/wireless/
6 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
7 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
8 */
9
10 #include <linux/etherdevice.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/types.h>
14 #include <linux/slab.h>
15 #include <linux/gfp.h>
16 #include <linux/device.h>
17 #include <linux/list.h>
18 #include <linux/netdevice.h>
19 #include <linux/spinlock.h>
20 #include <linux/refcount.h>
21 #include <linux/workqueue.h>
22 #include <linux/u64_stats_sync.h>
23 #include <linux/timekeeping.h>
24 #include <rdma/ib_verbs.h>
25 #include <net/netlink.h>
26 #include <net/genetlink.h>
27 #include <net/rtnetlink.h>
28 #include <net/net_namespace.h>
29 #include <net/sock.h>
30 #include <net/devlink.h>
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/devlink.h>
33
34 #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
35 (__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
36
37 struct devlink_dev_stats {
38 u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
39 u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
40 };
41
42 struct devlink {
43 u32 index;
44 struct list_head port_list;
45 struct list_head rate_list;
46 struct list_head sb_list;
47 struct list_head dpipe_table_list;
48 struct list_head resource_list;
49 struct list_head param_list;
50 struct list_head region_list;
51 struct list_head reporter_list;
52 struct mutex reporters_lock; /* protects reporter_list */
53 struct devlink_dpipe_headers *dpipe_headers;
54 struct list_head trap_list;
55 struct list_head trap_group_list;
56 struct list_head trap_policer_list;
57 struct list_head linecard_list;
58 struct mutex linecards_lock; /* protects linecard_list */
59 const struct devlink_ops *ops;
60 u64 features;
61 struct xarray snapshot_ids;
62 struct devlink_dev_stats stats;
63 struct device *dev;
64 possible_net_t _net;
65 /* Serializes access to devlink instance specific objects such as
66 * port, sb, dpipe, resource, params, region, traps and more.
67 */
68 struct mutex lock;
69 struct lock_class_key lock_key;
70 u8 reload_failed:1;
71 refcount_t refcount;
72 struct completion comp;
73 struct rcu_head rcu;
74 char priv[] __aligned(NETDEV_ALIGN);
75 };
76
77 struct devlink_linecard_ops;
78 struct devlink_linecard_type;
79
80 struct devlink_linecard {
81 struct list_head list;
82 struct devlink *devlink;
83 unsigned int index;
84 refcount_t refcount;
85 const struct devlink_linecard_ops *ops;
86 void *priv;
87 enum devlink_linecard_state state;
88 struct mutex state_lock; /* Protects state */
89 const char *type;
90 struct devlink_linecard_type *types;
91 unsigned int types_count;
92 struct devlink *nested_devlink;
93 };
94
95 /**
96 * struct devlink_resource - devlink resource
97 * @name: name of the resource
98 * @id: id, per devlink instance
99 * @size: size of the resource
100 * @size_new: updated size of the resource, reload is needed
101 * @size_valid: valid in case the total size of the resource is valid
102 * including its children
103 * @parent: parent resource
104 * @size_params: size parameters
105 * @list: parent list
106 * @resource_list: list of child resources
107 * @occ_get: occupancy getter callback
108 * @occ_get_priv: occupancy getter callback priv
109 */
110 struct devlink_resource {
111 const char *name;
112 u64 id;
113 u64 size;
114 u64 size_new;
115 bool size_valid;
116 struct devlink_resource *parent;
117 struct devlink_resource_size_params size_params;
118 struct list_head list;
119 struct list_head resource_list;
120 devlink_resource_occ_get_t *occ_get;
121 void *occ_get_priv;
122 };
123
devlink_priv(struct devlink * devlink)124 void *devlink_priv(struct devlink *devlink)
125 {
126 return &devlink->priv;
127 }
128 EXPORT_SYMBOL_GPL(devlink_priv);
129
priv_to_devlink(void * priv)130 struct devlink *priv_to_devlink(void *priv)
131 {
132 return container_of(priv, struct devlink, priv);
133 }
134 EXPORT_SYMBOL_GPL(priv_to_devlink);
135
devlink_to_dev(const struct devlink * devlink)136 struct device *devlink_to_dev(const struct devlink *devlink)
137 {
138 return devlink->dev;
139 }
140 EXPORT_SYMBOL_GPL(devlink_to_dev);
141
142 static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
143 {
144 .name = "destination mac",
145 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
146 .bitwidth = 48,
147 },
148 };
149
150 struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
151 .name = "ethernet",
152 .id = DEVLINK_DPIPE_HEADER_ETHERNET,
153 .fields = devlink_dpipe_fields_ethernet,
154 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
155 .global = true,
156 };
157 EXPORT_SYMBOL_GPL(devlink_dpipe_header_ethernet);
158
159 static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
160 {
161 .name = "destination ip",
162 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
163 .bitwidth = 32,
164 },
165 };
166
167 struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
168 .name = "ipv4",
169 .id = DEVLINK_DPIPE_HEADER_IPV4,
170 .fields = devlink_dpipe_fields_ipv4,
171 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
172 .global = true,
173 };
174 EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv4);
175
176 static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
177 {
178 .name = "destination ip",
179 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
180 .bitwidth = 128,
181 },
182 };
183
184 struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
185 .name = "ipv6",
186 .id = DEVLINK_DPIPE_HEADER_IPV6,
187 .fields = devlink_dpipe_fields_ipv6,
188 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
189 .global = true,
190 };
191 EXPORT_SYMBOL_GPL(devlink_dpipe_header_ipv6);
192
193 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
194 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
195 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_trap_report);
196
197 static const struct nla_policy devlink_function_nl_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {
198 [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY },
199 [DEVLINK_PORT_FN_ATTR_STATE] =
200 NLA_POLICY_RANGE(NLA_U8, DEVLINK_PORT_FN_STATE_INACTIVE,
201 DEVLINK_PORT_FN_STATE_ACTIVE),
202 };
203
204 static const struct nla_policy devlink_selftest_nl_policy[DEVLINK_ATTR_SELFTEST_ID_MAX + 1] = {
205 [DEVLINK_ATTR_SELFTEST_ID_FLASH] = { .type = NLA_FLAG },
206 };
207
208 static DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC);
209 #define DEVLINK_REGISTERED XA_MARK_1
210 #define DEVLINK_UNREGISTERING XA_MARK_2
211
212 /* devlink instances are open to the access from the user space after
213 * devlink_register() call. Such logical barrier allows us to have certain
214 * expectations related to locking.
215 *
216 * Before *_register() - we are in initialization stage and no parallel
217 * access possible to the devlink instance. All drivers perform that phase
218 * by implicitly holding device_lock.
219 *
220 * After *_register() - users and driver can access devlink instance at
221 * the same time.
222 */
223 #define ASSERT_DEVLINK_REGISTERED(d) \
224 WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
225 #define ASSERT_DEVLINK_NOT_REGISTERED(d) \
226 WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
227
devlink_net(const struct devlink * devlink)228 struct net *devlink_net(const struct devlink *devlink)
229 {
230 return read_pnet(&devlink->_net);
231 }
232 EXPORT_SYMBOL_GPL(devlink_net);
233
__devlink_put_rcu(struct rcu_head * head)234 static void __devlink_put_rcu(struct rcu_head *head)
235 {
236 struct devlink *devlink = container_of(head, struct devlink, rcu);
237
238 complete(&devlink->comp);
239 }
240
devlink_put(struct devlink * devlink)241 void devlink_put(struct devlink *devlink)
242 {
243 if (refcount_dec_and_test(&devlink->refcount))
244 /* Make sure unregister operation that may await the completion
245 * is unblocked only after all users are after the end of
246 * RCU grace period.
247 */
248 call_rcu(&devlink->rcu, __devlink_put_rcu);
249 }
250
devlink_try_get(struct devlink * devlink)251 struct devlink *__must_check devlink_try_get(struct devlink *devlink)
252 {
253 if (refcount_inc_not_zero(&devlink->refcount))
254 return devlink;
255 return NULL;
256 }
257
devl_assert_locked(struct devlink * devlink)258 void devl_assert_locked(struct devlink *devlink)
259 {
260 lockdep_assert_held(&devlink->lock);
261 }
262 EXPORT_SYMBOL_GPL(devl_assert_locked);
263
264 #ifdef CONFIG_LOCKDEP
265 /* For use in conjunction with LOCKDEP only e.g. rcu_dereference_protected() */
devl_lock_is_held(struct devlink * devlink)266 bool devl_lock_is_held(struct devlink *devlink)
267 {
268 return lockdep_is_held(&devlink->lock);
269 }
270 EXPORT_SYMBOL_GPL(devl_lock_is_held);
271 #endif
272
devl_lock(struct devlink * devlink)273 void devl_lock(struct devlink *devlink)
274 {
275 mutex_lock(&devlink->lock);
276 }
277 EXPORT_SYMBOL_GPL(devl_lock);
278
devl_trylock(struct devlink * devlink)279 int devl_trylock(struct devlink *devlink)
280 {
281 return mutex_trylock(&devlink->lock);
282 }
283 EXPORT_SYMBOL_GPL(devl_trylock);
284
devl_unlock(struct devlink * devlink)285 void devl_unlock(struct devlink *devlink)
286 {
287 mutex_unlock(&devlink->lock);
288 }
289 EXPORT_SYMBOL_GPL(devl_unlock);
290
291 static struct devlink *
devlinks_xa_find_get(struct net * net,unsigned long * indexp,xa_mark_t filter,void * (* xa_find_fn)(struct xarray *,unsigned long *,unsigned long,xa_mark_t))292 devlinks_xa_find_get(struct net *net, unsigned long *indexp, xa_mark_t filter,
293 void * (*xa_find_fn)(struct xarray *, unsigned long *,
294 unsigned long, xa_mark_t))
295 {
296 struct devlink *devlink;
297
298 rcu_read_lock();
299 retry:
300 devlink = xa_find_fn(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
301 if (!devlink)
302 goto unlock;
303
304 /* In case devlink_unregister() was already called and "unregistering"
305 * mark was set, do not allow to get a devlink reference here.
306 * This prevents live-lock of devlink_unregister() wait for completion.
307 */
308 if (xa_get_mark(&devlinks, *indexp, DEVLINK_UNREGISTERING))
309 goto retry;
310
311 /* For a possible retry, the xa_find_after() should be always used */
312 xa_find_fn = xa_find_after;
313 if (!devlink_try_get(devlink))
314 goto retry;
315 if (!net_eq(devlink_net(devlink), net)) {
316 devlink_put(devlink);
317 goto retry;
318 }
319 unlock:
320 rcu_read_unlock();
321 return devlink;
322 }
323
devlinks_xa_find_get_first(struct net * net,unsigned long * indexp,xa_mark_t filter)324 static struct devlink *devlinks_xa_find_get_first(struct net *net,
325 unsigned long *indexp,
326 xa_mark_t filter)
327 {
328 return devlinks_xa_find_get(net, indexp, filter, xa_find);
329 }
330
devlinks_xa_find_get_next(struct net * net,unsigned long * indexp,xa_mark_t filter)331 static struct devlink *devlinks_xa_find_get_next(struct net *net,
332 unsigned long *indexp,
333 xa_mark_t filter)
334 {
335 return devlinks_xa_find_get(net, indexp, filter, xa_find_after);
336 }
337
338 /* Iterate over devlink pointers which were possible to get reference to.
339 * devlink_put() needs to be called for each iterated devlink pointer
340 * in loop body in order to release the reference.
341 */
342 #define devlinks_xa_for_each_get(net, index, devlink, filter) \
343 for (index = 0, \
344 devlink = devlinks_xa_find_get_first(net, &index, filter); \
345 devlink; devlink = devlinks_xa_find_get_next(net, &index, filter))
346
347 #define devlinks_xa_for_each_registered_get(net, index, devlink) \
348 devlinks_xa_for_each_get(net, index, devlink, DEVLINK_REGISTERED)
349
devlink_get_from_attrs(struct net * net,struct nlattr ** attrs)350 static struct devlink *devlink_get_from_attrs(struct net *net,
351 struct nlattr **attrs)
352 {
353 struct devlink *devlink;
354 unsigned long index;
355 char *busname;
356 char *devname;
357
358 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
359 return ERR_PTR(-EINVAL);
360
361 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
362 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
363
364 devlinks_xa_for_each_registered_get(net, index, devlink) {
365 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
366 strcmp(dev_name(devlink->dev), devname) == 0)
367 return devlink;
368 devlink_put(devlink);
369 }
370
371 return ERR_PTR(-ENODEV);
372 }
373
374 #define ASSERT_DEVLINK_PORT_REGISTERED(devlink_port) \
375 WARN_ON_ONCE(!(devlink_port)->registered)
376 #define ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port) \
377 WARN_ON_ONCE((devlink_port)->registered)
378 #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port) \
379 WARN_ON_ONCE(!(devlink_port)->initialized)
380
devlink_port_get_by_index(struct devlink * devlink,unsigned int port_index)381 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
382 unsigned int port_index)
383 {
384 struct devlink_port *devlink_port;
385
386 list_for_each_entry(devlink_port, &devlink->port_list, list) {
387 if (devlink_port->index == port_index)
388 return devlink_port;
389 }
390 return NULL;
391 }
392
devlink_port_index_exists(struct devlink * devlink,unsigned int port_index)393 static bool devlink_port_index_exists(struct devlink *devlink,
394 unsigned int port_index)
395 {
396 return devlink_port_get_by_index(devlink, port_index);
397 }
398
devlink_port_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)399 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
400 struct nlattr **attrs)
401 {
402 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
403 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
404 struct devlink_port *devlink_port;
405
406 devlink_port = devlink_port_get_by_index(devlink, port_index);
407 if (!devlink_port)
408 return ERR_PTR(-ENODEV);
409 return devlink_port;
410 }
411 return ERR_PTR(-EINVAL);
412 }
413
devlink_port_get_from_info(struct devlink * devlink,struct genl_info * info)414 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
415 struct genl_info *info)
416 {
417 return devlink_port_get_from_attrs(devlink, info->attrs);
418 }
419
420 static inline bool
devlink_rate_is_leaf(struct devlink_rate * devlink_rate)421 devlink_rate_is_leaf(struct devlink_rate *devlink_rate)
422 {
423 return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF;
424 }
425
426 static inline bool
devlink_rate_is_node(struct devlink_rate * devlink_rate)427 devlink_rate_is_node(struct devlink_rate *devlink_rate)
428 {
429 return devlink_rate->type == DEVLINK_RATE_TYPE_NODE;
430 }
431
432 static struct devlink_rate *
devlink_rate_leaf_get_from_info(struct devlink * devlink,struct genl_info * info)433 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info)
434 {
435 struct devlink_rate *devlink_rate;
436 struct devlink_port *devlink_port;
437
438 devlink_port = devlink_port_get_from_attrs(devlink, info->attrs);
439 if (IS_ERR(devlink_port))
440 return ERR_CAST(devlink_port);
441 devlink_rate = devlink_port->devlink_rate;
442 return devlink_rate ?: ERR_PTR(-ENODEV);
443 }
444
445 static struct devlink_rate *
devlink_rate_node_get_by_name(struct devlink * devlink,const char * node_name)446 devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name)
447 {
448 static struct devlink_rate *devlink_rate;
449
450 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
451 if (devlink_rate_is_node(devlink_rate) &&
452 !strcmp(node_name, devlink_rate->name))
453 return devlink_rate;
454 }
455 return ERR_PTR(-ENODEV);
456 }
457
458 static struct devlink_rate *
devlink_rate_node_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)459 devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs)
460 {
461 const char *rate_node_name;
462 size_t len;
463
464 if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME])
465 return ERR_PTR(-EINVAL);
466 rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]);
467 len = strlen(rate_node_name);
468 /* Name cannot be empty or decimal number */
469 if (!len || strspn(rate_node_name, "0123456789") == len)
470 return ERR_PTR(-EINVAL);
471
472 return devlink_rate_node_get_by_name(devlink, rate_node_name);
473 }
474
475 static struct devlink_rate *
devlink_rate_node_get_from_info(struct devlink * devlink,struct genl_info * info)476 devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info)
477 {
478 return devlink_rate_node_get_from_attrs(devlink, info->attrs);
479 }
480
481 static struct devlink_rate *
devlink_rate_get_from_info(struct devlink * devlink,struct genl_info * info)482 devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info)
483 {
484 struct nlattr **attrs = info->attrs;
485
486 if (attrs[DEVLINK_ATTR_PORT_INDEX])
487 return devlink_rate_leaf_get_from_info(devlink, info);
488 else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME])
489 return devlink_rate_node_get_from_info(devlink, info);
490 else
491 return ERR_PTR(-EINVAL);
492 }
493
494 static struct devlink_linecard *
devlink_linecard_get_by_index(struct devlink * devlink,unsigned int linecard_index)495 devlink_linecard_get_by_index(struct devlink *devlink,
496 unsigned int linecard_index)
497 {
498 struct devlink_linecard *devlink_linecard;
499
500 list_for_each_entry(devlink_linecard, &devlink->linecard_list, list) {
501 if (devlink_linecard->index == linecard_index)
502 return devlink_linecard;
503 }
504 return NULL;
505 }
506
devlink_linecard_index_exists(struct devlink * devlink,unsigned int linecard_index)507 static bool devlink_linecard_index_exists(struct devlink *devlink,
508 unsigned int linecard_index)
509 {
510 return devlink_linecard_get_by_index(devlink, linecard_index);
511 }
512
513 static struct devlink_linecard *
devlink_linecard_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)514 devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs)
515 {
516 if (attrs[DEVLINK_ATTR_LINECARD_INDEX]) {
517 u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]);
518 struct devlink_linecard *linecard;
519
520 mutex_lock(&devlink->linecards_lock);
521 linecard = devlink_linecard_get_by_index(devlink, linecard_index);
522 if (linecard)
523 refcount_inc(&linecard->refcount);
524 mutex_unlock(&devlink->linecards_lock);
525 if (!linecard)
526 return ERR_PTR(-ENODEV);
527 return linecard;
528 }
529 return ERR_PTR(-EINVAL);
530 }
531
532 static struct devlink_linecard *
devlink_linecard_get_from_info(struct devlink * devlink,struct genl_info * info)533 devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info)
534 {
535 return devlink_linecard_get_from_attrs(devlink, info->attrs);
536 }
537
devlink_linecard_put(struct devlink_linecard * linecard)538 static void devlink_linecard_put(struct devlink_linecard *linecard)
539 {
540 if (refcount_dec_and_test(&linecard->refcount)) {
541 mutex_destroy(&linecard->state_lock);
542 kfree(linecard);
543 }
544 }
545
546 struct devlink_sb {
547 struct list_head list;
548 unsigned int index;
549 u32 size;
550 u16 ingress_pools_count;
551 u16 egress_pools_count;
552 u16 ingress_tc_count;
553 u16 egress_tc_count;
554 };
555
devlink_sb_pool_count(struct devlink_sb * devlink_sb)556 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
557 {
558 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
559 }
560
devlink_sb_get_by_index(struct devlink * devlink,unsigned int sb_index)561 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
562 unsigned int sb_index)
563 {
564 struct devlink_sb *devlink_sb;
565
566 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
567 if (devlink_sb->index == sb_index)
568 return devlink_sb;
569 }
570 return NULL;
571 }
572
devlink_sb_index_exists(struct devlink * devlink,unsigned int sb_index)573 static bool devlink_sb_index_exists(struct devlink *devlink,
574 unsigned int sb_index)
575 {
576 return devlink_sb_get_by_index(devlink, sb_index);
577 }
578
devlink_sb_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)579 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
580 struct nlattr **attrs)
581 {
582 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
583 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
584 struct devlink_sb *devlink_sb;
585
586 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
587 if (!devlink_sb)
588 return ERR_PTR(-ENODEV);
589 return devlink_sb;
590 }
591 return ERR_PTR(-EINVAL);
592 }
593
devlink_sb_get_from_info(struct devlink * devlink,struct genl_info * info)594 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
595 struct genl_info *info)
596 {
597 return devlink_sb_get_from_attrs(devlink, info->attrs);
598 }
599
devlink_sb_pool_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,u16 * p_pool_index)600 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
601 struct nlattr **attrs,
602 u16 *p_pool_index)
603 {
604 u16 val;
605
606 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
607 return -EINVAL;
608
609 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
610 if (val >= devlink_sb_pool_count(devlink_sb))
611 return -EINVAL;
612 *p_pool_index = val;
613 return 0;
614 }
615
devlink_sb_pool_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,u16 * p_pool_index)616 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
617 struct genl_info *info,
618 u16 *p_pool_index)
619 {
620 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
621 p_pool_index);
622 }
623
624 static int
devlink_sb_pool_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_pool_type * p_pool_type)625 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
626 enum devlink_sb_pool_type *p_pool_type)
627 {
628 u8 val;
629
630 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
631 return -EINVAL;
632
633 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
634 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
635 val != DEVLINK_SB_POOL_TYPE_EGRESS)
636 return -EINVAL;
637 *p_pool_type = val;
638 return 0;
639 }
640
641 static int
devlink_sb_pool_type_get_from_info(struct genl_info * info,enum devlink_sb_pool_type * p_pool_type)642 devlink_sb_pool_type_get_from_info(struct genl_info *info,
643 enum devlink_sb_pool_type *p_pool_type)
644 {
645 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
646 }
647
648 static int
devlink_sb_th_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_threshold_type * p_th_type)649 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
650 enum devlink_sb_threshold_type *p_th_type)
651 {
652 u8 val;
653
654 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
655 return -EINVAL;
656
657 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
658 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
659 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
660 return -EINVAL;
661 *p_th_type = val;
662 return 0;
663 }
664
665 static int
devlink_sb_th_type_get_from_info(struct genl_info * info,enum devlink_sb_threshold_type * p_th_type)666 devlink_sb_th_type_get_from_info(struct genl_info *info,
667 enum devlink_sb_threshold_type *p_th_type)
668 {
669 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
670 }
671
672 static int
devlink_sb_tc_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)673 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
674 struct nlattr **attrs,
675 enum devlink_sb_pool_type pool_type,
676 u16 *p_tc_index)
677 {
678 u16 val;
679
680 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
681 return -EINVAL;
682
683 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
684 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
685 val >= devlink_sb->ingress_tc_count)
686 return -EINVAL;
687 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
688 val >= devlink_sb->egress_tc_count)
689 return -EINVAL;
690 *p_tc_index = val;
691 return 0;
692 }
693
694 static int
devlink_sb_tc_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)695 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
696 struct genl_info *info,
697 enum devlink_sb_pool_type pool_type,
698 u16 *p_tc_index)
699 {
700 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
701 pool_type, p_tc_index);
702 }
703
704 struct devlink_region {
705 struct devlink *devlink;
706 struct devlink_port *port;
707 struct list_head list;
708 union {
709 const struct devlink_region_ops *ops;
710 const struct devlink_port_region_ops *port_ops;
711 };
712 struct mutex snapshot_lock; /* protects snapshot_list,
713 * max_snapshots and cur_snapshots
714 * consistency.
715 */
716 struct list_head snapshot_list;
717 u32 max_snapshots;
718 u32 cur_snapshots;
719 u64 size;
720 };
721
722 struct devlink_snapshot {
723 struct list_head list;
724 struct devlink_region *region;
725 u8 *data;
726 u32 id;
727 };
728
729 static struct devlink_region *
devlink_region_get_by_name(struct devlink * devlink,const char * region_name)730 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
731 {
732 struct devlink_region *region;
733
734 list_for_each_entry(region, &devlink->region_list, list)
735 if (!strcmp(region->ops->name, region_name))
736 return region;
737
738 return NULL;
739 }
740
741 static struct devlink_region *
devlink_port_region_get_by_name(struct devlink_port * port,const char * region_name)742 devlink_port_region_get_by_name(struct devlink_port *port,
743 const char *region_name)
744 {
745 struct devlink_region *region;
746
747 list_for_each_entry(region, &port->region_list, list)
748 if (!strcmp(region->ops->name, region_name))
749 return region;
750
751 return NULL;
752 }
753
754 static struct devlink_snapshot *
devlink_region_snapshot_get_by_id(struct devlink_region * region,u32 id)755 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
756 {
757 struct devlink_snapshot *snapshot;
758
759 list_for_each_entry(snapshot, ®ion->snapshot_list, list)
760 if (snapshot->id == id)
761 return snapshot;
762
763 return NULL;
764 }
765
766 #define DEVLINK_NL_FLAG_NEED_PORT BIT(0)
767 #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1)
768 #define DEVLINK_NL_FLAG_NEED_RATE BIT(2)
769 #define DEVLINK_NL_FLAG_NEED_RATE_NODE BIT(3)
770 #define DEVLINK_NL_FLAG_NEED_LINECARD BIT(4)
771
devlink_nl_pre_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)772 static int devlink_nl_pre_doit(const struct genl_ops *ops,
773 struct sk_buff *skb, struct genl_info *info)
774 {
775 struct devlink_linecard *linecard;
776 struct devlink_port *devlink_port;
777 struct devlink *devlink;
778 int err;
779
780 devlink = devlink_get_from_attrs(genl_info_net(info), info->attrs);
781 if (IS_ERR(devlink))
782 return PTR_ERR(devlink);
783 devl_lock(devlink);
784 info->user_ptr[0] = devlink;
785 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
786 devlink_port = devlink_port_get_from_info(devlink, info);
787 if (IS_ERR(devlink_port)) {
788 err = PTR_ERR(devlink_port);
789 goto unlock;
790 }
791 info->user_ptr[1] = devlink_port;
792 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT) {
793 devlink_port = devlink_port_get_from_info(devlink, info);
794 if (!IS_ERR(devlink_port))
795 info->user_ptr[1] = devlink_port;
796 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_RATE) {
797 struct devlink_rate *devlink_rate;
798
799 devlink_rate = devlink_rate_get_from_info(devlink, info);
800 if (IS_ERR(devlink_rate)) {
801 err = PTR_ERR(devlink_rate);
802 goto unlock;
803 }
804 info->user_ptr[1] = devlink_rate;
805 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_RATE_NODE) {
806 struct devlink_rate *rate_node;
807
808 rate_node = devlink_rate_node_get_from_info(devlink, info);
809 if (IS_ERR(rate_node)) {
810 err = PTR_ERR(rate_node);
811 goto unlock;
812 }
813 info->user_ptr[1] = rate_node;
814 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_LINECARD) {
815 linecard = devlink_linecard_get_from_info(devlink, info);
816 if (IS_ERR(linecard)) {
817 err = PTR_ERR(linecard);
818 goto unlock;
819 }
820 info->user_ptr[1] = linecard;
821 }
822 return 0;
823
824 unlock:
825 devl_unlock(devlink);
826 devlink_put(devlink);
827 return err;
828 }
829
devlink_nl_post_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)830 static void devlink_nl_post_doit(const struct genl_ops *ops,
831 struct sk_buff *skb, struct genl_info *info)
832 {
833 struct devlink_linecard *linecard;
834 struct devlink *devlink;
835
836 devlink = info->user_ptr[0];
837 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_LINECARD) {
838 linecard = info->user_ptr[1];
839 devlink_linecard_put(linecard);
840 }
841 devl_unlock(devlink);
842 devlink_put(devlink);
843 }
844
845 static struct genl_family devlink_nl_family;
846
847 enum devlink_multicast_groups {
848 DEVLINK_MCGRP_CONFIG,
849 };
850
851 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
852 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
853 };
854
devlink_nl_put_handle(struct sk_buff * msg,struct devlink * devlink)855 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
856 {
857 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
858 return -EMSGSIZE;
859 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
860 return -EMSGSIZE;
861 return 0;
862 }
863
devlink_nl_put_nested_handle(struct sk_buff * msg,struct devlink * devlink)864 static int devlink_nl_put_nested_handle(struct sk_buff *msg, struct devlink *devlink)
865 {
866 struct nlattr *nested_attr;
867
868 nested_attr = nla_nest_start(msg, DEVLINK_ATTR_NESTED_DEVLINK);
869 if (!nested_attr)
870 return -EMSGSIZE;
871 if (devlink_nl_put_handle(msg, devlink))
872 goto nla_put_failure;
873
874 nla_nest_end(msg, nested_attr);
875 return 0;
876
877 nla_put_failure:
878 nla_nest_cancel(msg, nested_attr);
879 return -EMSGSIZE;
880 }
881
882 struct devlink_reload_combination {
883 enum devlink_reload_action action;
884 enum devlink_reload_limit limit;
885 };
886
887 static const struct devlink_reload_combination devlink_reload_invalid_combinations[] = {
888 {
889 /* can't reinitialize driver with no down time */
890 .action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
891 .limit = DEVLINK_RELOAD_LIMIT_NO_RESET,
892 },
893 };
894
895 static bool
devlink_reload_combination_is_invalid(enum devlink_reload_action action,enum devlink_reload_limit limit)896 devlink_reload_combination_is_invalid(enum devlink_reload_action action,
897 enum devlink_reload_limit limit)
898 {
899 int i;
900
901 for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)
902 if (devlink_reload_invalid_combinations[i].action == action &&
903 devlink_reload_invalid_combinations[i].limit == limit)
904 return true;
905 return false;
906 }
907
908 static bool
devlink_reload_action_is_supported(struct devlink * devlink,enum devlink_reload_action action)909 devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
910 {
911 return test_bit(action, &devlink->ops->reload_actions);
912 }
913
914 static bool
devlink_reload_limit_is_supported(struct devlink * devlink,enum devlink_reload_limit limit)915 devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_limit limit)
916 {
917 return test_bit(limit, &devlink->ops->reload_limits);
918 }
919
devlink_reload_stat_put(struct sk_buff * msg,enum devlink_reload_limit limit,u32 value)920 static int devlink_reload_stat_put(struct sk_buff *msg,
921 enum devlink_reload_limit limit, u32 value)
922 {
923 struct nlattr *reload_stats_entry;
924
925 reload_stats_entry = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS_ENTRY);
926 if (!reload_stats_entry)
927 return -EMSGSIZE;
928
929 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_STATS_LIMIT, limit) ||
930 nla_put_u32(msg, DEVLINK_ATTR_RELOAD_STATS_VALUE, value))
931 goto nla_put_failure;
932 nla_nest_end(msg, reload_stats_entry);
933 return 0;
934
935 nla_put_failure:
936 nla_nest_cancel(msg, reload_stats_entry);
937 return -EMSGSIZE;
938 }
939
devlink_reload_stats_put(struct sk_buff * msg,struct devlink * devlink,bool is_remote)940 static int devlink_reload_stats_put(struct sk_buff *msg, struct devlink *devlink, bool is_remote)
941 {
942 struct nlattr *reload_stats_attr, *act_info, *act_stats;
943 int i, j, stat_idx;
944 u32 value;
945
946 if (!is_remote)
947 reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_STATS);
948 else
949 reload_stats_attr = nla_nest_start(msg, DEVLINK_ATTR_REMOTE_RELOAD_STATS);
950
951 if (!reload_stats_attr)
952 return -EMSGSIZE;
953
954 for (i = 0; i <= DEVLINK_RELOAD_ACTION_MAX; i++) {
955 if ((!is_remote &&
956 !devlink_reload_action_is_supported(devlink, i)) ||
957 i == DEVLINK_RELOAD_ACTION_UNSPEC)
958 continue;
959 act_info = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_INFO);
960 if (!act_info)
961 goto nla_put_failure;
962
963 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_ACTION, i))
964 goto action_info_nest_cancel;
965 act_stats = nla_nest_start(msg, DEVLINK_ATTR_RELOAD_ACTION_STATS);
966 if (!act_stats)
967 goto action_info_nest_cancel;
968
969 for (j = 0; j <= DEVLINK_RELOAD_LIMIT_MAX; j++) {
970 /* Remote stats are shown even if not locally supported.
971 * Stats of actions with unspecified limit are shown
972 * though drivers don't need to register unspecified
973 * limit.
974 */
975 if ((!is_remote && j != DEVLINK_RELOAD_LIMIT_UNSPEC &&
976 !devlink_reload_limit_is_supported(devlink, j)) ||
977 devlink_reload_combination_is_invalid(i, j))
978 continue;
979
980 stat_idx = j * __DEVLINK_RELOAD_ACTION_MAX + i;
981 if (!is_remote)
982 value = devlink->stats.reload_stats[stat_idx];
983 else
984 value = devlink->stats.remote_reload_stats[stat_idx];
985 if (devlink_reload_stat_put(msg, j, value))
986 goto action_stats_nest_cancel;
987 }
988 nla_nest_end(msg, act_stats);
989 nla_nest_end(msg, act_info);
990 }
991 nla_nest_end(msg, reload_stats_attr);
992 return 0;
993
994 action_stats_nest_cancel:
995 nla_nest_cancel(msg, act_stats);
996 action_info_nest_cancel:
997 nla_nest_cancel(msg, act_info);
998 nla_put_failure:
999 nla_nest_cancel(msg, reload_stats_attr);
1000 return -EMSGSIZE;
1001 }
1002
devlink_nl_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)1003 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
1004 enum devlink_command cmd, u32 portid,
1005 u32 seq, int flags)
1006 {
1007 struct nlattr *dev_stats;
1008 void *hdr;
1009
1010 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1011 if (!hdr)
1012 return -EMSGSIZE;
1013
1014 if (devlink_nl_put_handle(msg, devlink))
1015 goto nla_put_failure;
1016 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
1017 goto nla_put_failure;
1018
1019 dev_stats = nla_nest_start(msg, DEVLINK_ATTR_DEV_STATS);
1020 if (!dev_stats)
1021 goto nla_put_failure;
1022
1023 if (devlink_reload_stats_put(msg, devlink, false))
1024 goto dev_stats_nest_cancel;
1025 if (devlink_reload_stats_put(msg, devlink, true))
1026 goto dev_stats_nest_cancel;
1027
1028 nla_nest_end(msg, dev_stats);
1029 genlmsg_end(msg, hdr);
1030 return 0;
1031
1032 dev_stats_nest_cancel:
1033 nla_nest_cancel(msg, dev_stats);
1034 nla_put_failure:
1035 genlmsg_cancel(msg, hdr);
1036 return -EMSGSIZE;
1037 }
1038
devlink_notify(struct devlink * devlink,enum devlink_command cmd)1039 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
1040 {
1041 struct sk_buff *msg;
1042 int err;
1043
1044 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
1045 WARN_ON(!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED));
1046
1047 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1048 if (!msg)
1049 return;
1050
1051 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
1052 if (err) {
1053 nlmsg_free(msg);
1054 return;
1055 }
1056
1057 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
1058 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
1059 }
1060
devlink_nl_port_attrs_put(struct sk_buff * msg,struct devlink_port * devlink_port)1061 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
1062 struct devlink_port *devlink_port)
1063 {
1064 struct devlink_port_attrs *attrs = &devlink_port->attrs;
1065
1066 if (!devlink_port->attrs_set)
1067 return 0;
1068 if (attrs->lanes) {
1069 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_LANES, attrs->lanes))
1070 return -EMSGSIZE;
1071 }
1072 if (nla_put_u8(msg, DEVLINK_ATTR_PORT_SPLITTABLE, attrs->splittable))
1073 return -EMSGSIZE;
1074 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
1075 return -EMSGSIZE;
1076 switch (devlink_port->attrs.flavour) {
1077 case DEVLINK_PORT_FLAVOUR_PCI_PF:
1078 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER,
1079 attrs->pci_pf.controller) ||
1080 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_pf.pf))
1081 return -EMSGSIZE;
1082 if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_pf.external))
1083 return -EMSGSIZE;
1084 break;
1085 case DEVLINK_PORT_FLAVOUR_PCI_VF:
1086 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER,
1087 attrs->pci_vf.controller) ||
1088 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs->pci_vf.pf) ||
1089 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, attrs->pci_vf.vf))
1090 return -EMSGSIZE;
1091 if (nla_put_u8(msg, DEVLINK_ATTR_PORT_EXTERNAL, attrs->pci_vf.external))
1092 return -EMSGSIZE;
1093 break;
1094 case DEVLINK_PORT_FLAVOUR_PCI_SF:
1095 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER,
1096 attrs->pci_sf.controller) ||
1097 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
1098 attrs->pci_sf.pf) ||
1099 nla_put_u32(msg, DEVLINK_ATTR_PORT_PCI_SF_NUMBER,
1100 attrs->pci_sf.sf))
1101 return -EMSGSIZE;
1102 break;
1103 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
1104 case DEVLINK_PORT_FLAVOUR_CPU:
1105 case DEVLINK_PORT_FLAVOUR_DSA:
1106 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
1107 attrs->phys.port_number))
1108 return -EMSGSIZE;
1109 if (!attrs->split)
1110 return 0;
1111 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
1112 attrs->phys.port_number))
1113 return -EMSGSIZE;
1114 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
1115 attrs->phys.split_subport_number))
1116 return -EMSGSIZE;
1117 break;
1118 default:
1119 break;
1120 }
1121 return 0;
1122 }
1123
devlink_port_fn_hw_addr_fill(const struct devlink_ops * ops,struct devlink_port * port,struct sk_buff * msg,struct netlink_ext_ack * extack,bool * msg_updated)1124 static int devlink_port_fn_hw_addr_fill(const struct devlink_ops *ops,
1125 struct devlink_port *port,
1126 struct sk_buff *msg,
1127 struct netlink_ext_ack *extack,
1128 bool *msg_updated)
1129 {
1130 u8 hw_addr[MAX_ADDR_LEN];
1131 int hw_addr_len;
1132 int err;
1133
1134 if (!ops->port_function_hw_addr_get)
1135 return 0;
1136
1137 err = ops->port_function_hw_addr_get(port, hw_addr, &hw_addr_len,
1138 extack);
1139 if (err) {
1140 if (err == -EOPNOTSUPP)
1141 return 0;
1142 return err;
1143 }
1144 err = nla_put(msg, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, hw_addr_len, hw_addr);
1145 if (err)
1146 return err;
1147 *msg_updated = true;
1148 return 0;
1149 }
1150
devlink_nl_rate_fill(struct sk_buff * msg,struct devlink_rate * devlink_rate,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)1151 static int devlink_nl_rate_fill(struct sk_buff *msg,
1152 struct devlink_rate *devlink_rate,
1153 enum devlink_command cmd, u32 portid, u32 seq,
1154 int flags, struct netlink_ext_ack *extack)
1155 {
1156 struct devlink *devlink = devlink_rate->devlink;
1157 void *hdr;
1158
1159 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1160 if (!hdr)
1161 return -EMSGSIZE;
1162
1163 if (devlink_nl_put_handle(msg, devlink))
1164 goto nla_put_failure;
1165
1166 if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type))
1167 goto nla_put_failure;
1168
1169 if (devlink_rate_is_leaf(devlink_rate)) {
1170 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
1171 devlink_rate->devlink_port->index))
1172 goto nla_put_failure;
1173 } else if (devlink_rate_is_node(devlink_rate)) {
1174 if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME,
1175 devlink_rate->name))
1176 goto nla_put_failure;
1177 }
1178
1179 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE,
1180 devlink_rate->tx_share, DEVLINK_ATTR_PAD))
1181 goto nla_put_failure;
1182
1183 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX,
1184 devlink_rate->tx_max, DEVLINK_ATTR_PAD))
1185 goto nla_put_failure;
1186
1187 if (devlink_rate->parent)
1188 if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME,
1189 devlink_rate->parent->name))
1190 goto nla_put_failure;
1191
1192 genlmsg_end(msg, hdr);
1193 return 0;
1194
1195 nla_put_failure:
1196 genlmsg_cancel(msg, hdr);
1197 return -EMSGSIZE;
1198 }
1199
1200 static bool
devlink_port_fn_state_valid(enum devlink_port_fn_state state)1201 devlink_port_fn_state_valid(enum devlink_port_fn_state state)
1202 {
1203 return state == DEVLINK_PORT_FN_STATE_INACTIVE ||
1204 state == DEVLINK_PORT_FN_STATE_ACTIVE;
1205 }
1206
1207 static bool
devlink_port_fn_opstate_valid(enum devlink_port_fn_opstate opstate)1208 devlink_port_fn_opstate_valid(enum devlink_port_fn_opstate opstate)
1209 {
1210 return opstate == DEVLINK_PORT_FN_OPSTATE_DETACHED ||
1211 opstate == DEVLINK_PORT_FN_OPSTATE_ATTACHED;
1212 }
1213
devlink_port_fn_state_fill(const struct devlink_ops * ops,struct devlink_port * port,struct sk_buff * msg,struct netlink_ext_ack * extack,bool * msg_updated)1214 static int devlink_port_fn_state_fill(const struct devlink_ops *ops,
1215 struct devlink_port *port,
1216 struct sk_buff *msg,
1217 struct netlink_ext_ack *extack,
1218 bool *msg_updated)
1219 {
1220 enum devlink_port_fn_opstate opstate;
1221 enum devlink_port_fn_state state;
1222 int err;
1223
1224 if (!ops->port_fn_state_get)
1225 return 0;
1226
1227 err = ops->port_fn_state_get(port, &state, &opstate, extack);
1228 if (err) {
1229 if (err == -EOPNOTSUPP)
1230 return 0;
1231 return err;
1232 }
1233 if (!devlink_port_fn_state_valid(state)) {
1234 WARN_ON_ONCE(1);
1235 NL_SET_ERR_MSG_MOD(extack, "Invalid state read from driver");
1236 return -EINVAL;
1237 }
1238 if (!devlink_port_fn_opstate_valid(opstate)) {
1239 WARN_ON_ONCE(1);
1240 NL_SET_ERR_MSG_MOD(extack,
1241 "Invalid operational state read from driver");
1242 return -EINVAL;
1243 }
1244 if (nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_STATE, state) ||
1245 nla_put_u8(msg, DEVLINK_PORT_FN_ATTR_OPSTATE, opstate))
1246 return -EMSGSIZE;
1247 *msg_updated = true;
1248 return 0;
1249 }
1250
1251 static int
devlink_nl_port_function_attrs_put(struct sk_buff * msg,struct devlink_port * port,struct netlink_ext_ack * extack)1252 devlink_nl_port_function_attrs_put(struct sk_buff *msg, struct devlink_port *port,
1253 struct netlink_ext_ack *extack)
1254 {
1255 const struct devlink_ops *ops;
1256 struct nlattr *function_attr;
1257 bool msg_updated = false;
1258 int err;
1259
1260 function_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PORT_FUNCTION);
1261 if (!function_attr)
1262 return -EMSGSIZE;
1263
1264 ops = port->devlink->ops;
1265 err = devlink_port_fn_hw_addr_fill(ops, port, msg, extack,
1266 &msg_updated);
1267 if (err)
1268 goto out;
1269 err = devlink_port_fn_state_fill(ops, port, msg, extack, &msg_updated);
1270 out:
1271 if (err || !msg_updated)
1272 nla_nest_cancel(msg, function_attr);
1273 else
1274 nla_nest_end(msg, function_attr);
1275 return err;
1276 }
1277
devlink_nl_port_fill(struct sk_buff * msg,struct devlink_port * devlink_port,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)1278 static int devlink_nl_port_fill(struct sk_buff *msg,
1279 struct devlink_port *devlink_port,
1280 enum devlink_command cmd, u32 portid, u32 seq,
1281 int flags, struct netlink_ext_ack *extack)
1282 {
1283 struct devlink *devlink = devlink_port->devlink;
1284 void *hdr;
1285
1286 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1287 if (!hdr)
1288 return -EMSGSIZE;
1289
1290 if (devlink_nl_put_handle(msg, devlink))
1291 goto nla_put_failure;
1292 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1293 goto nla_put_failure;
1294
1295 /* Hold rtnl lock while accessing port's netdev attributes. */
1296 rtnl_lock();
1297 spin_lock_bh(&devlink_port->type_lock);
1298 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
1299 goto nla_put_failure_type_locked;
1300 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
1301 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
1302 devlink_port->desired_type))
1303 goto nla_put_failure_type_locked;
1304 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
1305 struct net *net = devlink_net(devlink_port->devlink);
1306 struct net_device *netdev = devlink_port->type_dev;
1307
1308 if (netdev && net_eq(net, dev_net(netdev)) &&
1309 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
1310 netdev->ifindex) ||
1311 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
1312 netdev->name)))
1313 goto nla_put_failure_type_locked;
1314 }
1315 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
1316 struct ib_device *ibdev = devlink_port->type_dev;
1317
1318 if (ibdev &&
1319 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
1320 ibdev->name))
1321 goto nla_put_failure_type_locked;
1322 }
1323 spin_unlock_bh(&devlink_port->type_lock);
1324 rtnl_unlock();
1325 if (devlink_nl_port_attrs_put(msg, devlink_port))
1326 goto nla_put_failure;
1327 if (devlink_nl_port_function_attrs_put(msg, devlink_port, extack))
1328 goto nla_put_failure;
1329 if (devlink_port->linecard &&
1330 nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX,
1331 devlink_port->linecard->index))
1332 goto nla_put_failure;
1333
1334 genlmsg_end(msg, hdr);
1335 return 0;
1336
1337 nla_put_failure_type_locked:
1338 spin_unlock_bh(&devlink_port->type_lock);
1339 rtnl_unlock();
1340 nla_put_failure:
1341 genlmsg_cancel(msg, hdr);
1342 return -EMSGSIZE;
1343 }
1344
devlink_port_notify(struct devlink_port * devlink_port,enum devlink_command cmd)1345 static void devlink_port_notify(struct devlink_port *devlink_port,
1346 enum devlink_command cmd)
1347 {
1348 struct devlink *devlink = devlink_port->devlink;
1349 struct sk_buff *msg;
1350 int err;
1351
1352 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
1353
1354 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
1355 return;
1356
1357 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1358 if (!msg)
1359 return;
1360
1361 err = devlink_nl_port_fill(msg, devlink_port, cmd, 0, 0, 0, NULL);
1362 if (err) {
1363 nlmsg_free(msg);
1364 return;
1365 }
1366
1367 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
1368 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
1369 }
1370
devlink_rate_notify(struct devlink_rate * devlink_rate,enum devlink_command cmd)1371 static void devlink_rate_notify(struct devlink_rate *devlink_rate,
1372 enum devlink_command cmd)
1373 {
1374 struct devlink *devlink = devlink_rate->devlink;
1375 struct sk_buff *msg;
1376 int err;
1377
1378 WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL);
1379
1380 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
1381 return;
1382
1383 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1384 if (!msg)
1385 return;
1386
1387 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL);
1388 if (err) {
1389 nlmsg_free(msg);
1390 return;
1391 }
1392
1393 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
1394 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
1395 }
1396
devlink_nl_cmd_rate_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1397 static int devlink_nl_cmd_rate_get_dumpit(struct sk_buff *msg,
1398 struct netlink_callback *cb)
1399 {
1400 struct devlink_rate *devlink_rate;
1401 struct devlink *devlink;
1402 int start = cb->args[0];
1403 unsigned long index;
1404 int idx = 0;
1405 int err = 0;
1406
1407 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
1408 devl_lock(devlink);
1409 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
1410 enum devlink_command cmd = DEVLINK_CMD_RATE_NEW;
1411 u32 id = NETLINK_CB(cb->skb).portid;
1412
1413 if (idx < start) {
1414 idx++;
1415 continue;
1416 }
1417 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id,
1418 cb->nlh->nlmsg_seq,
1419 NLM_F_MULTI, NULL);
1420 if (err) {
1421 devl_unlock(devlink);
1422 devlink_put(devlink);
1423 goto out;
1424 }
1425 idx++;
1426 }
1427 devl_unlock(devlink);
1428 devlink_put(devlink);
1429 }
1430 out:
1431 if (err != -EMSGSIZE)
1432 return err;
1433
1434 cb->args[0] = idx;
1435 return msg->len;
1436 }
1437
devlink_nl_cmd_rate_get_doit(struct sk_buff * skb,struct genl_info * info)1438 static int devlink_nl_cmd_rate_get_doit(struct sk_buff *skb,
1439 struct genl_info *info)
1440 {
1441 struct devlink_rate *devlink_rate = info->user_ptr[1];
1442 struct sk_buff *msg;
1443 int err;
1444
1445 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1446 if (!msg)
1447 return -ENOMEM;
1448
1449 err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW,
1450 info->snd_portid, info->snd_seq, 0,
1451 info->extack);
1452 if (err) {
1453 nlmsg_free(msg);
1454 return err;
1455 }
1456
1457 return genlmsg_reply(msg, info);
1458 }
1459
1460 static bool
devlink_rate_is_parent_node(struct devlink_rate * devlink_rate,struct devlink_rate * parent)1461 devlink_rate_is_parent_node(struct devlink_rate *devlink_rate,
1462 struct devlink_rate *parent)
1463 {
1464 while (parent) {
1465 if (parent == devlink_rate)
1466 return true;
1467 parent = parent->parent;
1468 }
1469 return false;
1470 }
1471
devlink_nl_cmd_get_doit(struct sk_buff * skb,struct genl_info * info)1472 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
1473 {
1474 struct devlink *devlink = info->user_ptr[0];
1475 struct sk_buff *msg;
1476 int err;
1477
1478 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1479 if (!msg)
1480 return -ENOMEM;
1481
1482 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
1483 info->snd_portid, info->snd_seq, 0);
1484 if (err) {
1485 nlmsg_free(msg);
1486 return err;
1487 }
1488
1489 return genlmsg_reply(msg, info);
1490 }
1491
devlink_nl_cmd_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1492 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
1493 struct netlink_callback *cb)
1494 {
1495 struct devlink *devlink;
1496 int start = cb->args[0];
1497 unsigned long index;
1498 int idx = 0;
1499 int err;
1500
1501 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
1502 if (idx < start) {
1503 idx++;
1504 devlink_put(devlink);
1505 continue;
1506 }
1507
1508 devl_lock(devlink);
1509 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
1510 NETLINK_CB(cb->skb).portid,
1511 cb->nlh->nlmsg_seq, NLM_F_MULTI);
1512 devl_unlock(devlink);
1513 devlink_put(devlink);
1514
1515 if (err)
1516 goto out;
1517 idx++;
1518 }
1519 out:
1520 cb->args[0] = idx;
1521 return msg->len;
1522 }
1523
devlink_nl_cmd_port_get_doit(struct sk_buff * skb,struct genl_info * info)1524 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
1525 struct genl_info *info)
1526 {
1527 struct devlink_port *devlink_port = info->user_ptr[1];
1528 struct sk_buff *msg;
1529 int err;
1530
1531 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1532 if (!msg)
1533 return -ENOMEM;
1534
1535 err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW,
1536 info->snd_portid, info->snd_seq, 0,
1537 info->extack);
1538 if (err) {
1539 nlmsg_free(msg);
1540 return err;
1541 }
1542
1543 return genlmsg_reply(msg, info);
1544 }
1545
devlink_nl_cmd_port_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1546 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
1547 struct netlink_callback *cb)
1548 {
1549 struct devlink *devlink;
1550 struct devlink_port *devlink_port;
1551 int start = cb->args[0];
1552 unsigned long index;
1553 int idx = 0;
1554 int err;
1555
1556 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
1557 devl_lock(devlink);
1558 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1559 if (idx < start) {
1560 idx++;
1561 continue;
1562 }
1563 err = devlink_nl_port_fill(msg, devlink_port,
1564 DEVLINK_CMD_NEW,
1565 NETLINK_CB(cb->skb).portid,
1566 cb->nlh->nlmsg_seq,
1567 NLM_F_MULTI, cb->extack);
1568 if (err) {
1569 devl_unlock(devlink);
1570 devlink_put(devlink);
1571 goto out;
1572 }
1573 idx++;
1574 }
1575 devl_unlock(devlink);
1576 devlink_put(devlink);
1577 }
1578 out:
1579 cb->args[0] = idx;
1580 return msg->len;
1581 }
1582
devlink_port_type_set(struct devlink_port * devlink_port,enum devlink_port_type port_type)1583 static int devlink_port_type_set(struct devlink_port *devlink_port,
1584 enum devlink_port_type port_type)
1585
1586 {
1587 int err;
1588
1589 if (!devlink_port->devlink->ops->port_type_set)
1590 return -EOPNOTSUPP;
1591
1592 if (port_type == devlink_port->type)
1593 return 0;
1594
1595 err = devlink_port->devlink->ops->port_type_set(devlink_port,
1596 port_type);
1597 if (err)
1598 return err;
1599
1600 devlink_port->desired_type = port_type;
1601 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1602 return 0;
1603 }
1604
devlink_port_function_hw_addr_set(struct devlink_port * port,const struct nlattr * attr,struct netlink_ext_ack * extack)1605 static int devlink_port_function_hw_addr_set(struct devlink_port *port,
1606 const struct nlattr *attr,
1607 struct netlink_ext_ack *extack)
1608 {
1609 const struct devlink_ops *ops = port->devlink->ops;
1610 const u8 *hw_addr;
1611 int hw_addr_len;
1612
1613 hw_addr = nla_data(attr);
1614 hw_addr_len = nla_len(attr);
1615 if (hw_addr_len > MAX_ADDR_LEN) {
1616 NL_SET_ERR_MSG_MOD(extack, "Port function hardware address too long");
1617 return -EINVAL;
1618 }
1619 if (port->type == DEVLINK_PORT_TYPE_ETH) {
1620 if (hw_addr_len != ETH_ALEN) {
1621 NL_SET_ERR_MSG_MOD(extack, "Address must be 6 bytes for Ethernet device");
1622 return -EINVAL;
1623 }
1624 if (!is_unicast_ether_addr(hw_addr)) {
1625 NL_SET_ERR_MSG_MOD(extack, "Non-unicast hardware address unsupported");
1626 return -EINVAL;
1627 }
1628 }
1629
1630 if (!ops->port_function_hw_addr_set) {
1631 NL_SET_ERR_MSG_MOD(extack, "Port doesn't support function attributes");
1632 return -EOPNOTSUPP;
1633 }
1634
1635 return ops->port_function_hw_addr_set(port, hw_addr, hw_addr_len,
1636 extack);
1637 }
1638
devlink_port_fn_state_set(struct devlink_port * port,const struct nlattr * attr,struct netlink_ext_ack * extack)1639 static int devlink_port_fn_state_set(struct devlink_port *port,
1640 const struct nlattr *attr,
1641 struct netlink_ext_ack *extack)
1642 {
1643 enum devlink_port_fn_state state;
1644 const struct devlink_ops *ops;
1645
1646 state = nla_get_u8(attr);
1647 ops = port->devlink->ops;
1648 if (!ops->port_fn_state_set) {
1649 NL_SET_ERR_MSG_MOD(extack,
1650 "Function does not support state setting");
1651 return -EOPNOTSUPP;
1652 }
1653 return ops->port_fn_state_set(port, state, extack);
1654 }
1655
devlink_port_function_set(struct devlink_port * port,const struct nlattr * attr,struct netlink_ext_ack * extack)1656 static int devlink_port_function_set(struct devlink_port *port,
1657 const struct nlattr *attr,
1658 struct netlink_ext_ack *extack)
1659 {
1660 struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1];
1661 int err;
1662
1663 err = nla_parse_nested(tb, DEVLINK_PORT_FUNCTION_ATTR_MAX, attr,
1664 devlink_function_nl_policy, extack);
1665 if (err < 0) {
1666 NL_SET_ERR_MSG_MOD(extack, "Fail to parse port function attributes");
1667 return err;
1668 }
1669
1670 attr = tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR];
1671 if (attr) {
1672 err = devlink_port_function_hw_addr_set(port, attr, extack);
1673 if (err)
1674 return err;
1675 }
1676 /* Keep this as the last function attribute set, so that when
1677 * multiple port function attributes are set along with state,
1678 * Those can be applied first before activating the state.
1679 */
1680 attr = tb[DEVLINK_PORT_FN_ATTR_STATE];
1681 if (attr)
1682 err = devlink_port_fn_state_set(port, attr, extack);
1683
1684 if (!err)
1685 devlink_port_notify(port, DEVLINK_CMD_PORT_NEW);
1686 return err;
1687 }
1688
devlink_nl_cmd_port_set_doit(struct sk_buff * skb,struct genl_info * info)1689 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
1690 struct genl_info *info)
1691 {
1692 struct devlink_port *devlink_port = info->user_ptr[1];
1693 int err;
1694
1695 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
1696 enum devlink_port_type port_type;
1697
1698 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
1699 err = devlink_port_type_set(devlink_port, port_type);
1700 if (err)
1701 return err;
1702 }
1703
1704 if (info->attrs[DEVLINK_ATTR_PORT_FUNCTION]) {
1705 struct nlattr *attr = info->attrs[DEVLINK_ATTR_PORT_FUNCTION];
1706 struct netlink_ext_ack *extack = info->extack;
1707
1708 err = devlink_port_function_set(devlink_port, attr, extack);
1709 if (err)
1710 return err;
1711 }
1712
1713 return 0;
1714 }
1715
devlink_nl_cmd_port_split_doit(struct sk_buff * skb,struct genl_info * info)1716 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
1717 struct genl_info *info)
1718 {
1719 struct devlink_port *devlink_port = info->user_ptr[1];
1720 struct devlink *devlink = info->user_ptr[0];
1721 u32 count;
1722
1723 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_SPLIT_COUNT))
1724 return -EINVAL;
1725 if (!devlink->ops->port_split)
1726 return -EOPNOTSUPP;
1727
1728 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
1729
1730 if (!devlink_port->attrs.splittable) {
1731 /* Split ports cannot be split. */
1732 if (devlink_port->attrs.split)
1733 NL_SET_ERR_MSG_MOD(info->extack, "Port cannot be split further");
1734 else
1735 NL_SET_ERR_MSG_MOD(info->extack, "Port cannot be split");
1736 return -EINVAL;
1737 }
1738
1739 if (count < 2 || !is_power_of_2(count) || count > devlink_port->attrs.lanes) {
1740 NL_SET_ERR_MSG_MOD(info->extack, "Invalid split count");
1741 return -EINVAL;
1742 }
1743
1744 return devlink->ops->port_split(devlink, devlink_port, count,
1745 info->extack);
1746 }
1747
devlink_nl_cmd_port_unsplit_doit(struct sk_buff * skb,struct genl_info * info)1748 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
1749 struct genl_info *info)
1750 {
1751 struct devlink_port *devlink_port = info->user_ptr[1];
1752 struct devlink *devlink = info->user_ptr[0];
1753
1754 if (!devlink->ops->port_unsplit)
1755 return -EOPNOTSUPP;
1756 return devlink->ops->port_unsplit(devlink, devlink_port, info->extack);
1757 }
1758
devlink_port_new_notify(struct devlink * devlink,unsigned int port_index,struct genl_info * info)1759 static int devlink_port_new_notify(struct devlink *devlink,
1760 unsigned int port_index,
1761 struct genl_info *info)
1762 {
1763 struct devlink_port *devlink_port;
1764 struct sk_buff *msg;
1765 int err;
1766
1767 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1768 if (!msg)
1769 return -ENOMEM;
1770
1771 lockdep_assert_held(&devlink->lock);
1772 devlink_port = devlink_port_get_by_index(devlink, port_index);
1773 if (!devlink_port) {
1774 err = -ENODEV;
1775 goto out;
1776 }
1777
1778 err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW,
1779 info->snd_portid, info->snd_seq, 0, NULL);
1780 if (err)
1781 goto out;
1782
1783 return genlmsg_reply(msg, info);
1784
1785 out:
1786 nlmsg_free(msg);
1787 return err;
1788 }
1789
devlink_nl_cmd_port_new_doit(struct sk_buff * skb,struct genl_info * info)1790 static int devlink_nl_cmd_port_new_doit(struct sk_buff *skb,
1791 struct genl_info *info)
1792 {
1793 struct netlink_ext_ack *extack = info->extack;
1794 struct devlink_port_new_attrs new_attrs = {};
1795 struct devlink *devlink = info->user_ptr[0];
1796 unsigned int new_port_index;
1797 int err;
1798
1799 if (!devlink->ops->port_new || !devlink->ops->port_del)
1800 return -EOPNOTSUPP;
1801
1802 if (!info->attrs[DEVLINK_ATTR_PORT_FLAVOUR] ||
1803 !info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]) {
1804 NL_SET_ERR_MSG_MOD(extack, "Port flavour or PCI PF are not specified");
1805 return -EINVAL;
1806 }
1807 new_attrs.flavour = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_FLAVOUR]);
1808 new_attrs.pfnum =
1809 nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_PCI_PF_NUMBER]);
1810
1811 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
1812 /* Port index of the new port being created by driver. */
1813 new_attrs.port_index =
1814 nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
1815 new_attrs.port_index_valid = true;
1816 }
1817 if (info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]) {
1818 new_attrs.controller =
1819 nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_CONTROLLER_NUMBER]);
1820 new_attrs.controller_valid = true;
1821 }
1822 if (new_attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_SF &&
1823 info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) {
1824 new_attrs.sfnum = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]);
1825 new_attrs.sfnum_valid = true;
1826 }
1827
1828 err = devlink->ops->port_new(devlink, &new_attrs, extack,
1829 &new_port_index);
1830 if (err)
1831 return err;
1832
1833 err = devlink_port_new_notify(devlink, new_port_index, info);
1834 if (err && err != -ENODEV) {
1835 /* Fail to send the response; destroy newly created port. */
1836 devlink->ops->port_del(devlink, new_port_index, extack);
1837 }
1838 return err;
1839 }
1840
devlink_nl_cmd_port_del_doit(struct sk_buff * skb,struct genl_info * info)1841 static int devlink_nl_cmd_port_del_doit(struct sk_buff *skb,
1842 struct genl_info *info)
1843 {
1844 struct netlink_ext_ack *extack = info->extack;
1845 struct devlink *devlink = info->user_ptr[0];
1846 unsigned int port_index;
1847
1848 if (!devlink->ops->port_del)
1849 return -EOPNOTSUPP;
1850
1851 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_INDEX)) {
1852 NL_SET_ERR_MSG_MOD(extack, "Port index is not specified");
1853 return -EINVAL;
1854 }
1855 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
1856
1857 return devlink->ops->port_del(devlink, port_index, extack);
1858 }
1859
1860 static int
devlink_nl_rate_parent_node_set(struct devlink_rate * devlink_rate,struct genl_info * info,struct nlattr * nla_parent)1861 devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
1862 struct genl_info *info,
1863 struct nlattr *nla_parent)
1864 {
1865 struct devlink *devlink = devlink_rate->devlink;
1866 const char *parent_name = nla_data(nla_parent);
1867 const struct devlink_ops *ops = devlink->ops;
1868 size_t len = strlen(parent_name);
1869 struct devlink_rate *parent;
1870 int err = -EOPNOTSUPP;
1871
1872 parent = devlink_rate->parent;
1873 if (parent && len) {
1874 NL_SET_ERR_MSG_MOD(info->extack, "Rate object already has parent.");
1875 return -EBUSY;
1876 } else if (parent && !len) {
1877 if (devlink_rate_is_leaf(devlink_rate))
1878 err = ops->rate_leaf_parent_set(devlink_rate, NULL,
1879 devlink_rate->priv, NULL,
1880 info->extack);
1881 else if (devlink_rate_is_node(devlink_rate))
1882 err = ops->rate_node_parent_set(devlink_rate, NULL,
1883 devlink_rate->priv, NULL,
1884 info->extack);
1885 if (err)
1886 return err;
1887
1888 refcount_dec(&parent->refcnt);
1889 devlink_rate->parent = NULL;
1890 } else if (!parent && len) {
1891 parent = devlink_rate_node_get_by_name(devlink, parent_name);
1892 if (IS_ERR(parent))
1893 return -ENODEV;
1894
1895 if (parent == devlink_rate) {
1896 NL_SET_ERR_MSG_MOD(info->extack, "Parent to self is not allowed");
1897 return -EINVAL;
1898 }
1899
1900 if (devlink_rate_is_node(devlink_rate) &&
1901 devlink_rate_is_parent_node(devlink_rate, parent->parent)) {
1902 NL_SET_ERR_MSG_MOD(info->extack, "Node is already a parent of parent node.");
1903 return -EEXIST;
1904 }
1905
1906 if (devlink_rate_is_leaf(devlink_rate))
1907 err = ops->rate_leaf_parent_set(devlink_rate, parent,
1908 devlink_rate->priv, parent->priv,
1909 info->extack);
1910 else if (devlink_rate_is_node(devlink_rate))
1911 err = ops->rate_node_parent_set(devlink_rate, parent,
1912 devlink_rate->priv, parent->priv,
1913 info->extack);
1914 if (err)
1915 return err;
1916
1917 refcount_inc(&parent->refcnt);
1918 devlink_rate->parent = parent;
1919 }
1920
1921 return 0;
1922 }
1923
devlink_nl_rate_set(struct devlink_rate * devlink_rate,const struct devlink_ops * ops,struct genl_info * info)1924 static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
1925 const struct devlink_ops *ops,
1926 struct genl_info *info)
1927 {
1928 struct nlattr *nla_parent, **attrs = info->attrs;
1929 int err = -EOPNOTSUPP;
1930 u64 rate;
1931
1932 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) {
1933 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]);
1934 if (devlink_rate_is_leaf(devlink_rate))
1935 err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv,
1936 rate, info->extack);
1937 else if (devlink_rate_is_node(devlink_rate))
1938 err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv,
1939 rate, info->extack);
1940 if (err)
1941 return err;
1942 devlink_rate->tx_share = rate;
1943 }
1944
1945 if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) {
1946 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]);
1947 if (devlink_rate_is_leaf(devlink_rate))
1948 err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv,
1949 rate, info->extack);
1950 else if (devlink_rate_is_node(devlink_rate))
1951 err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv,
1952 rate, info->extack);
1953 if (err)
1954 return err;
1955 devlink_rate->tx_max = rate;
1956 }
1957
1958 nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
1959 if (nla_parent) {
1960 err = devlink_nl_rate_parent_node_set(devlink_rate, info,
1961 nla_parent);
1962 if (err)
1963 return err;
1964 }
1965
1966 return 0;
1967 }
1968
devlink_rate_set_ops_supported(const struct devlink_ops * ops,struct genl_info * info,enum devlink_rate_type type)1969 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops,
1970 struct genl_info *info,
1971 enum devlink_rate_type type)
1972 {
1973 struct nlattr **attrs = info->attrs;
1974
1975 if (type == DEVLINK_RATE_TYPE_LEAF) {
1976 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) {
1977 NL_SET_ERR_MSG_MOD(info->extack, "TX share set isn't supported for the leafs");
1978 return false;
1979 }
1980 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) {
1981 NL_SET_ERR_MSG_MOD(info->extack, "TX max set isn't supported for the leafs");
1982 return false;
1983 }
1984 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
1985 !ops->rate_leaf_parent_set) {
1986 NL_SET_ERR_MSG_MOD(info->extack, "Parent set isn't supported for the leafs");
1987 return false;
1988 }
1989 } else if (type == DEVLINK_RATE_TYPE_NODE) {
1990 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) {
1991 NL_SET_ERR_MSG_MOD(info->extack, "TX share set isn't supported for the nodes");
1992 return false;
1993 }
1994 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) {
1995 NL_SET_ERR_MSG_MOD(info->extack, "TX max set isn't supported for the nodes");
1996 return false;
1997 }
1998 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
1999 !ops->rate_node_parent_set) {
2000 NL_SET_ERR_MSG_MOD(info->extack, "Parent set isn't supported for the nodes");
2001 return false;
2002 }
2003 } else {
2004 WARN(1, "Unknown type of rate object");
2005 return false;
2006 }
2007
2008 return true;
2009 }
2010
devlink_nl_cmd_rate_set_doit(struct sk_buff * skb,struct genl_info * info)2011 static int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb,
2012 struct genl_info *info)
2013 {
2014 struct devlink_rate *devlink_rate = info->user_ptr[1];
2015 struct devlink *devlink = devlink_rate->devlink;
2016 const struct devlink_ops *ops = devlink->ops;
2017 int err;
2018
2019 if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type))
2020 return -EOPNOTSUPP;
2021
2022 err = devlink_nl_rate_set(devlink_rate, ops, info);
2023
2024 if (!err)
2025 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW);
2026 return err;
2027 }
2028
devlink_nl_cmd_rate_new_doit(struct sk_buff * skb,struct genl_info * info)2029 static int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb,
2030 struct genl_info *info)
2031 {
2032 struct devlink *devlink = info->user_ptr[0];
2033 struct devlink_rate *rate_node;
2034 const struct devlink_ops *ops;
2035 int err;
2036
2037 ops = devlink->ops;
2038 if (!ops || !ops->rate_node_new || !ops->rate_node_del) {
2039 NL_SET_ERR_MSG_MOD(info->extack, "Rate nodes aren't supported");
2040 return -EOPNOTSUPP;
2041 }
2042
2043 if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE))
2044 return -EOPNOTSUPP;
2045
2046 rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs);
2047 if (!IS_ERR(rate_node))
2048 return -EEXIST;
2049 else if (rate_node == ERR_PTR(-EINVAL))
2050 return -EINVAL;
2051
2052 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL);
2053 if (!rate_node)
2054 return -ENOMEM;
2055
2056 rate_node->devlink = devlink;
2057 rate_node->type = DEVLINK_RATE_TYPE_NODE;
2058 rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL);
2059 if (!rate_node->name) {
2060 err = -ENOMEM;
2061 goto err_strdup;
2062 }
2063
2064 err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack);
2065 if (err)
2066 goto err_node_new;
2067
2068 err = devlink_nl_rate_set(rate_node, ops, info);
2069 if (err)
2070 goto err_rate_set;
2071
2072 refcount_set(&rate_node->refcnt, 1);
2073 list_add(&rate_node->list, &devlink->rate_list);
2074 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
2075 return 0;
2076
2077 err_rate_set:
2078 ops->rate_node_del(rate_node, rate_node->priv, info->extack);
2079 err_node_new:
2080 kfree(rate_node->name);
2081 err_strdup:
2082 kfree(rate_node);
2083 return err;
2084 }
2085
devlink_nl_cmd_rate_del_doit(struct sk_buff * skb,struct genl_info * info)2086 static int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb,
2087 struct genl_info *info)
2088 {
2089 struct devlink_rate *rate_node = info->user_ptr[1];
2090 struct devlink *devlink = rate_node->devlink;
2091 const struct devlink_ops *ops = devlink->ops;
2092 int err;
2093
2094 if (refcount_read(&rate_node->refcnt) > 1) {
2095 NL_SET_ERR_MSG_MOD(info->extack, "Node has children. Cannot delete node.");
2096 return -EBUSY;
2097 }
2098
2099 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL);
2100 err = ops->rate_node_del(rate_node, rate_node->priv, info->extack);
2101 if (rate_node->parent)
2102 refcount_dec(&rate_node->parent->refcnt);
2103 list_del(&rate_node->list);
2104 kfree(rate_node->name);
2105 kfree(rate_node);
2106 return err;
2107 }
2108
2109 struct devlink_linecard_type {
2110 const char *type;
2111 const void *priv;
2112 };
2113
devlink_nl_linecard_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_linecard * linecard,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)2114 static int devlink_nl_linecard_fill(struct sk_buff *msg,
2115 struct devlink *devlink,
2116 struct devlink_linecard *linecard,
2117 enum devlink_command cmd, u32 portid,
2118 u32 seq, int flags,
2119 struct netlink_ext_ack *extack)
2120 {
2121 struct devlink_linecard_type *linecard_type;
2122 struct nlattr *attr;
2123 void *hdr;
2124 int i;
2125
2126 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2127 if (!hdr)
2128 return -EMSGSIZE;
2129
2130 if (devlink_nl_put_handle(msg, devlink))
2131 goto nla_put_failure;
2132 if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index))
2133 goto nla_put_failure;
2134 if (nla_put_u8(msg, DEVLINK_ATTR_LINECARD_STATE, linecard->state))
2135 goto nla_put_failure;
2136 if (linecard->type &&
2137 nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, linecard->type))
2138 goto nla_put_failure;
2139
2140 if (linecard->types_count) {
2141 attr = nla_nest_start(msg,
2142 DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES);
2143 if (!attr)
2144 goto nla_put_failure;
2145 for (i = 0; i < linecard->types_count; i++) {
2146 linecard_type = &linecard->types[i];
2147 if (nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE,
2148 linecard_type->type)) {
2149 nla_nest_cancel(msg, attr);
2150 goto nla_put_failure;
2151 }
2152 }
2153 nla_nest_end(msg, attr);
2154 }
2155
2156 if (linecard->nested_devlink &&
2157 devlink_nl_put_nested_handle(msg, linecard->nested_devlink))
2158 goto nla_put_failure;
2159
2160 genlmsg_end(msg, hdr);
2161 return 0;
2162
2163 nla_put_failure:
2164 genlmsg_cancel(msg, hdr);
2165 return -EMSGSIZE;
2166 }
2167
devlink_linecard_notify(struct devlink_linecard * linecard,enum devlink_command cmd)2168 static void devlink_linecard_notify(struct devlink_linecard *linecard,
2169 enum devlink_command cmd)
2170 {
2171 struct devlink *devlink = linecard->devlink;
2172 struct sk_buff *msg;
2173 int err;
2174
2175 WARN_ON(cmd != DEVLINK_CMD_LINECARD_NEW &&
2176 cmd != DEVLINK_CMD_LINECARD_DEL);
2177
2178 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
2179 return;
2180
2181 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2182 if (!msg)
2183 return;
2184
2185 err = devlink_nl_linecard_fill(msg, devlink, linecard, cmd, 0, 0, 0,
2186 NULL);
2187 if (err) {
2188 nlmsg_free(msg);
2189 return;
2190 }
2191
2192 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2193 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2194 }
2195
devlink_nl_cmd_linecard_get_doit(struct sk_buff * skb,struct genl_info * info)2196 static int devlink_nl_cmd_linecard_get_doit(struct sk_buff *skb,
2197 struct genl_info *info)
2198 {
2199 struct devlink_linecard *linecard = info->user_ptr[1];
2200 struct devlink *devlink = linecard->devlink;
2201 struct sk_buff *msg;
2202 int err;
2203
2204 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2205 if (!msg)
2206 return -ENOMEM;
2207
2208 mutex_lock(&linecard->state_lock);
2209 err = devlink_nl_linecard_fill(msg, devlink, linecard,
2210 DEVLINK_CMD_LINECARD_NEW,
2211 info->snd_portid, info->snd_seq, 0,
2212 info->extack);
2213 mutex_unlock(&linecard->state_lock);
2214 if (err) {
2215 nlmsg_free(msg);
2216 return err;
2217 }
2218
2219 return genlmsg_reply(msg, info);
2220 }
2221
devlink_nl_cmd_linecard_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)2222 static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg,
2223 struct netlink_callback *cb)
2224 {
2225 struct devlink_linecard *linecard;
2226 struct devlink *devlink;
2227 int start = cb->args[0];
2228 unsigned long index;
2229 int idx = 0;
2230 int err;
2231
2232 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
2233 mutex_lock(&devlink->linecards_lock);
2234 list_for_each_entry(linecard, &devlink->linecard_list, list) {
2235 if (idx < start) {
2236 idx++;
2237 continue;
2238 }
2239 mutex_lock(&linecard->state_lock);
2240 err = devlink_nl_linecard_fill(msg, devlink, linecard,
2241 DEVLINK_CMD_LINECARD_NEW,
2242 NETLINK_CB(cb->skb).portid,
2243 cb->nlh->nlmsg_seq,
2244 NLM_F_MULTI,
2245 cb->extack);
2246 mutex_unlock(&linecard->state_lock);
2247 if (err) {
2248 mutex_unlock(&devlink->linecards_lock);
2249 devlink_put(devlink);
2250 goto out;
2251 }
2252 idx++;
2253 }
2254 mutex_unlock(&devlink->linecards_lock);
2255 devlink_put(devlink);
2256 }
2257 out:
2258 cb->args[0] = idx;
2259 return msg->len;
2260 }
2261
2262 static struct devlink_linecard_type *
devlink_linecard_type_lookup(struct devlink_linecard * linecard,const char * type)2263 devlink_linecard_type_lookup(struct devlink_linecard *linecard,
2264 const char *type)
2265 {
2266 struct devlink_linecard_type *linecard_type;
2267 int i;
2268
2269 for (i = 0; i < linecard->types_count; i++) {
2270 linecard_type = &linecard->types[i];
2271 if (!strcmp(type, linecard_type->type))
2272 return linecard_type;
2273 }
2274 return NULL;
2275 }
2276
devlink_linecard_type_set(struct devlink_linecard * linecard,const char * type,struct netlink_ext_ack * extack)2277 static int devlink_linecard_type_set(struct devlink_linecard *linecard,
2278 const char *type,
2279 struct netlink_ext_ack *extack)
2280 {
2281 const struct devlink_linecard_ops *ops = linecard->ops;
2282 struct devlink_linecard_type *linecard_type;
2283 int err;
2284
2285 mutex_lock(&linecard->state_lock);
2286 if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) {
2287 NL_SET_ERR_MSG_MOD(extack, "Line card is currently being provisioned");
2288 err = -EBUSY;
2289 goto out;
2290 }
2291 if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) {
2292 NL_SET_ERR_MSG_MOD(extack, "Line card is currently being unprovisioned");
2293 err = -EBUSY;
2294 goto out;
2295 }
2296
2297 linecard_type = devlink_linecard_type_lookup(linecard, type);
2298 if (!linecard_type) {
2299 NL_SET_ERR_MSG_MOD(extack, "Unsupported line card type provided");
2300 err = -EINVAL;
2301 goto out;
2302 }
2303
2304 if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONED &&
2305 linecard->state != DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) {
2306 NL_SET_ERR_MSG_MOD(extack, "Line card already provisioned");
2307 err = -EBUSY;
2308 /* Check if the line card is provisioned in the same
2309 * way the user asks. In case it is, make the operation
2310 * to return success.
2311 */
2312 if (ops->same_provision &&
2313 ops->same_provision(linecard, linecard->priv,
2314 linecard_type->type,
2315 linecard_type->priv))
2316 err = 0;
2317 goto out;
2318 }
2319
2320 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING;
2321 linecard->type = linecard_type->type;
2322 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
2323 mutex_unlock(&linecard->state_lock);
2324 err = ops->provision(linecard, linecard->priv, linecard_type->type,
2325 linecard_type->priv, extack);
2326 if (err) {
2327 /* Provisioning failed. Assume the linecard is unprovisioned
2328 * for future operations.
2329 */
2330 mutex_lock(&linecard->state_lock);
2331 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
2332 linecard->type = NULL;
2333 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
2334 mutex_unlock(&linecard->state_lock);
2335 }
2336 return err;
2337
2338 out:
2339 mutex_unlock(&linecard->state_lock);
2340 return err;
2341 }
2342
devlink_linecard_type_unset(struct devlink_linecard * linecard,struct netlink_ext_ack * extack)2343 static int devlink_linecard_type_unset(struct devlink_linecard *linecard,
2344 struct netlink_ext_ack *extack)
2345 {
2346 int err;
2347
2348 mutex_lock(&linecard->state_lock);
2349 if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) {
2350 NL_SET_ERR_MSG_MOD(extack, "Line card is currently being provisioned");
2351 err = -EBUSY;
2352 goto out;
2353 }
2354 if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) {
2355 NL_SET_ERR_MSG_MOD(extack, "Line card is currently being unprovisioned");
2356 err = -EBUSY;
2357 goto out;
2358 }
2359 if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) {
2360 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
2361 linecard->type = NULL;
2362 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
2363 err = 0;
2364 goto out;
2365 }
2366
2367 if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONED) {
2368 NL_SET_ERR_MSG_MOD(extack, "Line card is not provisioned");
2369 err = 0;
2370 goto out;
2371 }
2372 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONING;
2373 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
2374 mutex_unlock(&linecard->state_lock);
2375 err = linecard->ops->unprovision(linecard, linecard->priv,
2376 extack);
2377 if (err) {
2378 /* Unprovisioning failed. Assume the linecard is unprovisioned
2379 * for future operations.
2380 */
2381 mutex_lock(&linecard->state_lock);
2382 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
2383 linecard->type = NULL;
2384 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
2385 mutex_unlock(&linecard->state_lock);
2386 }
2387 return err;
2388
2389 out:
2390 mutex_unlock(&linecard->state_lock);
2391 return err;
2392 }
2393
devlink_nl_cmd_linecard_set_doit(struct sk_buff * skb,struct genl_info * info)2394 static int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb,
2395 struct genl_info *info)
2396 {
2397 struct devlink_linecard *linecard = info->user_ptr[1];
2398 struct netlink_ext_ack *extack = info->extack;
2399 int err;
2400
2401 if (info->attrs[DEVLINK_ATTR_LINECARD_TYPE]) {
2402 const char *type;
2403
2404 type = nla_data(info->attrs[DEVLINK_ATTR_LINECARD_TYPE]);
2405 if (strcmp(type, "")) {
2406 err = devlink_linecard_type_set(linecard, type, extack);
2407 if (err)
2408 return err;
2409 } else {
2410 err = devlink_linecard_type_unset(linecard, extack);
2411 if (err)
2412 return err;
2413 }
2414 }
2415
2416 return 0;
2417 }
2418
devlink_nl_sb_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,enum devlink_command cmd,u32 portid,u32 seq,int flags)2419 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
2420 struct devlink_sb *devlink_sb,
2421 enum devlink_command cmd, u32 portid,
2422 u32 seq, int flags)
2423 {
2424 void *hdr;
2425
2426 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2427 if (!hdr)
2428 return -EMSGSIZE;
2429
2430 if (devlink_nl_put_handle(msg, devlink))
2431 goto nla_put_failure;
2432 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
2433 goto nla_put_failure;
2434 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
2435 goto nla_put_failure;
2436 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
2437 devlink_sb->ingress_pools_count))
2438 goto nla_put_failure;
2439 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
2440 devlink_sb->egress_pools_count))
2441 goto nla_put_failure;
2442 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
2443 devlink_sb->ingress_tc_count))
2444 goto nla_put_failure;
2445 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
2446 devlink_sb->egress_tc_count))
2447 goto nla_put_failure;
2448
2449 genlmsg_end(msg, hdr);
2450 return 0;
2451
2452 nla_put_failure:
2453 genlmsg_cancel(msg, hdr);
2454 return -EMSGSIZE;
2455 }
2456
devlink_nl_cmd_sb_get_doit(struct sk_buff * skb,struct genl_info * info)2457 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
2458 struct genl_info *info)
2459 {
2460 struct devlink *devlink = info->user_ptr[0];
2461 struct devlink_sb *devlink_sb;
2462 struct sk_buff *msg;
2463 int err;
2464
2465 devlink_sb = devlink_sb_get_from_info(devlink, info);
2466 if (IS_ERR(devlink_sb))
2467 return PTR_ERR(devlink_sb);
2468
2469 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2470 if (!msg)
2471 return -ENOMEM;
2472
2473 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
2474 DEVLINK_CMD_SB_NEW,
2475 info->snd_portid, info->snd_seq, 0);
2476 if (err) {
2477 nlmsg_free(msg);
2478 return err;
2479 }
2480
2481 return genlmsg_reply(msg, info);
2482 }
2483
devlink_nl_cmd_sb_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)2484 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
2485 struct netlink_callback *cb)
2486 {
2487 struct devlink *devlink;
2488 struct devlink_sb *devlink_sb;
2489 int start = cb->args[0];
2490 unsigned long index;
2491 int idx = 0;
2492 int err;
2493
2494 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
2495 devl_lock(devlink);
2496 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
2497 if (idx < start) {
2498 idx++;
2499 continue;
2500 }
2501 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
2502 DEVLINK_CMD_SB_NEW,
2503 NETLINK_CB(cb->skb).portid,
2504 cb->nlh->nlmsg_seq,
2505 NLM_F_MULTI);
2506 if (err) {
2507 devl_unlock(devlink);
2508 devlink_put(devlink);
2509 goto out;
2510 }
2511 idx++;
2512 }
2513 devl_unlock(devlink);
2514 devlink_put(devlink);
2515 }
2516 out:
2517 cb->args[0] = idx;
2518 return msg->len;
2519 }
2520
devlink_nl_sb_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)2521 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
2522 struct devlink_sb *devlink_sb,
2523 u16 pool_index, enum devlink_command cmd,
2524 u32 portid, u32 seq, int flags)
2525 {
2526 struct devlink_sb_pool_info pool_info;
2527 void *hdr;
2528 int err;
2529
2530 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
2531 pool_index, &pool_info);
2532 if (err)
2533 return err;
2534
2535 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2536 if (!hdr)
2537 return -EMSGSIZE;
2538
2539 if (devlink_nl_put_handle(msg, devlink))
2540 goto nla_put_failure;
2541 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
2542 goto nla_put_failure;
2543 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
2544 goto nla_put_failure;
2545 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
2546 goto nla_put_failure;
2547 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
2548 goto nla_put_failure;
2549 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
2550 pool_info.threshold_type))
2551 goto nla_put_failure;
2552 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
2553 pool_info.cell_size))
2554 goto nla_put_failure;
2555
2556 genlmsg_end(msg, hdr);
2557 return 0;
2558
2559 nla_put_failure:
2560 genlmsg_cancel(msg, hdr);
2561 return -EMSGSIZE;
2562 }
2563
devlink_nl_cmd_sb_pool_get_doit(struct sk_buff * skb,struct genl_info * info)2564 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
2565 struct genl_info *info)
2566 {
2567 struct devlink *devlink = info->user_ptr[0];
2568 struct devlink_sb *devlink_sb;
2569 struct sk_buff *msg;
2570 u16 pool_index;
2571 int err;
2572
2573 devlink_sb = devlink_sb_get_from_info(devlink, info);
2574 if (IS_ERR(devlink_sb))
2575 return PTR_ERR(devlink_sb);
2576
2577 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
2578 &pool_index);
2579 if (err)
2580 return err;
2581
2582 if (!devlink->ops->sb_pool_get)
2583 return -EOPNOTSUPP;
2584
2585 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2586 if (!msg)
2587 return -ENOMEM;
2588
2589 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
2590 DEVLINK_CMD_SB_POOL_NEW,
2591 info->snd_portid, info->snd_seq, 0);
2592 if (err) {
2593 nlmsg_free(msg);
2594 return err;
2595 }
2596
2597 return genlmsg_reply(msg, info);
2598 }
2599
__sb_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)2600 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
2601 struct devlink *devlink,
2602 struct devlink_sb *devlink_sb,
2603 u32 portid, u32 seq)
2604 {
2605 u16 pool_count = devlink_sb_pool_count(devlink_sb);
2606 u16 pool_index;
2607 int err;
2608
2609 for (pool_index = 0; pool_index < pool_count; pool_index++) {
2610 if (*p_idx < start) {
2611 (*p_idx)++;
2612 continue;
2613 }
2614 err = devlink_nl_sb_pool_fill(msg, devlink,
2615 devlink_sb,
2616 pool_index,
2617 DEVLINK_CMD_SB_POOL_NEW,
2618 portid, seq, NLM_F_MULTI);
2619 if (err)
2620 return err;
2621 (*p_idx)++;
2622 }
2623 return 0;
2624 }
2625
devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)2626 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
2627 struct netlink_callback *cb)
2628 {
2629 struct devlink *devlink;
2630 struct devlink_sb *devlink_sb;
2631 int start = cb->args[0];
2632 unsigned long index;
2633 int idx = 0;
2634 int err = 0;
2635
2636 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
2637 if (!devlink->ops->sb_pool_get)
2638 goto retry;
2639
2640 devl_lock(devlink);
2641 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
2642 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
2643 devlink_sb,
2644 NETLINK_CB(cb->skb).portid,
2645 cb->nlh->nlmsg_seq);
2646 if (err == -EOPNOTSUPP) {
2647 err = 0;
2648 } else if (err) {
2649 devl_unlock(devlink);
2650 devlink_put(devlink);
2651 goto out;
2652 }
2653 }
2654 devl_unlock(devlink);
2655 retry:
2656 devlink_put(devlink);
2657 }
2658 out:
2659 if (err != -EMSGSIZE)
2660 return err;
2661
2662 cb->args[0] = idx;
2663 return msg->len;
2664 }
2665
devlink_sb_pool_set(struct devlink * devlink,unsigned int sb_index,u16 pool_index,u32 size,enum devlink_sb_threshold_type threshold_type,struct netlink_ext_ack * extack)2666 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
2667 u16 pool_index, u32 size,
2668 enum devlink_sb_threshold_type threshold_type,
2669 struct netlink_ext_ack *extack)
2670
2671 {
2672 const struct devlink_ops *ops = devlink->ops;
2673
2674 if (ops->sb_pool_set)
2675 return ops->sb_pool_set(devlink, sb_index, pool_index,
2676 size, threshold_type, extack);
2677 return -EOPNOTSUPP;
2678 }
2679
devlink_nl_cmd_sb_pool_set_doit(struct sk_buff * skb,struct genl_info * info)2680 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
2681 struct genl_info *info)
2682 {
2683 struct devlink *devlink = info->user_ptr[0];
2684 enum devlink_sb_threshold_type threshold_type;
2685 struct devlink_sb *devlink_sb;
2686 u16 pool_index;
2687 u32 size;
2688 int err;
2689
2690 devlink_sb = devlink_sb_get_from_info(devlink, info);
2691 if (IS_ERR(devlink_sb))
2692 return PTR_ERR(devlink_sb);
2693
2694 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
2695 &pool_index);
2696 if (err)
2697 return err;
2698
2699 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
2700 if (err)
2701 return err;
2702
2703 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE))
2704 return -EINVAL;
2705
2706 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
2707 return devlink_sb_pool_set(devlink, devlink_sb->index,
2708 pool_index, size, threshold_type,
2709 info->extack);
2710 }
2711
devlink_nl_sb_port_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)2712 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
2713 struct devlink *devlink,
2714 struct devlink_port *devlink_port,
2715 struct devlink_sb *devlink_sb,
2716 u16 pool_index,
2717 enum devlink_command cmd,
2718 u32 portid, u32 seq, int flags)
2719 {
2720 const struct devlink_ops *ops = devlink->ops;
2721 u32 threshold;
2722 void *hdr;
2723 int err;
2724
2725 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
2726 pool_index, &threshold);
2727 if (err)
2728 return err;
2729
2730 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2731 if (!hdr)
2732 return -EMSGSIZE;
2733
2734 if (devlink_nl_put_handle(msg, devlink))
2735 goto nla_put_failure;
2736 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
2737 goto nla_put_failure;
2738 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
2739 goto nla_put_failure;
2740 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
2741 goto nla_put_failure;
2742 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
2743 goto nla_put_failure;
2744
2745 if (ops->sb_occ_port_pool_get) {
2746 u32 cur;
2747 u32 max;
2748
2749 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
2750 pool_index, &cur, &max);
2751 if (err && err != -EOPNOTSUPP)
2752 goto sb_occ_get_failure;
2753 if (!err) {
2754 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
2755 goto nla_put_failure;
2756 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
2757 goto nla_put_failure;
2758 }
2759 }
2760
2761 genlmsg_end(msg, hdr);
2762 return 0;
2763
2764 nla_put_failure:
2765 err = -EMSGSIZE;
2766 sb_occ_get_failure:
2767 genlmsg_cancel(msg, hdr);
2768 return err;
2769 }
2770
devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff * skb,struct genl_info * info)2771 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
2772 struct genl_info *info)
2773 {
2774 struct devlink_port *devlink_port = info->user_ptr[1];
2775 struct devlink *devlink = devlink_port->devlink;
2776 struct devlink_sb *devlink_sb;
2777 struct sk_buff *msg;
2778 u16 pool_index;
2779 int err;
2780
2781 devlink_sb = devlink_sb_get_from_info(devlink, info);
2782 if (IS_ERR(devlink_sb))
2783 return PTR_ERR(devlink_sb);
2784
2785 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
2786 &pool_index);
2787 if (err)
2788 return err;
2789
2790 if (!devlink->ops->sb_port_pool_get)
2791 return -EOPNOTSUPP;
2792
2793 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2794 if (!msg)
2795 return -ENOMEM;
2796
2797 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
2798 devlink_sb, pool_index,
2799 DEVLINK_CMD_SB_PORT_POOL_NEW,
2800 info->snd_portid, info->snd_seq, 0);
2801 if (err) {
2802 nlmsg_free(msg);
2803 return err;
2804 }
2805
2806 return genlmsg_reply(msg, info);
2807 }
2808
__sb_port_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)2809 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
2810 struct devlink *devlink,
2811 struct devlink_sb *devlink_sb,
2812 u32 portid, u32 seq)
2813 {
2814 struct devlink_port *devlink_port;
2815 u16 pool_count = devlink_sb_pool_count(devlink_sb);
2816 u16 pool_index;
2817 int err;
2818
2819 list_for_each_entry(devlink_port, &devlink->port_list, list) {
2820 for (pool_index = 0; pool_index < pool_count; pool_index++) {
2821 if (*p_idx < start) {
2822 (*p_idx)++;
2823 continue;
2824 }
2825 err = devlink_nl_sb_port_pool_fill(msg, devlink,
2826 devlink_port,
2827 devlink_sb,
2828 pool_index,
2829 DEVLINK_CMD_SB_PORT_POOL_NEW,
2830 portid, seq,
2831 NLM_F_MULTI);
2832 if (err)
2833 return err;
2834 (*p_idx)++;
2835 }
2836 }
2837 return 0;
2838 }
2839
devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)2840 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
2841 struct netlink_callback *cb)
2842 {
2843 struct devlink *devlink;
2844 struct devlink_sb *devlink_sb;
2845 int start = cb->args[0];
2846 unsigned long index;
2847 int idx = 0;
2848 int err = 0;
2849
2850 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
2851 if (!devlink->ops->sb_port_pool_get)
2852 goto retry;
2853
2854 devl_lock(devlink);
2855 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
2856 err = __sb_port_pool_get_dumpit(msg, start, &idx,
2857 devlink, devlink_sb,
2858 NETLINK_CB(cb->skb).portid,
2859 cb->nlh->nlmsg_seq);
2860 if (err == -EOPNOTSUPP) {
2861 err = 0;
2862 } else if (err) {
2863 devl_unlock(devlink);
2864 devlink_put(devlink);
2865 goto out;
2866 }
2867 }
2868 devl_unlock(devlink);
2869 retry:
2870 devlink_put(devlink);
2871 }
2872 out:
2873 if (err != -EMSGSIZE)
2874 return err;
2875
2876 cb->args[0] = idx;
2877 return msg->len;
2878 }
2879
devlink_sb_port_pool_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)2880 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
2881 unsigned int sb_index, u16 pool_index,
2882 u32 threshold,
2883 struct netlink_ext_ack *extack)
2884
2885 {
2886 const struct devlink_ops *ops = devlink_port->devlink->ops;
2887
2888 if (ops->sb_port_pool_set)
2889 return ops->sb_port_pool_set(devlink_port, sb_index,
2890 pool_index, threshold, extack);
2891 return -EOPNOTSUPP;
2892 }
2893
devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff * skb,struct genl_info * info)2894 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
2895 struct genl_info *info)
2896 {
2897 struct devlink_port *devlink_port = info->user_ptr[1];
2898 struct devlink *devlink = info->user_ptr[0];
2899 struct devlink_sb *devlink_sb;
2900 u16 pool_index;
2901 u32 threshold;
2902 int err;
2903
2904 devlink_sb = devlink_sb_get_from_info(devlink, info);
2905 if (IS_ERR(devlink_sb))
2906 return PTR_ERR(devlink_sb);
2907
2908 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
2909 &pool_index);
2910 if (err)
2911 return err;
2912
2913 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
2914 return -EINVAL;
2915
2916 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
2917 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
2918 pool_index, threshold, info->extack);
2919 }
2920
2921 static int
devlink_nl_sb_tc_pool_bind_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 tc_index,enum devlink_sb_pool_type pool_type,enum devlink_command cmd,u32 portid,u32 seq,int flags)2922 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
2923 struct devlink_port *devlink_port,
2924 struct devlink_sb *devlink_sb, u16 tc_index,
2925 enum devlink_sb_pool_type pool_type,
2926 enum devlink_command cmd,
2927 u32 portid, u32 seq, int flags)
2928 {
2929 const struct devlink_ops *ops = devlink->ops;
2930 u16 pool_index;
2931 u32 threshold;
2932 void *hdr;
2933 int err;
2934
2935 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
2936 tc_index, pool_type,
2937 &pool_index, &threshold);
2938 if (err)
2939 return err;
2940
2941 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2942 if (!hdr)
2943 return -EMSGSIZE;
2944
2945 if (devlink_nl_put_handle(msg, devlink))
2946 goto nla_put_failure;
2947 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
2948 goto nla_put_failure;
2949 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
2950 goto nla_put_failure;
2951 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
2952 goto nla_put_failure;
2953 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
2954 goto nla_put_failure;
2955 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
2956 goto nla_put_failure;
2957 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
2958 goto nla_put_failure;
2959
2960 if (ops->sb_occ_tc_port_bind_get) {
2961 u32 cur;
2962 u32 max;
2963
2964 err = ops->sb_occ_tc_port_bind_get(devlink_port,
2965 devlink_sb->index,
2966 tc_index, pool_type,
2967 &cur, &max);
2968 if (err && err != -EOPNOTSUPP)
2969 return err;
2970 if (!err) {
2971 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
2972 goto nla_put_failure;
2973 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
2974 goto nla_put_failure;
2975 }
2976 }
2977
2978 genlmsg_end(msg, hdr);
2979 return 0;
2980
2981 nla_put_failure:
2982 genlmsg_cancel(msg, hdr);
2983 return -EMSGSIZE;
2984 }
2985
devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff * skb,struct genl_info * info)2986 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
2987 struct genl_info *info)
2988 {
2989 struct devlink_port *devlink_port = info->user_ptr[1];
2990 struct devlink *devlink = devlink_port->devlink;
2991 struct devlink_sb *devlink_sb;
2992 struct sk_buff *msg;
2993 enum devlink_sb_pool_type pool_type;
2994 u16 tc_index;
2995 int err;
2996
2997 devlink_sb = devlink_sb_get_from_info(devlink, info);
2998 if (IS_ERR(devlink_sb))
2999 return PTR_ERR(devlink_sb);
3000
3001 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
3002 if (err)
3003 return err;
3004
3005 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
3006 pool_type, &tc_index);
3007 if (err)
3008 return err;
3009
3010 if (!devlink->ops->sb_tc_pool_bind_get)
3011 return -EOPNOTSUPP;
3012
3013 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3014 if (!msg)
3015 return -ENOMEM;
3016
3017 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
3018 devlink_sb, tc_index, pool_type,
3019 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
3020 info->snd_portid,
3021 info->snd_seq, 0);
3022 if (err) {
3023 nlmsg_free(msg);
3024 return err;
3025 }
3026
3027 return genlmsg_reply(msg, info);
3028 }
3029
__sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)3030 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
3031 int start, int *p_idx,
3032 struct devlink *devlink,
3033 struct devlink_sb *devlink_sb,
3034 u32 portid, u32 seq)
3035 {
3036 struct devlink_port *devlink_port;
3037 u16 tc_index;
3038 int err;
3039
3040 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3041 for (tc_index = 0;
3042 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
3043 if (*p_idx < start) {
3044 (*p_idx)++;
3045 continue;
3046 }
3047 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
3048 devlink_port,
3049 devlink_sb,
3050 tc_index,
3051 DEVLINK_SB_POOL_TYPE_INGRESS,
3052 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
3053 portid, seq,
3054 NLM_F_MULTI);
3055 if (err)
3056 return err;
3057 (*p_idx)++;
3058 }
3059 for (tc_index = 0;
3060 tc_index < devlink_sb->egress_tc_count; tc_index++) {
3061 if (*p_idx < start) {
3062 (*p_idx)++;
3063 continue;
3064 }
3065 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
3066 devlink_port,
3067 devlink_sb,
3068 tc_index,
3069 DEVLINK_SB_POOL_TYPE_EGRESS,
3070 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
3071 portid, seq,
3072 NLM_F_MULTI);
3073 if (err)
3074 return err;
3075 (*p_idx)++;
3076 }
3077 }
3078 return 0;
3079 }
3080
3081 static int
devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)3082 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
3083 struct netlink_callback *cb)
3084 {
3085 struct devlink *devlink;
3086 struct devlink_sb *devlink_sb;
3087 int start = cb->args[0];
3088 unsigned long index;
3089 int idx = 0;
3090 int err = 0;
3091
3092 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
3093 if (!devlink->ops->sb_tc_pool_bind_get)
3094 goto retry;
3095
3096 devl_lock(devlink);
3097 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
3098 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
3099 devlink,
3100 devlink_sb,
3101 NETLINK_CB(cb->skb).portid,
3102 cb->nlh->nlmsg_seq);
3103 if (err == -EOPNOTSUPP) {
3104 err = 0;
3105 } else if (err) {
3106 devl_unlock(devlink);
3107 devlink_put(devlink);
3108 goto out;
3109 }
3110 }
3111 devl_unlock(devlink);
3112 retry:
3113 devlink_put(devlink);
3114 }
3115 out:
3116 if (err != -EMSGSIZE)
3117 return err;
3118
3119 cb->args[0] = idx;
3120 return msg->len;
3121 }
3122
devlink_sb_tc_pool_bind_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 tc_index,enum devlink_sb_pool_type pool_type,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)3123 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
3124 unsigned int sb_index, u16 tc_index,
3125 enum devlink_sb_pool_type pool_type,
3126 u16 pool_index, u32 threshold,
3127 struct netlink_ext_ack *extack)
3128
3129 {
3130 const struct devlink_ops *ops = devlink_port->devlink->ops;
3131
3132 if (ops->sb_tc_pool_bind_set)
3133 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
3134 tc_index, pool_type,
3135 pool_index, threshold, extack);
3136 return -EOPNOTSUPP;
3137 }
3138
devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff * skb,struct genl_info * info)3139 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
3140 struct genl_info *info)
3141 {
3142 struct devlink_port *devlink_port = info->user_ptr[1];
3143 struct devlink *devlink = info->user_ptr[0];
3144 enum devlink_sb_pool_type pool_type;
3145 struct devlink_sb *devlink_sb;
3146 u16 tc_index;
3147 u16 pool_index;
3148 u32 threshold;
3149 int err;
3150
3151 devlink_sb = devlink_sb_get_from_info(devlink, info);
3152 if (IS_ERR(devlink_sb))
3153 return PTR_ERR(devlink_sb);
3154
3155 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
3156 if (err)
3157 return err;
3158
3159 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
3160 pool_type, &tc_index);
3161 if (err)
3162 return err;
3163
3164 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
3165 &pool_index);
3166 if (err)
3167 return err;
3168
3169 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
3170 return -EINVAL;
3171
3172 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
3173 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
3174 tc_index, pool_type,
3175 pool_index, threshold, info->extack);
3176 }
3177
devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff * skb,struct genl_info * info)3178 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
3179 struct genl_info *info)
3180 {
3181 struct devlink *devlink = info->user_ptr[0];
3182 const struct devlink_ops *ops = devlink->ops;
3183 struct devlink_sb *devlink_sb;
3184
3185 devlink_sb = devlink_sb_get_from_info(devlink, info);
3186 if (IS_ERR(devlink_sb))
3187 return PTR_ERR(devlink_sb);
3188
3189 if (ops->sb_occ_snapshot)
3190 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
3191 return -EOPNOTSUPP;
3192 }
3193
devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff * skb,struct genl_info * info)3194 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
3195 struct genl_info *info)
3196 {
3197 struct devlink *devlink = info->user_ptr[0];
3198 const struct devlink_ops *ops = devlink->ops;
3199 struct devlink_sb *devlink_sb;
3200
3201 devlink_sb = devlink_sb_get_from_info(devlink, info);
3202 if (IS_ERR(devlink_sb))
3203 return PTR_ERR(devlink_sb);
3204
3205 if (ops->sb_occ_max_clear)
3206 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
3207 return -EOPNOTSUPP;
3208 }
3209
devlink_nl_eswitch_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)3210 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
3211 enum devlink_command cmd, u32 portid,
3212 u32 seq, int flags)
3213 {
3214 const struct devlink_ops *ops = devlink->ops;
3215 enum devlink_eswitch_encap_mode encap_mode;
3216 u8 inline_mode;
3217 void *hdr;
3218 int err = 0;
3219 u16 mode;
3220
3221 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3222 if (!hdr)
3223 return -EMSGSIZE;
3224
3225 err = devlink_nl_put_handle(msg, devlink);
3226 if (err)
3227 goto nla_put_failure;
3228
3229 if (ops->eswitch_mode_get) {
3230 err = ops->eswitch_mode_get(devlink, &mode);
3231 if (err)
3232 goto nla_put_failure;
3233 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
3234 if (err)
3235 goto nla_put_failure;
3236 }
3237
3238 if (ops->eswitch_inline_mode_get) {
3239 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
3240 if (err)
3241 goto nla_put_failure;
3242 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
3243 inline_mode);
3244 if (err)
3245 goto nla_put_failure;
3246 }
3247
3248 if (ops->eswitch_encap_mode_get) {
3249 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
3250 if (err)
3251 goto nla_put_failure;
3252 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
3253 if (err)
3254 goto nla_put_failure;
3255 }
3256
3257 genlmsg_end(msg, hdr);
3258 return 0;
3259
3260 nla_put_failure:
3261 genlmsg_cancel(msg, hdr);
3262 return err;
3263 }
3264
devlink_nl_cmd_eswitch_get_doit(struct sk_buff * skb,struct genl_info * info)3265 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
3266 struct genl_info *info)
3267 {
3268 struct devlink *devlink = info->user_ptr[0];
3269 struct sk_buff *msg;
3270 int err;
3271
3272 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3273 if (!msg)
3274 return -ENOMEM;
3275
3276 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
3277 info->snd_portid, info->snd_seq, 0);
3278
3279 if (err) {
3280 nlmsg_free(msg);
3281 return err;
3282 }
3283
3284 return genlmsg_reply(msg, info);
3285 }
3286
devlink_rate_nodes_check(struct devlink * devlink,u16 mode,struct netlink_ext_ack * extack)3287 static int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
3288 struct netlink_ext_ack *extack)
3289 {
3290 struct devlink_rate *devlink_rate;
3291
3292 list_for_each_entry(devlink_rate, &devlink->rate_list, list)
3293 if (devlink_rate_is_node(devlink_rate)) {
3294 NL_SET_ERR_MSG_MOD(extack, "Rate node(s) exists.");
3295 return -EBUSY;
3296 }
3297 return 0;
3298 }
3299
devlink_nl_cmd_eswitch_set_doit(struct sk_buff * skb,struct genl_info * info)3300 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
3301 struct genl_info *info)
3302 {
3303 struct devlink *devlink = info->user_ptr[0];
3304 const struct devlink_ops *ops = devlink->ops;
3305 enum devlink_eswitch_encap_mode encap_mode;
3306 u8 inline_mode;
3307 int err = 0;
3308 u16 mode;
3309
3310 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
3311 if (!ops->eswitch_mode_set)
3312 return -EOPNOTSUPP;
3313 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
3314 err = devlink_rate_nodes_check(devlink, mode, info->extack);
3315 if (err)
3316 return err;
3317 err = ops->eswitch_mode_set(devlink, mode, info->extack);
3318 if (err)
3319 return err;
3320 }
3321
3322 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
3323 if (!ops->eswitch_inline_mode_set)
3324 return -EOPNOTSUPP;
3325 inline_mode = nla_get_u8(
3326 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
3327 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
3328 info->extack);
3329 if (err)
3330 return err;
3331 }
3332
3333 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
3334 if (!ops->eswitch_encap_mode_set)
3335 return -EOPNOTSUPP;
3336 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
3337 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
3338 info->extack);
3339 if (err)
3340 return err;
3341 }
3342
3343 return 0;
3344 }
3345
devlink_dpipe_match_put(struct sk_buff * skb,struct devlink_dpipe_match * match)3346 int devlink_dpipe_match_put(struct sk_buff *skb,
3347 struct devlink_dpipe_match *match)
3348 {
3349 struct devlink_dpipe_header *header = match->header;
3350 struct devlink_dpipe_field *field = &header->fields[match->field_id];
3351 struct nlattr *match_attr;
3352
3353 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
3354 if (!match_attr)
3355 return -EMSGSIZE;
3356
3357 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
3358 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
3359 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
3360 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
3361 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
3362 goto nla_put_failure;
3363
3364 nla_nest_end(skb, match_attr);
3365 return 0;
3366
3367 nla_put_failure:
3368 nla_nest_cancel(skb, match_attr);
3369 return -EMSGSIZE;
3370 }
3371 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
3372
devlink_dpipe_matches_put(struct devlink_dpipe_table * table,struct sk_buff * skb)3373 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
3374 struct sk_buff *skb)
3375 {
3376 struct nlattr *matches_attr;
3377
3378 matches_attr = nla_nest_start_noflag(skb,
3379 DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
3380 if (!matches_attr)
3381 return -EMSGSIZE;
3382
3383 if (table->table_ops->matches_dump(table->priv, skb))
3384 goto nla_put_failure;
3385
3386 nla_nest_end(skb, matches_attr);
3387 return 0;
3388
3389 nla_put_failure:
3390 nla_nest_cancel(skb, matches_attr);
3391 return -EMSGSIZE;
3392 }
3393
devlink_dpipe_action_put(struct sk_buff * skb,struct devlink_dpipe_action * action)3394 int devlink_dpipe_action_put(struct sk_buff *skb,
3395 struct devlink_dpipe_action *action)
3396 {
3397 struct devlink_dpipe_header *header = action->header;
3398 struct devlink_dpipe_field *field = &header->fields[action->field_id];
3399 struct nlattr *action_attr;
3400
3401 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
3402 if (!action_attr)
3403 return -EMSGSIZE;
3404
3405 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
3406 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
3407 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
3408 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
3409 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
3410 goto nla_put_failure;
3411
3412 nla_nest_end(skb, action_attr);
3413 return 0;
3414
3415 nla_put_failure:
3416 nla_nest_cancel(skb, action_attr);
3417 return -EMSGSIZE;
3418 }
3419 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
3420
devlink_dpipe_actions_put(struct devlink_dpipe_table * table,struct sk_buff * skb)3421 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
3422 struct sk_buff *skb)
3423 {
3424 struct nlattr *actions_attr;
3425
3426 actions_attr = nla_nest_start_noflag(skb,
3427 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
3428 if (!actions_attr)
3429 return -EMSGSIZE;
3430
3431 if (table->table_ops->actions_dump(table->priv, skb))
3432 goto nla_put_failure;
3433
3434 nla_nest_end(skb, actions_attr);
3435 return 0;
3436
3437 nla_put_failure:
3438 nla_nest_cancel(skb, actions_attr);
3439 return -EMSGSIZE;
3440 }
3441
devlink_dpipe_table_put(struct sk_buff * skb,struct devlink_dpipe_table * table)3442 static int devlink_dpipe_table_put(struct sk_buff *skb,
3443 struct devlink_dpipe_table *table)
3444 {
3445 struct nlattr *table_attr;
3446 u64 table_size;
3447
3448 table_size = table->table_ops->size_get(table->priv);
3449 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
3450 if (!table_attr)
3451 return -EMSGSIZE;
3452
3453 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
3454 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
3455 DEVLINK_ATTR_PAD))
3456 goto nla_put_failure;
3457 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
3458 table->counters_enabled))
3459 goto nla_put_failure;
3460
3461 if (table->resource_valid) {
3462 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
3463 table->resource_id, DEVLINK_ATTR_PAD) ||
3464 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
3465 table->resource_units, DEVLINK_ATTR_PAD))
3466 goto nla_put_failure;
3467 }
3468 if (devlink_dpipe_matches_put(table, skb))
3469 goto nla_put_failure;
3470
3471 if (devlink_dpipe_actions_put(table, skb))
3472 goto nla_put_failure;
3473
3474 nla_nest_end(skb, table_attr);
3475 return 0;
3476
3477 nla_put_failure:
3478 nla_nest_cancel(skb, table_attr);
3479 return -EMSGSIZE;
3480 }
3481
devlink_dpipe_send_and_alloc_skb(struct sk_buff ** pskb,struct genl_info * info)3482 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
3483 struct genl_info *info)
3484 {
3485 int err;
3486
3487 if (*pskb) {
3488 err = genlmsg_reply(*pskb, info);
3489 if (err)
3490 return err;
3491 }
3492 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
3493 if (!*pskb)
3494 return -ENOMEM;
3495 return 0;
3496 }
3497
devlink_dpipe_tables_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct list_head * dpipe_tables,const char * table_name)3498 static int devlink_dpipe_tables_fill(struct genl_info *info,
3499 enum devlink_command cmd, int flags,
3500 struct list_head *dpipe_tables,
3501 const char *table_name)
3502 {
3503 struct devlink *devlink = info->user_ptr[0];
3504 struct devlink_dpipe_table *table;
3505 struct nlattr *tables_attr;
3506 struct sk_buff *skb = NULL;
3507 struct nlmsghdr *nlh;
3508 bool incomplete;
3509 void *hdr;
3510 int i;
3511 int err;
3512
3513 table = list_first_entry(dpipe_tables,
3514 struct devlink_dpipe_table, list);
3515 start_again:
3516 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
3517 if (err)
3518 return err;
3519
3520 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
3521 &devlink_nl_family, NLM_F_MULTI, cmd);
3522 if (!hdr) {
3523 nlmsg_free(skb);
3524 return -EMSGSIZE;
3525 }
3526
3527 if (devlink_nl_put_handle(skb, devlink))
3528 goto nla_put_failure;
3529 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
3530 if (!tables_attr)
3531 goto nla_put_failure;
3532
3533 i = 0;
3534 incomplete = false;
3535 list_for_each_entry_from(table, dpipe_tables, list) {
3536 if (!table_name) {
3537 err = devlink_dpipe_table_put(skb, table);
3538 if (err) {
3539 if (!i)
3540 goto err_table_put;
3541 incomplete = true;
3542 break;
3543 }
3544 } else {
3545 if (!strcmp(table->name, table_name)) {
3546 err = devlink_dpipe_table_put(skb, table);
3547 if (err)
3548 break;
3549 }
3550 }
3551 i++;
3552 }
3553
3554 nla_nest_end(skb, tables_attr);
3555 genlmsg_end(skb, hdr);
3556 if (incomplete)
3557 goto start_again;
3558
3559 send_done:
3560 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
3561 NLMSG_DONE, 0, flags | NLM_F_MULTI);
3562 if (!nlh) {
3563 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
3564 if (err)
3565 return err;
3566 goto send_done;
3567 }
3568
3569 return genlmsg_reply(skb, info);
3570
3571 nla_put_failure:
3572 err = -EMSGSIZE;
3573 err_table_put:
3574 nlmsg_free(skb);
3575 return err;
3576 }
3577
devlink_nl_cmd_dpipe_table_get(struct sk_buff * skb,struct genl_info * info)3578 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
3579 struct genl_info *info)
3580 {
3581 struct devlink *devlink = info->user_ptr[0];
3582 const char *table_name = NULL;
3583
3584 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
3585 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
3586
3587 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
3588 &devlink->dpipe_table_list,
3589 table_name);
3590 }
3591
devlink_dpipe_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)3592 static int devlink_dpipe_value_put(struct sk_buff *skb,
3593 struct devlink_dpipe_value *value)
3594 {
3595 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
3596 value->value_size, value->value))
3597 return -EMSGSIZE;
3598 if (value->mask)
3599 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
3600 value->value_size, value->mask))
3601 return -EMSGSIZE;
3602 if (value->mapping_valid)
3603 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
3604 value->mapping_value))
3605 return -EMSGSIZE;
3606 return 0;
3607 }
3608
devlink_dpipe_action_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)3609 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
3610 struct devlink_dpipe_value *value)
3611 {
3612 if (!value->action)
3613 return -EINVAL;
3614 if (devlink_dpipe_action_put(skb, value->action))
3615 return -EMSGSIZE;
3616 if (devlink_dpipe_value_put(skb, value))
3617 return -EMSGSIZE;
3618 return 0;
3619 }
3620
devlink_dpipe_action_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)3621 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
3622 struct devlink_dpipe_value *values,
3623 unsigned int values_count)
3624 {
3625 struct nlattr *action_attr;
3626 int i;
3627 int err;
3628
3629 for (i = 0; i < values_count; i++) {
3630 action_attr = nla_nest_start_noflag(skb,
3631 DEVLINK_ATTR_DPIPE_ACTION_VALUE);
3632 if (!action_attr)
3633 return -EMSGSIZE;
3634 err = devlink_dpipe_action_value_put(skb, &values[i]);
3635 if (err)
3636 goto err_action_value_put;
3637 nla_nest_end(skb, action_attr);
3638 }
3639 return 0;
3640
3641 err_action_value_put:
3642 nla_nest_cancel(skb, action_attr);
3643 return err;
3644 }
3645
devlink_dpipe_match_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)3646 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
3647 struct devlink_dpipe_value *value)
3648 {
3649 if (!value->match)
3650 return -EINVAL;
3651 if (devlink_dpipe_match_put(skb, value->match))
3652 return -EMSGSIZE;
3653 if (devlink_dpipe_value_put(skb, value))
3654 return -EMSGSIZE;
3655 return 0;
3656 }
3657
devlink_dpipe_match_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)3658 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
3659 struct devlink_dpipe_value *values,
3660 unsigned int values_count)
3661 {
3662 struct nlattr *match_attr;
3663 int i;
3664 int err;
3665
3666 for (i = 0; i < values_count; i++) {
3667 match_attr = nla_nest_start_noflag(skb,
3668 DEVLINK_ATTR_DPIPE_MATCH_VALUE);
3669 if (!match_attr)
3670 return -EMSGSIZE;
3671 err = devlink_dpipe_match_value_put(skb, &values[i]);
3672 if (err)
3673 goto err_match_value_put;
3674 nla_nest_end(skb, match_attr);
3675 }
3676 return 0;
3677
3678 err_match_value_put:
3679 nla_nest_cancel(skb, match_attr);
3680 return err;
3681 }
3682
devlink_dpipe_entry_put(struct sk_buff * skb,struct devlink_dpipe_entry * entry)3683 static int devlink_dpipe_entry_put(struct sk_buff *skb,
3684 struct devlink_dpipe_entry *entry)
3685 {
3686 struct nlattr *entry_attr, *matches_attr, *actions_attr;
3687 int err;
3688
3689 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
3690 if (!entry_attr)
3691 return -EMSGSIZE;
3692
3693 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
3694 DEVLINK_ATTR_PAD))
3695 goto nla_put_failure;
3696 if (entry->counter_valid)
3697 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
3698 entry->counter, DEVLINK_ATTR_PAD))
3699 goto nla_put_failure;
3700
3701 matches_attr = nla_nest_start_noflag(skb,
3702 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
3703 if (!matches_attr)
3704 goto nla_put_failure;
3705
3706 err = devlink_dpipe_match_values_put(skb, entry->match_values,
3707 entry->match_values_count);
3708 if (err) {
3709 nla_nest_cancel(skb, matches_attr);
3710 goto err_match_values_put;
3711 }
3712 nla_nest_end(skb, matches_attr);
3713
3714 actions_attr = nla_nest_start_noflag(skb,
3715 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
3716 if (!actions_attr)
3717 goto nla_put_failure;
3718
3719 err = devlink_dpipe_action_values_put(skb, entry->action_values,
3720 entry->action_values_count);
3721 if (err) {
3722 nla_nest_cancel(skb, actions_attr);
3723 goto err_action_values_put;
3724 }
3725 nla_nest_end(skb, actions_attr);
3726
3727 nla_nest_end(skb, entry_attr);
3728 return 0;
3729
3730 nla_put_failure:
3731 err = -EMSGSIZE;
3732 err_match_values_put:
3733 err_action_values_put:
3734 nla_nest_cancel(skb, entry_attr);
3735 return err;
3736 }
3737
3738 static struct devlink_dpipe_table *
devlink_dpipe_table_find(struct list_head * dpipe_tables,const char * table_name,struct devlink * devlink)3739 devlink_dpipe_table_find(struct list_head *dpipe_tables,
3740 const char *table_name, struct devlink *devlink)
3741 {
3742 struct devlink_dpipe_table *table;
3743 list_for_each_entry_rcu(table, dpipe_tables, list,
3744 lockdep_is_held(&devlink->lock)) {
3745 if (!strcmp(table->name, table_name))
3746 return table;
3747 }
3748 return NULL;
3749 }
3750
devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx * dump_ctx)3751 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
3752 {
3753 struct devlink *devlink;
3754 int err;
3755
3756 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
3757 dump_ctx->info);
3758 if (err)
3759 return err;
3760
3761 dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
3762 dump_ctx->info->snd_portid,
3763 dump_ctx->info->snd_seq,
3764 &devlink_nl_family, NLM_F_MULTI,
3765 dump_ctx->cmd);
3766 if (!dump_ctx->hdr)
3767 goto nla_put_failure;
3768
3769 devlink = dump_ctx->info->user_ptr[0];
3770 if (devlink_nl_put_handle(dump_ctx->skb, devlink))
3771 goto nla_put_failure;
3772 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
3773 DEVLINK_ATTR_DPIPE_ENTRIES);
3774 if (!dump_ctx->nest)
3775 goto nla_put_failure;
3776 return 0;
3777
3778 nla_put_failure:
3779 nlmsg_free(dump_ctx->skb);
3780 return -EMSGSIZE;
3781 }
3782 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
3783
devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx * dump_ctx,struct devlink_dpipe_entry * entry)3784 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
3785 struct devlink_dpipe_entry *entry)
3786 {
3787 return devlink_dpipe_entry_put(dump_ctx->skb, entry);
3788 }
3789 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
3790
devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx * dump_ctx)3791 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
3792 {
3793 nla_nest_end(dump_ctx->skb, dump_ctx->nest);
3794 genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
3795 return 0;
3796 }
3797 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
3798
devlink_dpipe_entry_clear(struct devlink_dpipe_entry * entry)3799 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
3800
3801 {
3802 unsigned int value_count, value_index;
3803 struct devlink_dpipe_value *value;
3804
3805 value = entry->action_values;
3806 value_count = entry->action_values_count;
3807 for (value_index = 0; value_index < value_count; value_index++) {
3808 kfree(value[value_index].value);
3809 kfree(value[value_index].mask);
3810 }
3811
3812 value = entry->match_values;
3813 value_count = entry->match_values_count;
3814 for (value_index = 0; value_index < value_count; value_index++) {
3815 kfree(value[value_index].value);
3816 kfree(value[value_index].mask);
3817 }
3818 }
3819 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_clear);
3820
devlink_dpipe_entries_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_table * table)3821 static int devlink_dpipe_entries_fill(struct genl_info *info,
3822 enum devlink_command cmd, int flags,
3823 struct devlink_dpipe_table *table)
3824 {
3825 struct devlink_dpipe_dump_ctx dump_ctx;
3826 struct nlmsghdr *nlh;
3827 int err;
3828
3829 dump_ctx.skb = NULL;
3830 dump_ctx.cmd = cmd;
3831 dump_ctx.info = info;
3832
3833 err = table->table_ops->entries_dump(table->priv,
3834 table->counters_enabled,
3835 &dump_ctx);
3836 if (err)
3837 return err;
3838
3839 send_done:
3840 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
3841 NLMSG_DONE, 0, flags | NLM_F_MULTI);
3842 if (!nlh) {
3843 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
3844 if (err)
3845 return err;
3846 goto send_done;
3847 }
3848 return genlmsg_reply(dump_ctx.skb, info);
3849 }
3850
devlink_nl_cmd_dpipe_entries_get(struct sk_buff * skb,struct genl_info * info)3851 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
3852 struct genl_info *info)
3853 {
3854 struct devlink *devlink = info->user_ptr[0];
3855 struct devlink_dpipe_table *table;
3856 const char *table_name;
3857
3858 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME))
3859 return -EINVAL;
3860
3861 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
3862 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
3863 table_name, devlink);
3864 if (!table)
3865 return -EINVAL;
3866
3867 if (!table->table_ops->entries_dump)
3868 return -EINVAL;
3869
3870 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
3871 0, table);
3872 }
3873
devlink_dpipe_fields_put(struct sk_buff * skb,const struct devlink_dpipe_header * header)3874 static int devlink_dpipe_fields_put(struct sk_buff *skb,
3875 const struct devlink_dpipe_header *header)
3876 {
3877 struct devlink_dpipe_field *field;
3878 struct nlattr *field_attr;
3879 int i;
3880
3881 for (i = 0; i < header->fields_count; i++) {
3882 field = &header->fields[i];
3883 field_attr = nla_nest_start_noflag(skb,
3884 DEVLINK_ATTR_DPIPE_FIELD);
3885 if (!field_attr)
3886 return -EMSGSIZE;
3887 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
3888 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
3889 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
3890 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
3891 goto nla_put_failure;
3892 nla_nest_end(skb, field_attr);
3893 }
3894 return 0;
3895
3896 nla_put_failure:
3897 nla_nest_cancel(skb, field_attr);
3898 return -EMSGSIZE;
3899 }
3900
devlink_dpipe_header_put(struct sk_buff * skb,struct devlink_dpipe_header * header)3901 static int devlink_dpipe_header_put(struct sk_buff *skb,
3902 struct devlink_dpipe_header *header)
3903 {
3904 struct nlattr *fields_attr, *header_attr;
3905 int err;
3906
3907 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
3908 if (!header_attr)
3909 return -EMSGSIZE;
3910
3911 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
3912 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
3913 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
3914 goto nla_put_failure;
3915
3916 fields_attr = nla_nest_start_noflag(skb,
3917 DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
3918 if (!fields_attr)
3919 goto nla_put_failure;
3920
3921 err = devlink_dpipe_fields_put(skb, header);
3922 if (err) {
3923 nla_nest_cancel(skb, fields_attr);
3924 goto nla_put_failure;
3925 }
3926 nla_nest_end(skb, fields_attr);
3927 nla_nest_end(skb, header_attr);
3928 return 0;
3929
3930 nla_put_failure:
3931 err = -EMSGSIZE;
3932 nla_nest_cancel(skb, header_attr);
3933 return err;
3934 }
3935
devlink_dpipe_headers_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_headers * dpipe_headers)3936 static int devlink_dpipe_headers_fill(struct genl_info *info,
3937 enum devlink_command cmd, int flags,
3938 struct devlink_dpipe_headers *
3939 dpipe_headers)
3940 {
3941 struct devlink *devlink = info->user_ptr[0];
3942 struct nlattr *headers_attr;
3943 struct sk_buff *skb = NULL;
3944 struct nlmsghdr *nlh;
3945 void *hdr;
3946 int i, j;
3947 int err;
3948
3949 i = 0;
3950 start_again:
3951 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
3952 if (err)
3953 return err;
3954
3955 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
3956 &devlink_nl_family, NLM_F_MULTI, cmd);
3957 if (!hdr) {
3958 nlmsg_free(skb);
3959 return -EMSGSIZE;
3960 }
3961
3962 if (devlink_nl_put_handle(skb, devlink))
3963 goto nla_put_failure;
3964 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
3965 if (!headers_attr)
3966 goto nla_put_failure;
3967
3968 j = 0;
3969 for (; i < dpipe_headers->headers_count; i++) {
3970 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
3971 if (err) {
3972 if (!j)
3973 goto err_table_put;
3974 break;
3975 }
3976 j++;
3977 }
3978 nla_nest_end(skb, headers_attr);
3979 genlmsg_end(skb, hdr);
3980 if (i != dpipe_headers->headers_count)
3981 goto start_again;
3982
3983 send_done:
3984 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
3985 NLMSG_DONE, 0, flags | NLM_F_MULTI);
3986 if (!nlh) {
3987 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
3988 if (err)
3989 return err;
3990 goto send_done;
3991 }
3992 return genlmsg_reply(skb, info);
3993
3994 nla_put_failure:
3995 err = -EMSGSIZE;
3996 err_table_put:
3997 nlmsg_free(skb);
3998 return err;
3999 }
4000
devlink_nl_cmd_dpipe_headers_get(struct sk_buff * skb,struct genl_info * info)4001 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
4002 struct genl_info *info)
4003 {
4004 struct devlink *devlink = info->user_ptr[0];
4005
4006 if (!devlink->dpipe_headers)
4007 return -EOPNOTSUPP;
4008 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
4009 0, devlink->dpipe_headers);
4010 }
4011
devlink_dpipe_table_counters_set(struct devlink * devlink,const char * table_name,bool enable)4012 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
4013 const char *table_name,
4014 bool enable)
4015 {
4016 struct devlink_dpipe_table *table;
4017
4018 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
4019 table_name, devlink);
4020 if (!table)
4021 return -EINVAL;
4022
4023 if (table->counter_control_extern)
4024 return -EOPNOTSUPP;
4025
4026 if (!(table->counters_enabled ^ enable))
4027 return 0;
4028
4029 table->counters_enabled = enable;
4030 if (table->table_ops->counters_set_update)
4031 table->table_ops->counters_set_update(table->priv, enable);
4032 return 0;
4033 }
4034
devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff * skb,struct genl_info * info)4035 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
4036 struct genl_info *info)
4037 {
4038 struct devlink *devlink = info->user_ptr[0];
4039 const char *table_name;
4040 bool counters_enable;
4041
4042 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME) ||
4043 GENL_REQ_ATTR_CHECK(info,
4044 DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED))
4045 return -EINVAL;
4046
4047 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
4048 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
4049
4050 return devlink_dpipe_table_counters_set(devlink, table_name,
4051 counters_enable);
4052 }
4053
4054 static struct devlink_resource *
devlink_resource_find(struct devlink * devlink,struct devlink_resource * resource,u64 resource_id)4055 devlink_resource_find(struct devlink *devlink,
4056 struct devlink_resource *resource, u64 resource_id)
4057 {
4058 struct list_head *resource_list;
4059
4060 if (resource)
4061 resource_list = &resource->resource_list;
4062 else
4063 resource_list = &devlink->resource_list;
4064
4065 list_for_each_entry(resource, resource_list, list) {
4066 struct devlink_resource *child_resource;
4067
4068 if (resource->id == resource_id)
4069 return resource;
4070
4071 child_resource = devlink_resource_find(devlink, resource,
4072 resource_id);
4073 if (child_resource)
4074 return child_resource;
4075 }
4076 return NULL;
4077 }
4078
4079 static void
devlink_resource_validate_children(struct devlink_resource * resource)4080 devlink_resource_validate_children(struct devlink_resource *resource)
4081 {
4082 struct devlink_resource *child_resource;
4083 bool size_valid = true;
4084 u64 parts_size = 0;
4085
4086 if (list_empty(&resource->resource_list))
4087 goto out;
4088
4089 list_for_each_entry(child_resource, &resource->resource_list, list)
4090 parts_size += child_resource->size_new;
4091
4092 if (parts_size > resource->size_new)
4093 size_valid = false;
4094 out:
4095 resource->size_valid = size_valid;
4096 }
4097
4098 static int
devlink_resource_validate_size(struct devlink_resource * resource,u64 size,struct netlink_ext_ack * extack)4099 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
4100 struct netlink_ext_ack *extack)
4101 {
4102 u64 reminder;
4103 int err = 0;
4104
4105 if (size > resource->size_params.size_max) {
4106 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
4107 err = -EINVAL;
4108 }
4109
4110 if (size < resource->size_params.size_min) {
4111 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
4112 err = -EINVAL;
4113 }
4114
4115 div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
4116 if (reminder) {
4117 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
4118 err = -EINVAL;
4119 }
4120
4121 return err;
4122 }
4123
devlink_nl_cmd_resource_set(struct sk_buff * skb,struct genl_info * info)4124 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
4125 struct genl_info *info)
4126 {
4127 struct devlink *devlink = info->user_ptr[0];
4128 struct devlink_resource *resource;
4129 u64 resource_id;
4130 u64 size;
4131 int err;
4132
4133 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_ID) ||
4134 GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_SIZE))
4135 return -EINVAL;
4136 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
4137
4138 resource = devlink_resource_find(devlink, NULL, resource_id);
4139 if (!resource)
4140 return -EINVAL;
4141
4142 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
4143 err = devlink_resource_validate_size(resource, size, info->extack);
4144 if (err)
4145 return err;
4146
4147 resource->size_new = size;
4148 devlink_resource_validate_children(resource);
4149 if (resource->parent)
4150 devlink_resource_validate_children(resource->parent);
4151 return 0;
4152 }
4153
4154 static int
devlink_resource_size_params_put(struct devlink_resource * resource,struct sk_buff * skb)4155 devlink_resource_size_params_put(struct devlink_resource *resource,
4156 struct sk_buff *skb)
4157 {
4158 struct devlink_resource_size_params *size_params;
4159
4160 size_params = &resource->size_params;
4161 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
4162 size_params->size_granularity, DEVLINK_ATTR_PAD) ||
4163 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
4164 size_params->size_max, DEVLINK_ATTR_PAD) ||
4165 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
4166 size_params->size_min, DEVLINK_ATTR_PAD) ||
4167 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
4168 return -EMSGSIZE;
4169 return 0;
4170 }
4171
devlink_resource_occ_put(struct devlink_resource * resource,struct sk_buff * skb)4172 static int devlink_resource_occ_put(struct devlink_resource *resource,
4173 struct sk_buff *skb)
4174 {
4175 if (!resource->occ_get)
4176 return 0;
4177 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
4178 resource->occ_get(resource->occ_get_priv),
4179 DEVLINK_ATTR_PAD);
4180 }
4181
devlink_resource_put(struct devlink * devlink,struct sk_buff * skb,struct devlink_resource * resource)4182 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
4183 struct devlink_resource *resource)
4184 {
4185 struct devlink_resource *child_resource;
4186 struct nlattr *child_resource_attr;
4187 struct nlattr *resource_attr;
4188
4189 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
4190 if (!resource_attr)
4191 return -EMSGSIZE;
4192
4193 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
4194 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
4195 DEVLINK_ATTR_PAD) ||
4196 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
4197 DEVLINK_ATTR_PAD))
4198 goto nla_put_failure;
4199 if (resource->size != resource->size_new)
4200 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
4201 resource->size_new, DEVLINK_ATTR_PAD);
4202 if (devlink_resource_occ_put(resource, skb))
4203 goto nla_put_failure;
4204 if (devlink_resource_size_params_put(resource, skb))
4205 goto nla_put_failure;
4206 if (list_empty(&resource->resource_list))
4207 goto out;
4208
4209 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
4210 resource->size_valid))
4211 goto nla_put_failure;
4212
4213 child_resource_attr = nla_nest_start_noflag(skb,
4214 DEVLINK_ATTR_RESOURCE_LIST);
4215 if (!child_resource_attr)
4216 goto nla_put_failure;
4217
4218 list_for_each_entry(child_resource, &resource->resource_list, list) {
4219 if (devlink_resource_put(devlink, skb, child_resource))
4220 goto resource_put_failure;
4221 }
4222
4223 nla_nest_end(skb, child_resource_attr);
4224 out:
4225 nla_nest_end(skb, resource_attr);
4226 return 0;
4227
4228 resource_put_failure:
4229 nla_nest_cancel(skb, child_resource_attr);
4230 nla_put_failure:
4231 nla_nest_cancel(skb, resource_attr);
4232 return -EMSGSIZE;
4233 }
4234
devlink_resource_fill(struct genl_info * info,enum devlink_command cmd,int flags)4235 static int devlink_resource_fill(struct genl_info *info,
4236 enum devlink_command cmd, int flags)
4237 {
4238 struct devlink *devlink = info->user_ptr[0];
4239 struct devlink_resource *resource;
4240 struct nlattr *resources_attr;
4241 struct sk_buff *skb = NULL;
4242 struct nlmsghdr *nlh;
4243 bool incomplete;
4244 void *hdr;
4245 int i;
4246 int err;
4247
4248 resource = list_first_entry(&devlink->resource_list,
4249 struct devlink_resource, list);
4250 start_again:
4251 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
4252 if (err)
4253 return err;
4254
4255 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4256 &devlink_nl_family, NLM_F_MULTI, cmd);
4257 if (!hdr) {
4258 nlmsg_free(skb);
4259 return -EMSGSIZE;
4260 }
4261
4262 if (devlink_nl_put_handle(skb, devlink))
4263 goto nla_put_failure;
4264
4265 resources_attr = nla_nest_start_noflag(skb,
4266 DEVLINK_ATTR_RESOURCE_LIST);
4267 if (!resources_attr)
4268 goto nla_put_failure;
4269
4270 incomplete = false;
4271 i = 0;
4272 list_for_each_entry_from(resource, &devlink->resource_list, list) {
4273 err = devlink_resource_put(devlink, skb, resource);
4274 if (err) {
4275 if (!i)
4276 goto err_resource_put;
4277 incomplete = true;
4278 break;
4279 }
4280 i++;
4281 }
4282 nla_nest_end(skb, resources_attr);
4283 genlmsg_end(skb, hdr);
4284 if (incomplete)
4285 goto start_again;
4286 send_done:
4287 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4288 NLMSG_DONE, 0, flags | NLM_F_MULTI);
4289 if (!nlh) {
4290 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
4291 if (err)
4292 return err;
4293 goto send_done;
4294 }
4295 return genlmsg_reply(skb, info);
4296
4297 nla_put_failure:
4298 err = -EMSGSIZE;
4299 err_resource_put:
4300 nlmsg_free(skb);
4301 return err;
4302 }
4303
devlink_nl_cmd_resource_dump(struct sk_buff * skb,struct genl_info * info)4304 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
4305 struct genl_info *info)
4306 {
4307 struct devlink *devlink = info->user_ptr[0];
4308
4309 if (list_empty(&devlink->resource_list))
4310 return -EOPNOTSUPP;
4311
4312 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
4313 }
4314
4315 static int
devlink_resources_validate(struct devlink * devlink,struct devlink_resource * resource,struct genl_info * info)4316 devlink_resources_validate(struct devlink *devlink,
4317 struct devlink_resource *resource,
4318 struct genl_info *info)
4319 {
4320 struct list_head *resource_list;
4321 int err = 0;
4322
4323 if (resource)
4324 resource_list = &resource->resource_list;
4325 else
4326 resource_list = &devlink->resource_list;
4327
4328 list_for_each_entry(resource, resource_list, list) {
4329 if (!resource->size_valid)
4330 return -EINVAL;
4331 err = devlink_resources_validate(devlink, resource, info);
4332 if (err)
4333 return err;
4334 }
4335 return err;
4336 }
4337
devlink_netns_get(struct sk_buff * skb,struct genl_info * info)4338 static struct net *devlink_netns_get(struct sk_buff *skb,
4339 struct genl_info *info)
4340 {
4341 struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID];
4342 struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD];
4343 struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID];
4344 struct net *net;
4345
4346 if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) {
4347 NL_SET_ERR_MSG_MOD(info->extack, "multiple netns identifying attributes specified");
4348 return ERR_PTR(-EINVAL);
4349 }
4350
4351 if (netns_pid_attr) {
4352 net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr));
4353 } else if (netns_fd_attr) {
4354 net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr));
4355 } else if (netns_id_attr) {
4356 net = get_net_ns_by_id(sock_net(skb->sk),
4357 nla_get_u32(netns_id_attr));
4358 if (!net)
4359 net = ERR_PTR(-EINVAL);
4360 } else {
4361 WARN_ON(1);
4362 net = ERR_PTR(-EINVAL);
4363 }
4364 if (IS_ERR(net)) {
4365 NL_SET_ERR_MSG_MOD(info->extack, "Unknown network namespace");
4366 return ERR_PTR(-EINVAL);
4367 }
4368 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
4369 put_net(net);
4370 return ERR_PTR(-EPERM);
4371 }
4372 return net;
4373 }
4374
4375 static void devlink_param_notify(struct devlink *devlink,
4376 unsigned int port_index,
4377 struct devlink_param_item *param_item,
4378 enum devlink_command cmd);
4379
devlink_ns_change_notify(struct devlink * devlink,struct net * dest_net,struct net * curr_net,bool new)4380 static void devlink_ns_change_notify(struct devlink *devlink,
4381 struct net *dest_net, struct net *curr_net,
4382 bool new)
4383 {
4384 struct devlink_param_item *param_item;
4385 enum devlink_command cmd;
4386
4387 /* Userspace needs to be notified about devlink objects
4388 * removed from original and entering new network namespace.
4389 * The rest of the devlink objects are re-created during
4390 * reload process so the notifications are generated separatelly.
4391 */
4392
4393 if (!dest_net || net_eq(dest_net, curr_net))
4394 return;
4395
4396 if (new)
4397 devlink_notify(devlink, DEVLINK_CMD_NEW);
4398
4399 cmd = new ? DEVLINK_CMD_PARAM_NEW : DEVLINK_CMD_PARAM_DEL;
4400 list_for_each_entry(param_item, &devlink->param_list, list)
4401 devlink_param_notify(devlink, 0, param_item, cmd);
4402
4403 if (!new)
4404 devlink_notify(devlink, DEVLINK_CMD_DEL);
4405 }
4406
devlink_reload_supported(const struct devlink_ops * ops)4407 static bool devlink_reload_supported(const struct devlink_ops *ops)
4408 {
4409 return ops->reload_down && ops->reload_up;
4410 }
4411
devlink_reload_failed_set(struct devlink * devlink,bool reload_failed)4412 static void devlink_reload_failed_set(struct devlink *devlink,
4413 bool reload_failed)
4414 {
4415 if (devlink->reload_failed == reload_failed)
4416 return;
4417 devlink->reload_failed = reload_failed;
4418 devlink_notify(devlink, DEVLINK_CMD_NEW);
4419 }
4420
devlink_is_reload_failed(const struct devlink * devlink)4421 bool devlink_is_reload_failed(const struct devlink *devlink)
4422 {
4423 return devlink->reload_failed;
4424 }
4425 EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
4426
4427 static void
__devlink_reload_stats_update(struct devlink * devlink,u32 * reload_stats,enum devlink_reload_limit limit,u32 actions_performed)4428 __devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
4429 enum devlink_reload_limit limit, u32 actions_performed)
4430 {
4431 unsigned long actions = actions_performed;
4432 int stat_idx;
4433 int action;
4434
4435 for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
4436 stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
4437 reload_stats[stat_idx]++;
4438 }
4439 devlink_notify(devlink, DEVLINK_CMD_NEW);
4440 }
4441
4442 static void
devlink_reload_stats_update(struct devlink * devlink,enum devlink_reload_limit limit,u32 actions_performed)4443 devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
4444 u32 actions_performed)
4445 {
4446 __devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
4447 actions_performed);
4448 }
4449
4450 /**
4451 * devlink_remote_reload_actions_performed - Update devlink on reload actions
4452 * performed which are not a direct result of devlink reload call.
4453 *
4454 * This should be called by a driver after performing reload actions in case it was not
4455 * a result of devlink reload call. For example fw_activate was performed as a result
4456 * of devlink reload triggered fw_activate on another host.
4457 * The motivation for this function is to keep data on reload actions performed on this
4458 * function whether it was done due to direct devlink reload call or not.
4459 *
4460 * @devlink: devlink
4461 * @limit: reload limit
4462 * @actions_performed: bitmask of actions performed
4463 */
devlink_remote_reload_actions_performed(struct devlink * devlink,enum devlink_reload_limit limit,u32 actions_performed)4464 void devlink_remote_reload_actions_performed(struct devlink *devlink,
4465 enum devlink_reload_limit limit,
4466 u32 actions_performed)
4467 {
4468 if (WARN_ON(!actions_performed ||
4469 actions_performed & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
4470 actions_performed >= BIT(__DEVLINK_RELOAD_ACTION_MAX) ||
4471 limit > DEVLINK_RELOAD_LIMIT_MAX))
4472 return;
4473
4474 __devlink_reload_stats_update(devlink, devlink->stats.remote_reload_stats, limit,
4475 actions_performed);
4476 }
4477 EXPORT_SYMBOL_GPL(devlink_remote_reload_actions_performed);
4478
devlink_reload(struct devlink * devlink,struct net * dest_net,enum devlink_reload_action action,enum devlink_reload_limit limit,u32 * actions_performed,struct netlink_ext_ack * extack)4479 static int devlink_reload(struct devlink *devlink, struct net *dest_net,
4480 enum devlink_reload_action action, enum devlink_reload_limit limit,
4481 u32 *actions_performed, struct netlink_ext_ack *extack)
4482 {
4483 u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
4484 struct net *curr_net;
4485 int err;
4486
4487 memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
4488 sizeof(remote_reload_stats));
4489
4490 curr_net = devlink_net(devlink);
4491 devlink_ns_change_notify(devlink, dest_net, curr_net, false);
4492 err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
4493 if (err)
4494 return err;
4495
4496 if (dest_net && !net_eq(dest_net, curr_net))
4497 write_pnet(&devlink->_net, dest_net);
4498
4499 err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
4500 devlink_reload_failed_set(devlink, !!err);
4501 if (err)
4502 return err;
4503
4504 devlink_ns_change_notify(devlink, dest_net, curr_net, true);
4505 WARN_ON(!(*actions_performed & BIT(action)));
4506 /* Catch driver on updating the remote action within devlink reload */
4507 WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
4508 sizeof(remote_reload_stats)));
4509 devlink_reload_stats_update(devlink, limit, *actions_performed);
4510 return 0;
4511 }
4512
4513 static int
devlink_nl_reload_actions_performed_snd(struct devlink * devlink,u32 actions_performed,enum devlink_command cmd,struct genl_info * info)4514 devlink_nl_reload_actions_performed_snd(struct devlink *devlink, u32 actions_performed,
4515 enum devlink_command cmd, struct genl_info *info)
4516 {
4517 struct sk_buff *msg;
4518 void *hdr;
4519
4520 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4521 if (!msg)
4522 return -ENOMEM;
4523
4524 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &devlink_nl_family, 0, cmd);
4525 if (!hdr)
4526 goto free_msg;
4527
4528 if (devlink_nl_put_handle(msg, devlink))
4529 goto nla_put_failure;
4530
4531 if (nla_put_bitfield32(msg, DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, actions_performed,
4532 actions_performed))
4533 goto nla_put_failure;
4534 genlmsg_end(msg, hdr);
4535
4536 return genlmsg_reply(msg, info);
4537
4538 nla_put_failure:
4539 genlmsg_cancel(msg, hdr);
4540 free_msg:
4541 nlmsg_free(msg);
4542 return -EMSGSIZE;
4543 }
4544
devlink_nl_cmd_reload(struct sk_buff * skb,struct genl_info * info)4545 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
4546 {
4547 struct devlink *devlink = info->user_ptr[0];
4548 enum devlink_reload_action action;
4549 enum devlink_reload_limit limit;
4550 struct net *dest_net = NULL;
4551 u32 actions_performed;
4552 int err;
4553
4554 if (!(devlink->features & DEVLINK_F_RELOAD))
4555 return -EOPNOTSUPP;
4556
4557 err = devlink_resources_validate(devlink, NULL, info);
4558 if (err) {
4559 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
4560 return err;
4561 }
4562
4563 if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
4564 action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]);
4565 else
4566 action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT;
4567
4568 if (!devlink_reload_action_is_supported(devlink, action)) {
4569 NL_SET_ERR_MSG_MOD(info->extack,
4570 "Requested reload action is not supported by the driver");
4571 return -EOPNOTSUPP;
4572 }
4573
4574 limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
4575 if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
4576 struct nla_bitfield32 limits;
4577 u32 limits_selected;
4578
4579 limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
4580 limits_selected = limits.value & limits.selector;
4581 if (!limits_selected) {
4582 NL_SET_ERR_MSG_MOD(info->extack, "Invalid limit selected");
4583 return -EINVAL;
4584 }
4585 for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
4586 if (limits_selected & BIT(limit))
4587 break;
4588 /* UAPI enables multiselection, but currently it is not used */
4589 if (limits_selected != BIT(limit)) {
4590 NL_SET_ERR_MSG_MOD(info->extack,
4591 "Multiselection of limit is not supported");
4592 return -EOPNOTSUPP;
4593 }
4594 if (!devlink_reload_limit_is_supported(devlink, limit)) {
4595 NL_SET_ERR_MSG_MOD(info->extack,
4596 "Requested limit is not supported by the driver");
4597 return -EOPNOTSUPP;
4598 }
4599 if (devlink_reload_combination_is_invalid(action, limit)) {
4600 NL_SET_ERR_MSG_MOD(info->extack,
4601 "Requested limit is invalid for this action");
4602 return -EINVAL;
4603 }
4604 }
4605 if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
4606 info->attrs[DEVLINK_ATTR_NETNS_FD] ||
4607 info->attrs[DEVLINK_ATTR_NETNS_ID]) {
4608 dest_net = devlink_netns_get(skb, info);
4609 if (IS_ERR(dest_net))
4610 return PTR_ERR(dest_net);
4611 }
4612
4613 err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
4614
4615 if (dest_net)
4616 put_net(dest_net);
4617
4618 if (err)
4619 return err;
4620 /* For backward compatibility generate reply only if attributes used by user */
4621 if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
4622 return 0;
4623
4624 return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
4625 DEVLINK_CMD_RELOAD, info);
4626 }
4627
devlink_nl_flash_update_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,struct devlink_flash_notify * params)4628 static int devlink_nl_flash_update_fill(struct sk_buff *msg,
4629 struct devlink *devlink,
4630 enum devlink_command cmd,
4631 struct devlink_flash_notify *params)
4632 {
4633 void *hdr;
4634
4635 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
4636 if (!hdr)
4637 return -EMSGSIZE;
4638
4639 if (devlink_nl_put_handle(msg, devlink))
4640 goto nla_put_failure;
4641
4642 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
4643 goto out;
4644
4645 if (params->status_msg &&
4646 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
4647 params->status_msg))
4648 goto nla_put_failure;
4649 if (params->component &&
4650 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
4651 params->component))
4652 goto nla_put_failure;
4653 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
4654 params->done, DEVLINK_ATTR_PAD))
4655 goto nla_put_failure;
4656 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
4657 params->total, DEVLINK_ATTR_PAD))
4658 goto nla_put_failure;
4659 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,
4660 params->timeout, DEVLINK_ATTR_PAD))
4661 goto nla_put_failure;
4662
4663 out:
4664 genlmsg_end(msg, hdr);
4665 return 0;
4666
4667 nla_put_failure:
4668 genlmsg_cancel(msg, hdr);
4669 return -EMSGSIZE;
4670 }
4671
__devlink_flash_update_notify(struct devlink * devlink,enum devlink_command cmd,struct devlink_flash_notify * params)4672 static void __devlink_flash_update_notify(struct devlink *devlink,
4673 enum devlink_command cmd,
4674 struct devlink_flash_notify *params)
4675 {
4676 struct sk_buff *msg;
4677 int err;
4678
4679 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
4680 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
4681 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
4682
4683 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
4684 return;
4685
4686 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4687 if (!msg)
4688 return;
4689
4690 err = devlink_nl_flash_update_fill(msg, devlink, cmd, params);
4691 if (err)
4692 goto out_free_msg;
4693
4694 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
4695 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
4696 return;
4697
4698 out_free_msg:
4699 nlmsg_free(msg);
4700 }
4701
devlink_flash_update_begin_notify(struct devlink * devlink)4702 static void devlink_flash_update_begin_notify(struct devlink *devlink)
4703 {
4704 struct devlink_flash_notify params = {};
4705
4706 __devlink_flash_update_notify(devlink,
4707 DEVLINK_CMD_FLASH_UPDATE,
4708 ¶ms);
4709 }
4710
devlink_flash_update_end_notify(struct devlink * devlink)4711 static void devlink_flash_update_end_notify(struct devlink *devlink)
4712 {
4713 struct devlink_flash_notify params = {};
4714
4715 __devlink_flash_update_notify(devlink,
4716 DEVLINK_CMD_FLASH_UPDATE_END,
4717 ¶ms);
4718 }
4719
devlink_flash_update_status_notify(struct devlink * devlink,const char * status_msg,const char * component,unsigned long done,unsigned long total)4720 void devlink_flash_update_status_notify(struct devlink *devlink,
4721 const char *status_msg,
4722 const char *component,
4723 unsigned long done,
4724 unsigned long total)
4725 {
4726 struct devlink_flash_notify params = {
4727 .status_msg = status_msg,
4728 .component = component,
4729 .done = done,
4730 .total = total,
4731 };
4732
4733 __devlink_flash_update_notify(devlink,
4734 DEVLINK_CMD_FLASH_UPDATE_STATUS,
4735 ¶ms);
4736 }
4737 EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
4738
devlink_flash_update_timeout_notify(struct devlink * devlink,const char * status_msg,const char * component,unsigned long timeout)4739 void devlink_flash_update_timeout_notify(struct devlink *devlink,
4740 const char *status_msg,
4741 const char *component,
4742 unsigned long timeout)
4743 {
4744 struct devlink_flash_notify params = {
4745 .status_msg = status_msg,
4746 .component = component,
4747 .timeout = timeout,
4748 };
4749
4750 __devlink_flash_update_notify(devlink,
4751 DEVLINK_CMD_FLASH_UPDATE_STATUS,
4752 ¶ms);
4753 }
4754 EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);
4755
4756 struct devlink_info_req {
4757 struct sk_buff *msg;
4758 void (*version_cb)(const char *version_name,
4759 enum devlink_info_version_type version_type,
4760 void *version_cb_priv);
4761 void *version_cb_priv;
4762 };
4763
4764 struct devlink_flash_component_lookup_ctx {
4765 const char *lookup_name;
4766 bool lookup_name_found;
4767 };
4768
4769 static void
devlink_flash_component_lookup_cb(const char * version_name,enum devlink_info_version_type version_type,void * version_cb_priv)4770 devlink_flash_component_lookup_cb(const char *version_name,
4771 enum devlink_info_version_type version_type,
4772 void *version_cb_priv)
4773 {
4774 struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;
4775
4776 if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
4777 lookup_ctx->lookup_name_found)
4778 return;
4779
4780 lookup_ctx->lookup_name_found =
4781 !strcmp(lookup_ctx->lookup_name, version_name);
4782 }
4783
devlink_flash_component_get(struct devlink * devlink,struct nlattr * nla_component,const char ** p_component,struct netlink_ext_ack * extack)4784 static int devlink_flash_component_get(struct devlink *devlink,
4785 struct nlattr *nla_component,
4786 const char **p_component,
4787 struct netlink_ext_ack *extack)
4788 {
4789 struct devlink_flash_component_lookup_ctx lookup_ctx = {};
4790 struct devlink_info_req req = {};
4791 const char *component;
4792 int ret;
4793
4794 if (!nla_component)
4795 return 0;
4796
4797 component = nla_data(nla_component);
4798
4799 if (!devlink->ops->info_get) {
4800 NL_SET_ERR_MSG_ATTR(extack, nla_component,
4801 "component update is not supported by this device");
4802 return -EOPNOTSUPP;
4803 }
4804
4805 lookup_ctx.lookup_name = component;
4806 req.version_cb = devlink_flash_component_lookup_cb;
4807 req.version_cb_priv = &lookup_ctx;
4808
4809 ret = devlink->ops->info_get(devlink, &req, NULL);
4810 if (ret)
4811 return ret;
4812
4813 if (!lookup_ctx.lookup_name_found) {
4814 NL_SET_ERR_MSG_ATTR(extack, nla_component,
4815 "selected component is not supported by this device");
4816 return -EINVAL;
4817 }
4818 *p_component = component;
4819 return 0;
4820 }
4821
devlink_nl_cmd_flash_update(struct sk_buff * skb,struct genl_info * info)4822 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
4823 struct genl_info *info)
4824 {
4825 struct nlattr *nla_overwrite_mask, *nla_file_name;
4826 struct devlink_flash_update_params params = {};
4827 struct devlink *devlink = info->user_ptr[0];
4828 const char *file_name;
4829 u32 supported_params;
4830 int ret;
4831
4832 if (!devlink->ops->flash_update)
4833 return -EOPNOTSUPP;
4834
4835 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
4836 return -EINVAL;
4837
4838 ret = devlink_flash_component_get(devlink,
4839 info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
4840 ¶ms.component, info->extack);
4841 if (ret)
4842 return ret;
4843
4844 supported_params = devlink->ops->supported_flash_update_params;
4845
4846 nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
4847 if (nla_overwrite_mask) {
4848 struct nla_bitfield32 sections;
4849
4850 if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) {
4851 NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask,
4852 "overwrite settings are not supported by this device");
4853 return -EOPNOTSUPP;
4854 }
4855 sections = nla_get_bitfield32(nla_overwrite_mask);
4856 params.overwrite_mask = sections.value & sections.selector;
4857 }
4858
4859 nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
4860 file_name = nla_data(nla_file_name);
4861 ret = request_firmware(¶ms.fw, file_name, devlink->dev);
4862 if (ret) {
4863 NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name, "failed to locate the requested firmware file");
4864 return ret;
4865 }
4866
4867 devlink_flash_update_begin_notify(devlink);
4868 ret = devlink->ops->flash_update(devlink, ¶ms, info->extack);
4869 devlink_flash_update_end_notify(devlink);
4870
4871 release_firmware(params.fw);
4872
4873 return ret;
4874 }
4875
4876 static int
devlink_nl_selftests_fill(struct sk_buff * msg,struct devlink * devlink,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)4877 devlink_nl_selftests_fill(struct sk_buff *msg, struct devlink *devlink,
4878 u32 portid, u32 seq, int flags,
4879 struct netlink_ext_ack *extack)
4880 {
4881 struct nlattr *selftests;
4882 void *hdr;
4883 int err;
4884 int i;
4885
4886 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags,
4887 DEVLINK_CMD_SELFTESTS_GET);
4888 if (!hdr)
4889 return -EMSGSIZE;
4890
4891 err = -EMSGSIZE;
4892 if (devlink_nl_put_handle(msg, devlink))
4893 goto err_cancel_msg;
4894
4895 selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
4896 if (!selftests)
4897 goto err_cancel_msg;
4898
4899 for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
4900 i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
4901 if (devlink->ops->selftest_check(devlink, i, extack)) {
4902 err = nla_put_flag(msg, i);
4903 if (err)
4904 goto err_cancel_msg;
4905 }
4906 }
4907
4908 nla_nest_end(msg, selftests);
4909 genlmsg_end(msg, hdr);
4910 return 0;
4911
4912 err_cancel_msg:
4913 genlmsg_cancel(msg, hdr);
4914 return err;
4915 }
4916
devlink_nl_cmd_selftests_get_doit(struct sk_buff * skb,struct genl_info * info)4917 static int devlink_nl_cmd_selftests_get_doit(struct sk_buff *skb,
4918 struct genl_info *info)
4919 {
4920 struct devlink *devlink = info->user_ptr[0];
4921 struct sk_buff *msg;
4922 int err;
4923
4924 if (!devlink->ops->selftest_check)
4925 return -EOPNOTSUPP;
4926
4927 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4928 if (!msg)
4929 return -ENOMEM;
4930
4931 err = devlink_nl_selftests_fill(msg, devlink, info->snd_portid,
4932 info->snd_seq, 0, info->extack);
4933 if (err) {
4934 nlmsg_free(msg);
4935 return err;
4936 }
4937
4938 return genlmsg_reply(msg, info);
4939 }
4940
devlink_nl_cmd_selftests_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)4941 static int devlink_nl_cmd_selftests_get_dumpit(struct sk_buff *msg,
4942 struct netlink_callback *cb)
4943 {
4944 struct devlink *devlink;
4945 int start = cb->args[0];
4946 unsigned long index;
4947 int idx = 0;
4948 int err = 0;
4949
4950 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
4951 if (idx < start || !devlink->ops->selftest_check)
4952 goto inc;
4953
4954 devl_lock(devlink);
4955 err = devlink_nl_selftests_fill(msg, devlink,
4956 NETLINK_CB(cb->skb).portid,
4957 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4958 cb->extack);
4959 devl_unlock(devlink);
4960 if (err) {
4961 devlink_put(devlink);
4962 break;
4963 }
4964 inc:
4965 idx++;
4966 devlink_put(devlink);
4967 }
4968
4969 if (err != -EMSGSIZE)
4970 return err;
4971
4972 cb->args[0] = idx;
4973 return msg->len;
4974 }
4975
devlink_selftest_result_put(struct sk_buff * skb,unsigned int id,enum devlink_selftest_status test_status)4976 static int devlink_selftest_result_put(struct sk_buff *skb, unsigned int id,
4977 enum devlink_selftest_status test_status)
4978 {
4979 struct nlattr *result_attr;
4980
4981 result_attr = nla_nest_start(skb, DEVLINK_ATTR_SELFTEST_RESULT);
4982 if (!result_attr)
4983 return -EMSGSIZE;
4984
4985 if (nla_put_u32(skb, DEVLINK_ATTR_SELFTEST_RESULT_ID, id) ||
4986 nla_put_u8(skb, DEVLINK_ATTR_SELFTEST_RESULT_STATUS,
4987 test_status))
4988 goto nla_put_failure;
4989
4990 nla_nest_end(skb, result_attr);
4991 return 0;
4992
4993 nla_put_failure:
4994 nla_nest_cancel(skb, result_attr);
4995 return -EMSGSIZE;
4996 }
4997
devlink_nl_cmd_selftests_run(struct sk_buff * skb,struct genl_info * info)4998 static int devlink_nl_cmd_selftests_run(struct sk_buff *skb,
4999 struct genl_info *info)
5000 {
5001 struct nlattr *tb[DEVLINK_ATTR_SELFTEST_ID_MAX + 1];
5002 struct devlink *devlink = info->user_ptr[0];
5003 struct nlattr *attrs, *selftests;
5004 struct sk_buff *msg;
5005 void *hdr;
5006 int err;
5007 int i;
5008
5009 if (!devlink->ops->selftest_run || !devlink->ops->selftest_check)
5010 return -EOPNOTSUPP;
5011
5012 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SELFTESTS))
5013 return -EINVAL;
5014
5015 attrs = info->attrs[DEVLINK_ATTR_SELFTESTS];
5016
5017 err = nla_parse_nested(tb, DEVLINK_ATTR_SELFTEST_ID_MAX, attrs,
5018 devlink_selftest_nl_policy, info->extack);
5019 if (err < 0)
5020 return err;
5021
5022 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5023 if (!msg)
5024 return -ENOMEM;
5025
5026 err = -EMSGSIZE;
5027 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
5028 &devlink_nl_family, 0, DEVLINK_CMD_SELFTESTS_RUN);
5029 if (!hdr)
5030 goto free_msg;
5031
5032 if (devlink_nl_put_handle(msg, devlink))
5033 goto genlmsg_cancel;
5034
5035 selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
5036 if (!selftests)
5037 goto genlmsg_cancel;
5038
5039 for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
5040 i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
5041 enum devlink_selftest_status test_status;
5042
5043 if (nla_get_flag(tb[i])) {
5044 if (!devlink->ops->selftest_check(devlink, i,
5045 info->extack)) {
5046 if (devlink_selftest_result_put(msg, i,
5047 DEVLINK_SELFTEST_STATUS_SKIP))
5048 goto selftests_nest_cancel;
5049 continue;
5050 }
5051
5052 test_status = devlink->ops->selftest_run(devlink, i,
5053 info->extack);
5054 if (devlink_selftest_result_put(msg, i, test_status))
5055 goto selftests_nest_cancel;
5056 }
5057 }
5058
5059 nla_nest_end(msg, selftests);
5060 genlmsg_end(msg, hdr);
5061 return genlmsg_reply(msg, info);
5062
5063 selftests_nest_cancel:
5064 nla_nest_cancel(msg, selftests);
5065 genlmsg_cancel:
5066 genlmsg_cancel(msg, hdr);
5067 free_msg:
5068 nlmsg_free(msg);
5069 return err;
5070 }
5071
5072 static const struct devlink_param devlink_param_generic[] = {
5073 {
5074 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
5075 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
5076 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
5077 },
5078 {
5079 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
5080 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
5081 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
5082 },
5083 {
5084 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
5085 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
5086 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
5087 },
5088 {
5089 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
5090 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
5091 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
5092 },
5093 {
5094 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
5095 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
5096 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
5097 },
5098 {
5099 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
5100 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
5101 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
5102 },
5103 {
5104 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
5105 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
5106 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
5107 },
5108 {
5109 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
5110 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
5111 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
5112 },
5113 {
5114 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
5115 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
5116 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
5117 },
5118 {
5119 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
5120 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
5121 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
5122 },
5123 {
5124 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET,
5125 .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME,
5126 .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE,
5127 },
5128 {
5129 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
5130 .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME,
5131 .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE,
5132 },
5133 {
5134 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
5135 .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME,
5136 .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE,
5137 },
5138 {
5139 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
5140 .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME,
5141 .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE,
5142 },
5143 {
5144 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
5145 .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME,
5146 .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE,
5147 },
5148 {
5149 .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
5150 .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME,
5151 .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE,
5152 },
5153 {
5154 .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
5155 .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME,
5156 .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE,
5157 },
5158 };
5159
devlink_param_generic_verify(const struct devlink_param * param)5160 static int devlink_param_generic_verify(const struct devlink_param *param)
5161 {
5162 /* verify it match generic parameter by id and name */
5163 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
5164 return -EINVAL;
5165 if (strcmp(param->name, devlink_param_generic[param->id].name))
5166 return -ENOENT;
5167
5168 WARN_ON(param->type != devlink_param_generic[param->id].type);
5169
5170 return 0;
5171 }
5172
devlink_param_driver_verify(const struct devlink_param * param)5173 static int devlink_param_driver_verify(const struct devlink_param *param)
5174 {
5175 int i;
5176
5177 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
5178 return -EINVAL;
5179 /* verify no such name in generic params */
5180 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
5181 if (!strcmp(param->name, devlink_param_generic[i].name))
5182 return -EEXIST;
5183
5184 return 0;
5185 }
5186
5187 static struct devlink_param_item *
devlink_param_find_by_name(struct list_head * param_list,const char * param_name)5188 devlink_param_find_by_name(struct list_head *param_list,
5189 const char *param_name)
5190 {
5191 struct devlink_param_item *param_item;
5192
5193 list_for_each_entry(param_item, param_list, list)
5194 if (!strcmp(param_item->param->name, param_name))
5195 return param_item;
5196 return NULL;
5197 }
5198
5199 static struct devlink_param_item *
devlink_param_find_by_id(struct list_head * param_list,u32 param_id)5200 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
5201 {
5202 struct devlink_param_item *param_item;
5203
5204 list_for_each_entry(param_item, param_list, list)
5205 if (param_item->param->id == param_id)
5206 return param_item;
5207 return NULL;
5208 }
5209
5210 static bool
devlink_param_cmode_is_supported(const struct devlink_param * param,enum devlink_param_cmode cmode)5211 devlink_param_cmode_is_supported(const struct devlink_param *param,
5212 enum devlink_param_cmode cmode)
5213 {
5214 return test_bit(cmode, ¶m->supported_cmodes);
5215 }
5216
devlink_param_get(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)5217 static int devlink_param_get(struct devlink *devlink,
5218 const struct devlink_param *param,
5219 struct devlink_param_gset_ctx *ctx)
5220 {
5221 if (!param->get || devlink->reload_failed)
5222 return -EOPNOTSUPP;
5223 return param->get(devlink, param->id, ctx);
5224 }
5225
devlink_param_set(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)5226 static int devlink_param_set(struct devlink *devlink,
5227 const struct devlink_param *param,
5228 struct devlink_param_gset_ctx *ctx)
5229 {
5230 if (!param->set || devlink->reload_failed)
5231 return -EOPNOTSUPP;
5232 return param->set(devlink, param->id, ctx);
5233 }
5234
5235 static int
devlink_param_type_to_nla_type(enum devlink_param_type param_type)5236 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
5237 {
5238 switch (param_type) {
5239 case DEVLINK_PARAM_TYPE_U8:
5240 return NLA_U8;
5241 case DEVLINK_PARAM_TYPE_U16:
5242 return NLA_U16;
5243 case DEVLINK_PARAM_TYPE_U32:
5244 return NLA_U32;
5245 case DEVLINK_PARAM_TYPE_STRING:
5246 return NLA_STRING;
5247 case DEVLINK_PARAM_TYPE_BOOL:
5248 return NLA_FLAG;
5249 default:
5250 return -EINVAL;
5251 }
5252 }
5253
5254 static int
devlink_nl_param_value_fill_one(struct sk_buff * msg,enum devlink_param_type type,enum devlink_param_cmode cmode,union devlink_param_value val)5255 devlink_nl_param_value_fill_one(struct sk_buff *msg,
5256 enum devlink_param_type type,
5257 enum devlink_param_cmode cmode,
5258 union devlink_param_value val)
5259 {
5260 struct nlattr *param_value_attr;
5261
5262 param_value_attr = nla_nest_start_noflag(msg,
5263 DEVLINK_ATTR_PARAM_VALUE);
5264 if (!param_value_attr)
5265 goto nla_put_failure;
5266
5267 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
5268 goto value_nest_cancel;
5269
5270 switch (type) {
5271 case DEVLINK_PARAM_TYPE_U8:
5272 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
5273 goto value_nest_cancel;
5274 break;
5275 case DEVLINK_PARAM_TYPE_U16:
5276 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
5277 goto value_nest_cancel;
5278 break;
5279 case DEVLINK_PARAM_TYPE_U32:
5280 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
5281 goto value_nest_cancel;
5282 break;
5283 case DEVLINK_PARAM_TYPE_STRING:
5284 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
5285 val.vstr))
5286 goto value_nest_cancel;
5287 break;
5288 case DEVLINK_PARAM_TYPE_BOOL:
5289 if (val.vbool &&
5290 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
5291 goto value_nest_cancel;
5292 break;
5293 }
5294
5295 nla_nest_end(msg, param_value_attr);
5296 return 0;
5297
5298 value_nest_cancel:
5299 nla_nest_cancel(msg, param_value_attr);
5300 nla_put_failure:
5301 return -EMSGSIZE;
5302 }
5303
devlink_nl_param_fill(struct sk_buff * msg,struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)5304 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
5305 unsigned int port_index,
5306 struct devlink_param_item *param_item,
5307 enum devlink_command cmd,
5308 u32 portid, u32 seq, int flags)
5309 {
5310 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
5311 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
5312 const struct devlink_param *param = param_item->param;
5313 struct devlink_param_gset_ctx ctx;
5314 struct nlattr *param_values_list;
5315 struct nlattr *param_attr;
5316 int nla_type;
5317 void *hdr;
5318 int err;
5319 int i;
5320
5321 /* Get value from driver part to driverinit configuration mode */
5322 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
5323 if (!devlink_param_cmode_is_supported(param, i))
5324 continue;
5325 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
5326 if (!param_item->driverinit_value_valid)
5327 return -EOPNOTSUPP;
5328 param_value[i] = param_item->driverinit_value;
5329 } else {
5330 ctx.cmode = i;
5331 err = devlink_param_get(devlink, param, &ctx);
5332 if (err)
5333 return err;
5334 param_value[i] = ctx.val;
5335 }
5336 param_value_set[i] = true;
5337 }
5338
5339 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5340 if (!hdr)
5341 return -EMSGSIZE;
5342
5343 if (devlink_nl_put_handle(msg, devlink))
5344 goto genlmsg_cancel;
5345
5346 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
5347 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
5348 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
5349 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
5350 goto genlmsg_cancel;
5351
5352 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
5353 if (!param_attr)
5354 goto genlmsg_cancel;
5355 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
5356 goto param_nest_cancel;
5357 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
5358 goto param_nest_cancel;
5359
5360 nla_type = devlink_param_type_to_nla_type(param->type);
5361 if (nla_type < 0)
5362 goto param_nest_cancel;
5363 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
5364 goto param_nest_cancel;
5365
5366 param_values_list = nla_nest_start_noflag(msg,
5367 DEVLINK_ATTR_PARAM_VALUES_LIST);
5368 if (!param_values_list)
5369 goto param_nest_cancel;
5370
5371 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
5372 if (!param_value_set[i])
5373 continue;
5374 err = devlink_nl_param_value_fill_one(msg, param->type,
5375 i, param_value[i]);
5376 if (err)
5377 goto values_list_nest_cancel;
5378 }
5379
5380 nla_nest_end(msg, param_values_list);
5381 nla_nest_end(msg, param_attr);
5382 genlmsg_end(msg, hdr);
5383 return 0;
5384
5385 values_list_nest_cancel:
5386 nla_nest_end(msg, param_values_list);
5387 param_nest_cancel:
5388 nla_nest_cancel(msg, param_attr);
5389 genlmsg_cancel:
5390 genlmsg_cancel(msg, hdr);
5391 return -EMSGSIZE;
5392 }
5393
devlink_param_notify(struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd)5394 static void devlink_param_notify(struct devlink *devlink,
5395 unsigned int port_index,
5396 struct devlink_param_item *param_item,
5397 enum devlink_command cmd)
5398 {
5399 struct sk_buff *msg;
5400 int err;
5401
5402 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
5403 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
5404 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
5405 ASSERT_DEVLINK_REGISTERED(devlink);
5406
5407 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5408 if (!msg)
5409 return;
5410 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
5411 0, 0, 0);
5412 if (err) {
5413 nlmsg_free(msg);
5414 return;
5415 }
5416
5417 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
5418 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
5419 }
5420
devlink_nl_cmd_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)5421 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
5422 struct netlink_callback *cb)
5423 {
5424 struct devlink_param_item *param_item;
5425 struct devlink *devlink;
5426 int start = cb->args[0];
5427 unsigned long index;
5428 int idx = 0;
5429 int err = 0;
5430
5431 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
5432 devl_lock(devlink);
5433 list_for_each_entry(param_item, &devlink->param_list, list) {
5434 if (idx < start) {
5435 idx++;
5436 continue;
5437 }
5438 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
5439 DEVLINK_CMD_PARAM_GET,
5440 NETLINK_CB(cb->skb).portid,
5441 cb->nlh->nlmsg_seq,
5442 NLM_F_MULTI);
5443 if (err == -EOPNOTSUPP) {
5444 err = 0;
5445 } else if (err) {
5446 devl_unlock(devlink);
5447 devlink_put(devlink);
5448 goto out;
5449 }
5450 idx++;
5451 }
5452 devl_unlock(devlink);
5453 devlink_put(devlink);
5454 }
5455 out:
5456 if (err != -EMSGSIZE)
5457 return err;
5458
5459 cb->args[0] = idx;
5460 return msg->len;
5461 }
5462
5463 static int
devlink_param_type_get_from_info(struct genl_info * info,enum devlink_param_type * param_type)5464 devlink_param_type_get_from_info(struct genl_info *info,
5465 enum devlink_param_type *param_type)
5466 {
5467 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
5468 return -EINVAL;
5469
5470 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
5471 case NLA_U8:
5472 *param_type = DEVLINK_PARAM_TYPE_U8;
5473 break;
5474 case NLA_U16:
5475 *param_type = DEVLINK_PARAM_TYPE_U16;
5476 break;
5477 case NLA_U32:
5478 *param_type = DEVLINK_PARAM_TYPE_U32;
5479 break;
5480 case NLA_STRING:
5481 *param_type = DEVLINK_PARAM_TYPE_STRING;
5482 break;
5483 case NLA_FLAG:
5484 *param_type = DEVLINK_PARAM_TYPE_BOOL;
5485 break;
5486 default:
5487 return -EINVAL;
5488 }
5489
5490 return 0;
5491 }
5492
5493 static int
devlink_param_value_get_from_info(const struct devlink_param * param,struct genl_info * info,union devlink_param_value * value)5494 devlink_param_value_get_from_info(const struct devlink_param *param,
5495 struct genl_info *info,
5496 union devlink_param_value *value)
5497 {
5498 struct nlattr *param_data;
5499 int len;
5500
5501 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
5502
5503 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
5504 return -EINVAL;
5505
5506 switch (param->type) {
5507 case DEVLINK_PARAM_TYPE_U8:
5508 if (nla_len(param_data) != sizeof(u8))
5509 return -EINVAL;
5510 value->vu8 = nla_get_u8(param_data);
5511 break;
5512 case DEVLINK_PARAM_TYPE_U16:
5513 if (nla_len(param_data) != sizeof(u16))
5514 return -EINVAL;
5515 value->vu16 = nla_get_u16(param_data);
5516 break;
5517 case DEVLINK_PARAM_TYPE_U32:
5518 if (nla_len(param_data) != sizeof(u32))
5519 return -EINVAL;
5520 value->vu32 = nla_get_u32(param_data);
5521 break;
5522 case DEVLINK_PARAM_TYPE_STRING:
5523 len = strnlen(nla_data(param_data), nla_len(param_data));
5524 if (len == nla_len(param_data) ||
5525 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
5526 return -EINVAL;
5527 strcpy(value->vstr, nla_data(param_data));
5528 break;
5529 case DEVLINK_PARAM_TYPE_BOOL:
5530 if (param_data && nla_len(param_data))
5531 return -EINVAL;
5532 value->vbool = nla_get_flag(param_data);
5533 break;
5534 }
5535 return 0;
5536 }
5537
5538 static struct devlink_param_item *
devlink_param_get_from_info(struct list_head * param_list,struct genl_info * info)5539 devlink_param_get_from_info(struct list_head *param_list,
5540 struct genl_info *info)
5541 {
5542 char *param_name;
5543
5544 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
5545 return NULL;
5546
5547 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
5548 return devlink_param_find_by_name(param_list, param_name);
5549 }
5550
devlink_nl_cmd_param_get_doit(struct sk_buff * skb,struct genl_info * info)5551 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
5552 struct genl_info *info)
5553 {
5554 struct devlink *devlink = info->user_ptr[0];
5555 struct devlink_param_item *param_item;
5556 struct sk_buff *msg;
5557 int err;
5558
5559 param_item = devlink_param_get_from_info(&devlink->param_list, info);
5560 if (!param_item)
5561 return -EINVAL;
5562
5563 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5564 if (!msg)
5565 return -ENOMEM;
5566
5567 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
5568 DEVLINK_CMD_PARAM_GET,
5569 info->snd_portid, info->snd_seq, 0);
5570 if (err) {
5571 nlmsg_free(msg);
5572 return err;
5573 }
5574
5575 return genlmsg_reply(msg, info);
5576 }
5577
__devlink_nl_cmd_param_set_doit(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,struct genl_info * info,enum devlink_command cmd)5578 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
5579 unsigned int port_index,
5580 struct list_head *param_list,
5581 struct genl_info *info,
5582 enum devlink_command cmd)
5583 {
5584 enum devlink_param_type param_type;
5585 struct devlink_param_gset_ctx ctx;
5586 enum devlink_param_cmode cmode;
5587 struct devlink_param_item *param_item;
5588 const struct devlink_param *param;
5589 union devlink_param_value value;
5590 int err = 0;
5591
5592 param_item = devlink_param_get_from_info(param_list, info);
5593 if (!param_item)
5594 return -EINVAL;
5595 param = param_item->param;
5596 err = devlink_param_type_get_from_info(info, ¶m_type);
5597 if (err)
5598 return err;
5599 if (param_type != param->type)
5600 return -EINVAL;
5601 err = devlink_param_value_get_from_info(param, info, &value);
5602 if (err)
5603 return err;
5604 if (param->validate) {
5605 err = param->validate(devlink, param->id, value, info->extack);
5606 if (err)
5607 return err;
5608 }
5609
5610 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
5611 return -EINVAL;
5612 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
5613 if (!devlink_param_cmode_is_supported(param, cmode))
5614 return -EOPNOTSUPP;
5615
5616 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
5617 if (param->type == DEVLINK_PARAM_TYPE_STRING)
5618 strcpy(param_item->driverinit_value.vstr, value.vstr);
5619 else
5620 param_item->driverinit_value = value;
5621 param_item->driverinit_value_valid = true;
5622 } else {
5623 if (!param->set)
5624 return -EOPNOTSUPP;
5625 ctx.val = value;
5626 ctx.cmode = cmode;
5627 err = devlink_param_set(devlink, param, &ctx);
5628 if (err)
5629 return err;
5630 }
5631
5632 devlink_param_notify(devlink, port_index, param_item, cmd);
5633 return 0;
5634 }
5635
devlink_nl_cmd_param_set_doit(struct sk_buff * skb,struct genl_info * info)5636 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
5637 struct genl_info *info)
5638 {
5639 struct devlink *devlink = info->user_ptr[0];
5640
5641 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
5642 info, DEVLINK_CMD_PARAM_NEW);
5643 }
5644
devlink_nl_cmd_port_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)5645 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
5646 struct netlink_callback *cb)
5647 {
5648 NL_SET_ERR_MSG_MOD(cb->extack, "Port params are not supported");
5649 return msg->len;
5650 }
5651
devlink_nl_cmd_port_param_get_doit(struct sk_buff * skb,struct genl_info * info)5652 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
5653 struct genl_info *info)
5654 {
5655 NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
5656 return -EINVAL;
5657 }
5658
devlink_nl_cmd_port_param_set_doit(struct sk_buff * skb,struct genl_info * info)5659 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
5660 struct genl_info *info)
5661 {
5662 NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
5663 return -EINVAL;
5664 }
5665
devlink_nl_region_snapshot_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_snapshot * snapshot)5666 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
5667 struct devlink *devlink,
5668 struct devlink_snapshot *snapshot)
5669 {
5670 struct nlattr *snap_attr;
5671 int err;
5672
5673 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
5674 if (!snap_attr)
5675 return -EINVAL;
5676
5677 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
5678 if (err)
5679 goto nla_put_failure;
5680
5681 nla_nest_end(msg, snap_attr);
5682 return 0;
5683
5684 nla_put_failure:
5685 nla_nest_cancel(msg, snap_attr);
5686 return err;
5687 }
5688
devlink_nl_region_snapshots_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_region * region)5689 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
5690 struct devlink *devlink,
5691 struct devlink_region *region)
5692 {
5693 struct devlink_snapshot *snapshot;
5694 struct nlattr *snapshots_attr;
5695 int err;
5696
5697 snapshots_attr = nla_nest_start_noflag(msg,
5698 DEVLINK_ATTR_REGION_SNAPSHOTS);
5699 if (!snapshots_attr)
5700 return -EINVAL;
5701
5702 list_for_each_entry(snapshot, ®ion->snapshot_list, list) {
5703 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
5704 if (err)
5705 goto nla_put_failure;
5706 }
5707
5708 nla_nest_end(msg, snapshots_attr);
5709 return 0;
5710
5711 nla_put_failure:
5712 nla_nest_cancel(msg, snapshots_attr);
5713 return err;
5714 }
5715
devlink_nl_region_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct devlink_region * region)5716 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
5717 enum devlink_command cmd, u32 portid,
5718 u32 seq, int flags,
5719 struct devlink_region *region)
5720 {
5721 void *hdr;
5722 int err;
5723
5724 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5725 if (!hdr)
5726 return -EMSGSIZE;
5727
5728 err = devlink_nl_put_handle(msg, devlink);
5729 if (err)
5730 goto nla_put_failure;
5731
5732 if (region->port) {
5733 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
5734 region->port->index);
5735 if (err)
5736 goto nla_put_failure;
5737 }
5738
5739 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
5740 if (err)
5741 goto nla_put_failure;
5742
5743 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
5744 region->size,
5745 DEVLINK_ATTR_PAD);
5746 if (err)
5747 goto nla_put_failure;
5748
5749 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
5750 region->max_snapshots);
5751 if (err)
5752 goto nla_put_failure;
5753
5754 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
5755 if (err)
5756 goto nla_put_failure;
5757
5758 genlmsg_end(msg, hdr);
5759 return 0;
5760
5761 nla_put_failure:
5762 genlmsg_cancel(msg, hdr);
5763 return err;
5764 }
5765
5766 static struct sk_buff *
devlink_nl_region_notify_build(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd,u32 portid,u32 seq)5767 devlink_nl_region_notify_build(struct devlink_region *region,
5768 struct devlink_snapshot *snapshot,
5769 enum devlink_command cmd, u32 portid, u32 seq)
5770 {
5771 struct devlink *devlink = region->devlink;
5772 struct sk_buff *msg;
5773 void *hdr;
5774 int err;
5775
5776
5777 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5778 if (!msg)
5779 return ERR_PTR(-ENOMEM);
5780
5781 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
5782 if (!hdr) {
5783 err = -EMSGSIZE;
5784 goto out_free_msg;
5785 }
5786
5787 err = devlink_nl_put_handle(msg, devlink);
5788 if (err)
5789 goto out_cancel_msg;
5790
5791 if (region->port) {
5792 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
5793 region->port->index);
5794 if (err)
5795 goto out_cancel_msg;
5796 }
5797
5798 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
5799 region->ops->name);
5800 if (err)
5801 goto out_cancel_msg;
5802
5803 if (snapshot) {
5804 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
5805 snapshot->id);
5806 if (err)
5807 goto out_cancel_msg;
5808 } else {
5809 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
5810 region->size, DEVLINK_ATTR_PAD);
5811 if (err)
5812 goto out_cancel_msg;
5813 }
5814 genlmsg_end(msg, hdr);
5815
5816 return msg;
5817
5818 out_cancel_msg:
5819 genlmsg_cancel(msg, hdr);
5820 out_free_msg:
5821 nlmsg_free(msg);
5822 return ERR_PTR(err);
5823 }
5824
devlink_nl_region_notify(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd)5825 static void devlink_nl_region_notify(struct devlink_region *region,
5826 struct devlink_snapshot *snapshot,
5827 enum devlink_command cmd)
5828 {
5829 struct devlink *devlink = region->devlink;
5830 struct sk_buff *msg;
5831
5832 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
5833 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
5834 return;
5835
5836 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
5837 if (IS_ERR(msg))
5838 return;
5839
5840 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
5841 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
5842 }
5843
5844 /**
5845 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
5846 * @devlink: devlink instance
5847 * @id: the snapshot id
5848 *
5849 * Track when a new snapshot begins using an id. Load the count for the
5850 * given id from the snapshot xarray, increment it, and store it back.
5851 *
5852 * Called when a new snapshot is created with the given id.
5853 *
5854 * The id *must* have been previously allocated by
5855 * devlink_region_snapshot_id_get().
5856 *
5857 * Returns 0 on success, or an error on failure.
5858 */
__devlink_snapshot_id_increment(struct devlink * devlink,u32 id)5859 static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
5860 {
5861 unsigned long count;
5862 void *p;
5863 int err;
5864
5865 xa_lock(&devlink->snapshot_ids);
5866 p = xa_load(&devlink->snapshot_ids, id);
5867 if (WARN_ON(!p)) {
5868 err = -EINVAL;
5869 goto unlock;
5870 }
5871
5872 if (WARN_ON(!xa_is_value(p))) {
5873 err = -EINVAL;
5874 goto unlock;
5875 }
5876
5877 count = xa_to_value(p);
5878 count++;
5879
5880 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
5881 GFP_ATOMIC));
5882 unlock:
5883 xa_unlock(&devlink->snapshot_ids);
5884 return err;
5885 }
5886
5887 /**
5888 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
5889 * @devlink: devlink instance
5890 * @id: the snapshot id
5891 *
5892 * Track when a snapshot is deleted and stops using an id. Load the count
5893 * for the given id from the snapshot xarray, decrement it, and store it
5894 * back.
5895 *
5896 * If the count reaches zero, erase this id from the xarray, freeing it
5897 * up for future re-use by devlink_region_snapshot_id_get().
5898 *
5899 * Called when a snapshot using the given id is deleted, and when the
5900 * initial allocator of the id is finished using it.
5901 */
__devlink_snapshot_id_decrement(struct devlink * devlink,u32 id)5902 static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
5903 {
5904 unsigned long count;
5905 void *p;
5906
5907 xa_lock(&devlink->snapshot_ids);
5908 p = xa_load(&devlink->snapshot_ids, id);
5909 if (WARN_ON(!p))
5910 goto unlock;
5911
5912 if (WARN_ON(!xa_is_value(p)))
5913 goto unlock;
5914
5915 count = xa_to_value(p);
5916
5917 if (count > 1) {
5918 count--;
5919 __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
5920 GFP_ATOMIC);
5921 } else {
5922 /* If this was the last user, we can erase this id */
5923 __xa_erase(&devlink->snapshot_ids, id);
5924 }
5925 unlock:
5926 xa_unlock(&devlink->snapshot_ids);
5927 }
5928
5929 /**
5930 * __devlink_snapshot_id_insert - Insert a specific snapshot ID
5931 * @devlink: devlink instance
5932 * @id: the snapshot id
5933 *
5934 * Mark the given snapshot id as used by inserting a zero value into the
5935 * snapshot xarray.
5936 *
5937 * This must be called while holding the devlink instance lock. Unlike
5938 * devlink_snapshot_id_get, the initial reference count is zero, not one.
5939 * It is expected that the id will immediately be used before
5940 * releasing the devlink instance lock.
5941 *
5942 * Returns zero on success, or an error code if the snapshot id could not
5943 * be inserted.
5944 */
__devlink_snapshot_id_insert(struct devlink * devlink,u32 id)5945 static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
5946 {
5947 int err;
5948
5949 xa_lock(&devlink->snapshot_ids);
5950 if (xa_load(&devlink->snapshot_ids, id)) {
5951 xa_unlock(&devlink->snapshot_ids);
5952 return -EEXIST;
5953 }
5954 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
5955 GFP_ATOMIC));
5956 xa_unlock(&devlink->snapshot_ids);
5957 return err;
5958 }
5959
5960 /**
5961 * __devlink_region_snapshot_id_get - get snapshot ID
5962 * @devlink: devlink instance
5963 * @id: storage to return snapshot id
5964 *
5965 * Allocates a new snapshot id. Returns zero on success, or a negative
5966 * error on failure. Must be called while holding the devlink instance
5967 * lock.
5968 *
5969 * Snapshot IDs are tracked using an xarray which stores the number of
5970 * users of the snapshot id.
5971 *
5972 * Note that the caller of this function counts as a 'user', in order to
5973 * avoid race conditions. The caller must release its hold on the
5974 * snapshot by using devlink_region_snapshot_id_put.
5975 */
__devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)5976 static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
5977 {
5978 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
5979 xa_limit_32b, GFP_KERNEL);
5980 }
5981
5982 /**
5983 * __devlink_region_snapshot_create - create a new snapshot
5984 * This will add a new snapshot of a region. The snapshot
5985 * will be stored on the region struct and can be accessed
5986 * from devlink. This is useful for future analyses of snapshots.
5987 * Multiple snapshots can be created on a region.
5988 * The @snapshot_id should be obtained using the getter function.
5989 *
5990 * Must be called only while holding the region snapshot lock.
5991 *
5992 * @region: devlink region of the snapshot
5993 * @data: snapshot data
5994 * @snapshot_id: snapshot id to be created
5995 */
5996 static int
__devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)5997 __devlink_region_snapshot_create(struct devlink_region *region,
5998 u8 *data, u32 snapshot_id)
5999 {
6000 struct devlink *devlink = region->devlink;
6001 struct devlink_snapshot *snapshot;
6002 int err;
6003
6004 lockdep_assert_held(®ion->snapshot_lock);
6005
6006 /* check if region can hold one more snapshot */
6007 if (region->cur_snapshots == region->max_snapshots)
6008 return -ENOSPC;
6009
6010 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
6011 return -EEXIST;
6012
6013 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
6014 if (!snapshot)
6015 return -ENOMEM;
6016
6017 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
6018 if (err)
6019 goto err_snapshot_id_increment;
6020
6021 snapshot->id = snapshot_id;
6022 snapshot->region = region;
6023 snapshot->data = data;
6024
6025 list_add_tail(&snapshot->list, ®ion->snapshot_list);
6026
6027 region->cur_snapshots++;
6028
6029 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
6030 return 0;
6031
6032 err_snapshot_id_increment:
6033 kfree(snapshot);
6034 return err;
6035 }
6036
devlink_region_snapshot_del(struct devlink_region * region,struct devlink_snapshot * snapshot)6037 static void devlink_region_snapshot_del(struct devlink_region *region,
6038 struct devlink_snapshot *snapshot)
6039 {
6040 struct devlink *devlink = region->devlink;
6041
6042 lockdep_assert_held(®ion->snapshot_lock);
6043
6044 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
6045 region->cur_snapshots--;
6046 list_del(&snapshot->list);
6047 region->ops->destructor(snapshot->data);
6048 __devlink_snapshot_id_decrement(devlink, snapshot->id);
6049 kfree(snapshot);
6050 }
6051
devlink_nl_cmd_region_get_doit(struct sk_buff * skb,struct genl_info * info)6052 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
6053 struct genl_info *info)
6054 {
6055 struct devlink *devlink = info->user_ptr[0];
6056 struct devlink_port *port = NULL;
6057 struct devlink_region *region;
6058 const char *region_name;
6059 struct sk_buff *msg;
6060 unsigned int index;
6061 int err;
6062
6063 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
6064 return -EINVAL;
6065
6066 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6067 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6068
6069 port = devlink_port_get_by_index(devlink, index);
6070 if (!port)
6071 return -ENODEV;
6072 }
6073
6074 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
6075 if (port)
6076 region = devlink_port_region_get_by_name(port, region_name);
6077 else
6078 region = devlink_region_get_by_name(devlink, region_name);
6079
6080 if (!region)
6081 return -EINVAL;
6082
6083 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6084 if (!msg)
6085 return -ENOMEM;
6086
6087 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
6088 info->snd_portid, info->snd_seq, 0,
6089 region);
6090 if (err) {
6091 nlmsg_free(msg);
6092 return err;
6093 }
6094
6095 return genlmsg_reply(msg, info);
6096 }
6097
devlink_nl_cmd_region_get_port_dumpit(struct sk_buff * msg,struct netlink_callback * cb,struct devlink_port * port,int * idx,int start)6098 static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
6099 struct netlink_callback *cb,
6100 struct devlink_port *port,
6101 int *idx,
6102 int start)
6103 {
6104 struct devlink_region *region;
6105 int err = 0;
6106
6107 list_for_each_entry(region, &port->region_list, list) {
6108 if (*idx < start) {
6109 (*idx)++;
6110 continue;
6111 }
6112 err = devlink_nl_region_fill(msg, port->devlink,
6113 DEVLINK_CMD_REGION_GET,
6114 NETLINK_CB(cb->skb).portid,
6115 cb->nlh->nlmsg_seq,
6116 NLM_F_MULTI, region);
6117 if (err)
6118 goto out;
6119 (*idx)++;
6120 }
6121
6122 out:
6123 return err;
6124 }
6125
devlink_nl_cmd_region_get_devlink_dumpit(struct sk_buff * msg,struct netlink_callback * cb,struct devlink * devlink,int * idx,int start)6126 static int devlink_nl_cmd_region_get_devlink_dumpit(struct sk_buff *msg,
6127 struct netlink_callback *cb,
6128 struct devlink *devlink,
6129 int *idx,
6130 int start)
6131 {
6132 struct devlink_region *region;
6133 struct devlink_port *port;
6134 int err = 0;
6135
6136 devl_lock(devlink);
6137 list_for_each_entry(region, &devlink->region_list, list) {
6138 if (*idx < start) {
6139 (*idx)++;
6140 continue;
6141 }
6142 err = devlink_nl_region_fill(msg, devlink,
6143 DEVLINK_CMD_REGION_GET,
6144 NETLINK_CB(cb->skb).portid,
6145 cb->nlh->nlmsg_seq,
6146 NLM_F_MULTI, region);
6147 if (err)
6148 goto out;
6149 (*idx)++;
6150 }
6151
6152 list_for_each_entry(port, &devlink->port_list, list) {
6153 err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, idx,
6154 start);
6155 if (err)
6156 goto out;
6157 }
6158
6159 out:
6160 devl_unlock(devlink);
6161 return err;
6162 }
6163
devlink_nl_cmd_region_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)6164 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
6165 struct netlink_callback *cb)
6166 {
6167 struct devlink *devlink;
6168 int start = cb->args[0];
6169 unsigned long index;
6170 int idx = 0;
6171 int err = 0;
6172
6173 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
6174 err = devlink_nl_cmd_region_get_devlink_dumpit(msg, cb, devlink,
6175 &idx, start);
6176 devlink_put(devlink);
6177 if (err)
6178 goto out;
6179 }
6180 out:
6181 cb->args[0] = idx;
6182 return msg->len;
6183 }
6184
devlink_nl_cmd_region_del(struct sk_buff * skb,struct genl_info * info)6185 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
6186 struct genl_info *info)
6187 {
6188 struct devlink *devlink = info->user_ptr[0];
6189 struct devlink_snapshot *snapshot;
6190 struct devlink_port *port = NULL;
6191 struct devlink_region *region;
6192 const char *region_name;
6193 unsigned int index;
6194 u32 snapshot_id;
6195
6196 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
6197 GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
6198 return -EINVAL;
6199
6200 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
6201 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
6202
6203 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6204 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6205
6206 port = devlink_port_get_by_index(devlink, index);
6207 if (!port)
6208 return -ENODEV;
6209 }
6210
6211 if (port)
6212 region = devlink_port_region_get_by_name(port, region_name);
6213 else
6214 region = devlink_region_get_by_name(devlink, region_name);
6215
6216 if (!region)
6217 return -EINVAL;
6218
6219 mutex_lock(®ion->snapshot_lock);
6220 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
6221 if (!snapshot) {
6222 mutex_unlock(®ion->snapshot_lock);
6223 return -EINVAL;
6224 }
6225
6226 devlink_region_snapshot_del(region, snapshot);
6227 mutex_unlock(®ion->snapshot_lock);
6228 return 0;
6229 }
6230
6231 static int
devlink_nl_cmd_region_new(struct sk_buff * skb,struct genl_info * info)6232 devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
6233 {
6234 struct devlink *devlink = info->user_ptr[0];
6235 struct devlink_snapshot *snapshot;
6236 struct devlink_port *port = NULL;
6237 struct nlattr *snapshot_id_attr;
6238 struct devlink_region *region;
6239 const char *region_name;
6240 unsigned int index;
6241 u32 snapshot_id;
6242 u8 *data;
6243 int err;
6244
6245 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
6246 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
6247 return -EINVAL;
6248 }
6249
6250 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
6251
6252 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6253 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6254
6255 port = devlink_port_get_by_index(devlink, index);
6256 if (!port)
6257 return -ENODEV;
6258 }
6259
6260 if (port)
6261 region = devlink_port_region_get_by_name(port, region_name);
6262 else
6263 region = devlink_region_get_by_name(devlink, region_name);
6264
6265 if (!region) {
6266 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist");
6267 return -EINVAL;
6268 }
6269
6270 if (!region->ops->snapshot) {
6271 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot");
6272 return -EOPNOTSUPP;
6273 }
6274
6275 mutex_lock(®ion->snapshot_lock);
6276
6277 if (region->cur_snapshots == region->max_snapshots) {
6278 NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots");
6279 err = -ENOSPC;
6280 goto unlock;
6281 }
6282
6283 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
6284 if (snapshot_id_attr) {
6285 snapshot_id = nla_get_u32(snapshot_id_attr);
6286
6287 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
6288 NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use");
6289 err = -EEXIST;
6290 goto unlock;
6291 }
6292
6293 err = __devlink_snapshot_id_insert(devlink, snapshot_id);
6294 if (err)
6295 goto unlock;
6296 } else {
6297 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
6298 if (err) {
6299 NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id");
6300 goto unlock;
6301 }
6302 }
6303
6304 if (port)
6305 err = region->port_ops->snapshot(port, region->port_ops,
6306 info->extack, &data);
6307 else
6308 err = region->ops->snapshot(devlink, region->ops,
6309 info->extack, &data);
6310 if (err)
6311 goto err_snapshot_capture;
6312
6313 err = __devlink_region_snapshot_create(region, data, snapshot_id);
6314 if (err)
6315 goto err_snapshot_create;
6316
6317 if (!snapshot_id_attr) {
6318 struct sk_buff *msg;
6319
6320 snapshot = devlink_region_snapshot_get_by_id(region,
6321 snapshot_id);
6322 if (WARN_ON(!snapshot)) {
6323 err = -EINVAL;
6324 goto unlock;
6325 }
6326
6327 msg = devlink_nl_region_notify_build(region, snapshot,
6328 DEVLINK_CMD_REGION_NEW,
6329 info->snd_portid,
6330 info->snd_seq);
6331 err = PTR_ERR_OR_ZERO(msg);
6332 if (err)
6333 goto err_notify;
6334
6335 err = genlmsg_reply(msg, info);
6336 if (err)
6337 goto err_notify;
6338 }
6339
6340 mutex_unlock(®ion->snapshot_lock);
6341 return 0;
6342
6343 err_snapshot_create:
6344 region->ops->destructor(data);
6345 err_snapshot_capture:
6346 __devlink_snapshot_id_decrement(devlink, snapshot_id);
6347 mutex_unlock(®ion->snapshot_lock);
6348 return err;
6349
6350 err_notify:
6351 devlink_region_snapshot_del(region, snapshot);
6352 unlock:
6353 mutex_unlock(®ion->snapshot_lock);
6354 return err;
6355 }
6356
devlink_nl_cmd_region_read_chunk_fill(struct sk_buff * msg,struct devlink * devlink,u8 * chunk,u32 chunk_size,u64 addr)6357 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
6358 struct devlink *devlink,
6359 u8 *chunk, u32 chunk_size,
6360 u64 addr)
6361 {
6362 struct nlattr *chunk_attr;
6363 int err;
6364
6365 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
6366 if (!chunk_attr)
6367 return -EINVAL;
6368
6369 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
6370 if (err)
6371 goto nla_put_failure;
6372
6373 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
6374 DEVLINK_ATTR_PAD);
6375 if (err)
6376 goto nla_put_failure;
6377
6378 nla_nest_end(msg, chunk_attr);
6379 return 0;
6380
6381 nla_put_failure:
6382 nla_nest_cancel(msg, chunk_attr);
6383 return err;
6384 }
6385
6386 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
6387
devlink_nl_region_read_snapshot_fill(struct sk_buff * skb,struct devlink * devlink,struct devlink_region * region,struct nlattr ** attrs,u64 start_offset,u64 end_offset,u64 * new_offset)6388 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
6389 struct devlink *devlink,
6390 struct devlink_region *region,
6391 struct nlattr **attrs,
6392 u64 start_offset,
6393 u64 end_offset,
6394 u64 *new_offset)
6395 {
6396 struct devlink_snapshot *snapshot;
6397 u64 curr_offset = start_offset;
6398 u32 snapshot_id;
6399 int err = 0;
6400
6401 *new_offset = start_offset;
6402
6403 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
6404 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
6405 if (!snapshot)
6406 return -EINVAL;
6407
6408 while (curr_offset < end_offset) {
6409 u32 data_size;
6410 u8 *data;
6411
6412 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
6413 data_size = end_offset - curr_offset;
6414 else
6415 data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
6416
6417 data = &snapshot->data[curr_offset];
6418 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
6419 data, data_size,
6420 curr_offset);
6421 if (err)
6422 break;
6423
6424 curr_offset += data_size;
6425 }
6426 *new_offset = curr_offset;
6427
6428 return err;
6429 }
6430
devlink_nl_cmd_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)6431 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
6432 struct netlink_callback *cb)
6433 {
6434 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
6435 u64 ret_offset, start_offset, end_offset = U64_MAX;
6436 struct nlattr **attrs = info->attrs;
6437 struct devlink_port *port = NULL;
6438 struct devlink_region *region;
6439 struct nlattr *chunks_attr;
6440 const char *region_name;
6441 struct devlink *devlink;
6442 unsigned int index;
6443 void *hdr;
6444 int err;
6445
6446 start_offset = *((u64 *)&cb->args[0]);
6447
6448 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
6449 if (IS_ERR(devlink))
6450 return PTR_ERR(devlink);
6451
6452 devl_lock(devlink);
6453
6454 if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
6455 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
6456 err = -EINVAL;
6457 goto out_unlock;
6458 }
6459
6460 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6461 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6462
6463 port = devlink_port_get_by_index(devlink, index);
6464 if (!port) {
6465 err = -ENODEV;
6466 goto out_unlock;
6467 }
6468 }
6469
6470 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
6471
6472 if (port)
6473 region = devlink_port_region_get_by_name(port, region_name);
6474 else
6475 region = devlink_region_get_by_name(devlink, region_name);
6476
6477 if (!region) {
6478 err = -EINVAL;
6479 goto out_unlock;
6480 }
6481
6482 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
6483 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
6484 if (!start_offset)
6485 start_offset =
6486 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
6487
6488 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
6489 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
6490 }
6491
6492 if (end_offset > region->size)
6493 end_offset = region->size;
6494
6495 /* return 0 if there is no further data to read */
6496 if (start_offset == end_offset) {
6497 err = 0;
6498 goto out_unlock;
6499 }
6500
6501 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
6502 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
6503 DEVLINK_CMD_REGION_READ);
6504 if (!hdr) {
6505 err = -EMSGSIZE;
6506 goto out_unlock;
6507 }
6508
6509 err = devlink_nl_put_handle(skb, devlink);
6510 if (err)
6511 goto nla_put_failure;
6512
6513 if (region->port) {
6514 err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
6515 region->port->index);
6516 if (err)
6517 goto nla_put_failure;
6518 }
6519
6520 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
6521 if (err)
6522 goto nla_put_failure;
6523
6524 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
6525 if (!chunks_attr) {
6526 err = -EMSGSIZE;
6527 goto nla_put_failure;
6528 }
6529
6530 err = devlink_nl_region_read_snapshot_fill(skb, devlink,
6531 region, attrs,
6532 start_offset,
6533 end_offset, &ret_offset);
6534
6535 if (err && err != -EMSGSIZE)
6536 goto nla_put_failure;
6537
6538 /* Check if there was any progress done to prevent infinite loop */
6539 if (ret_offset == start_offset) {
6540 err = -EINVAL;
6541 goto nla_put_failure;
6542 }
6543
6544 *((u64 *)&cb->args[0]) = ret_offset;
6545
6546 nla_nest_end(skb, chunks_attr);
6547 genlmsg_end(skb, hdr);
6548 devl_unlock(devlink);
6549 devlink_put(devlink);
6550 return skb->len;
6551
6552 nla_put_failure:
6553 genlmsg_cancel(skb, hdr);
6554 out_unlock:
6555 devl_unlock(devlink);
6556 devlink_put(devlink);
6557 return err;
6558 }
6559
devlink_info_driver_name_put(struct devlink_info_req * req,const char * name)6560 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
6561 {
6562 if (!req->msg)
6563 return 0;
6564 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
6565 }
6566 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
6567
devlink_info_serial_number_put(struct devlink_info_req * req,const char * sn)6568 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
6569 {
6570 if (!req->msg)
6571 return 0;
6572 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
6573 }
6574 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
6575
devlink_info_board_serial_number_put(struct devlink_info_req * req,const char * bsn)6576 int devlink_info_board_serial_number_put(struct devlink_info_req *req,
6577 const char *bsn)
6578 {
6579 if (!req->msg)
6580 return 0;
6581 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
6582 bsn);
6583 }
6584 EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
6585
devlink_info_version_put(struct devlink_info_req * req,int attr,const char * version_name,const char * version_value,enum devlink_info_version_type version_type)6586 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
6587 const char *version_name,
6588 const char *version_value,
6589 enum devlink_info_version_type version_type)
6590 {
6591 struct nlattr *nest;
6592 int err;
6593
6594 if (req->version_cb)
6595 req->version_cb(version_name, version_type,
6596 req->version_cb_priv);
6597
6598 if (!req->msg)
6599 return 0;
6600
6601 nest = nla_nest_start_noflag(req->msg, attr);
6602 if (!nest)
6603 return -EMSGSIZE;
6604
6605 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
6606 version_name);
6607 if (err)
6608 goto nla_put_failure;
6609
6610 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
6611 version_value);
6612 if (err)
6613 goto nla_put_failure;
6614
6615 nla_nest_end(req->msg, nest);
6616
6617 return 0;
6618
6619 nla_put_failure:
6620 nla_nest_cancel(req->msg, nest);
6621 return err;
6622 }
6623
devlink_info_version_fixed_put(struct devlink_info_req * req,const char * version_name,const char * version_value)6624 int devlink_info_version_fixed_put(struct devlink_info_req *req,
6625 const char *version_name,
6626 const char *version_value)
6627 {
6628 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
6629 version_name, version_value,
6630 DEVLINK_INFO_VERSION_TYPE_NONE);
6631 }
6632 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
6633
devlink_info_version_stored_put(struct devlink_info_req * req,const char * version_name,const char * version_value)6634 int devlink_info_version_stored_put(struct devlink_info_req *req,
6635 const char *version_name,
6636 const char *version_value)
6637 {
6638 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
6639 version_name, version_value,
6640 DEVLINK_INFO_VERSION_TYPE_NONE);
6641 }
6642 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
6643
devlink_info_version_stored_put_ext(struct devlink_info_req * req,const char * version_name,const char * version_value,enum devlink_info_version_type version_type)6644 int devlink_info_version_stored_put_ext(struct devlink_info_req *req,
6645 const char *version_name,
6646 const char *version_value,
6647 enum devlink_info_version_type version_type)
6648 {
6649 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
6650 version_name, version_value,
6651 version_type);
6652 }
6653 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put_ext);
6654
devlink_info_version_running_put(struct devlink_info_req * req,const char * version_name,const char * version_value)6655 int devlink_info_version_running_put(struct devlink_info_req *req,
6656 const char *version_name,
6657 const char *version_value)
6658 {
6659 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
6660 version_name, version_value,
6661 DEVLINK_INFO_VERSION_TYPE_NONE);
6662 }
6663 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
6664
devlink_info_version_running_put_ext(struct devlink_info_req * req,const char * version_name,const char * version_value,enum devlink_info_version_type version_type)6665 int devlink_info_version_running_put_ext(struct devlink_info_req *req,
6666 const char *version_name,
6667 const char *version_value,
6668 enum devlink_info_version_type version_type)
6669 {
6670 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
6671 version_name, version_value,
6672 version_type);
6673 }
6674 EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
6675
6676 static int
devlink_nl_info_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)6677 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
6678 enum devlink_command cmd, u32 portid,
6679 u32 seq, int flags, struct netlink_ext_ack *extack)
6680 {
6681 struct devlink_info_req req = {};
6682 void *hdr;
6683 int err;
6684
6685 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6686 if (!hdr)
6687 return -EMSGSIZE;
6688
6689 err = -EMSGSIZE;
6690 if (devlink_nl_put_handle(msg, devlink))
6691 goto err_cancel_msg;
6692
6693 req.msg = msg;
6694 err = devlink->ops->info_get(devlink, &req, extack);
6695 if (err)
6696 goto err_cancel_msg;
6697
6698 genlmsg_end(msg, hdr);
6699 return 0;
6700
6701 err_cancel_msg:
6702 genlmsg_cancel(msg, hdr);
6703 return err;
6704 }
6705
devlink_nl_cmd_info_get_doit(struct sk_buff * skb,struct genl_info * info)6706 static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
6707 struct genl_info *info)
6708 {
6709 struct devlink *devlink = info->user_ptr[0];
6710 struct sk_buff *msg;
6711 int err;
6712
6713 if (!devlink->ops->info_get)
6714 return -EOPNOTSUPP;
6715
6716 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6717 if (!msg)
6718 return -ENOMEM;
6719
6720 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
6721 info->snd_portid, info->snd_seq, 0,
6722 info->extack);
6723 if (err) {
6724 nlmsg_free(msg);
6725 return err;
6726 }
6727
6728 return genlmsg_reply(msg, info);
6729 }
6730
devlink_nl_cmd_info_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)6731 static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
6732 struct netlink_callback *cb)
6733 {
6734 struct devlink *devlink;
6735 int start = cb->args[0];
6736 unsigned long index;
6737 int idx = 0;
6738 int err = 0;
6739
6740 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
6741 if (idx < start || !devlink->ops->info_get)
6742 goto inc;
6743
6744 devl_lock(devlink);
6745 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
6746 NETLINK_CB(cb->skb).portid,
6747 cb->nlh->nlmsg_seq, NLM_F_MULTI,
6748 cb->extack);
6749 devl_unlock(devlink);
6750 if (err == -EOPNOTSUPP)
6751 err = 0;
6752 else if (err) {
6753 devlink_put(devlink);
6754 break;
6755 }
6756 inc:
6757 idx++;
6758 devlink_put(devlink);
6759 }
6760
6761 if (err != -EMSGSIZE)
6762 return err;
6763
6764 cb->args[0] = idx;
6765 return msg->len;
6766 }
6767
6768 struct devlink_fmsg_item {
6769 struct list_head list;
6770 int attrtype;
6771 u8 nla_type;
6772 u16 len;
6773 int value[];
6774 };
6775
6776 struct devlink_fmsg {
6777 struct list_head item_list;
6778 bool putting_binary; /* This flag forces enclosing of binary data
6779 * in an array brackets. It forces using
6780 * of designated API:
6781 * devlink_fmsg_binary_pair_nest_start()
6782 * devlink_fmsg_binary_pair_nest_end()
6783 */
6784 };
6785
devlink_fmsg_alloc(void)6786 static struct devlink_fmsg *devlink_fmsg_alloc(void)
6787 {
6788 struct devlink_fmsg *fmsg;
6789
6790 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
6791 if (!fmsg)
6792 return NULL;
6793
6794 INIT_LIST_HEAD(&fmsg->item_list);
6795
6796 return fmsg;
6797 }
6798
devlink_fmsg_free(struct devlink_fmsg * fmsg)6799 static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
6800 {
6801 struct devlink_fmsg_item *item, *tmp;
6802
6803 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
6804 list_del(&item->list);
6805 kfree(item);
6806 }
6807 kfree(fmsg);
6808 }
6809
devlink_fmsg_nest_common(struct devlink_fmsg * fmsg,int attrtype)6810 static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
6811 int attrtype)
6812 {
6813 struct devlink_fmsg_item *item;
6814
6815 item = kzalloc(sizeof(*item), GFP_KERNEL);
6816 if (!item)
6817 return -ENOMEM;
6818
6819 item->attrtype = attrtype;
6820 list_add_tail(&item->list, &fmsg->item_list);
6821
6822 return 0;
6823 }
6824
devlink_fmsg_obj_nest_start(struct devlink_fmsg * fmsg)6825 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
6826 {
6827 if (fmsg->putting_binary)
6828 return -EINVAL;
6829
6830 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
6831 }
6832 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
6833
devlink_fmsg_nest_end(struct devlink_fmsg * fmsg)6834 static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
6835 {
6836 if (fmsg->putting_binary)
6837 return -EINVAL;
6838
6839 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
6840 }
6841
devlink_fmsg_obj_nest_end(struct devlink_fmsg * fmsg)6842 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
6843 {
6844 if (fmsg->putting_binary)
6845 return -EINVAL;
6846
6847 return devlink_fmsg_nest_end(fmsg);
6848 }
6849 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
6850
6851 #define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
6852
devlink_fmsg_put_name(struct devlink_fmsg * fmsg,const char * name)6853 static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
6854 {
6855 struct devlink_fmsg_item *item;
6856
6857 if (fmsg->putting_binary)
6858 return -EINVAL;
6859
6860 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
6861 return -EMSGSIZE;
6862
6863 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
6864 if (!item)
6865 return -ENOMEM;
6866
6867 item->nla_type = NLA_NUL_STRING;
6868 item->len = strlen(name) + 1;
6869 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
6870 memcpy(&item->value, name, item->len);
6871 list_add_tail(&item->list, &fmsg->item_list);
6872
6873 return 0;
6874 }
6875
devlink_fmsg_pair_nest_start(struct devlink_fmsg * fmsg,const char * name)6876 int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
6877 {
6878 int err;
6879
6880 if (fmsg->putting_binary)
6881 return -EINVAL;
6882
6883 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
6884 if (err)
6885 return err;
6886
6887 err = devlink_fmsg_put_name(fmsg, name);
6888 if (err)
6889 return err;
6890
6891 return 0;
6892 }
6893 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
6894
devlink_fmsg_pair_nest_end(struct devlink_fmsg * fmsg)6895 int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
6896 {
6897 if (fmsg->putting_binary)
6898 return -EINVAL;
6899
6900 return devlink_fmsg_nest_end(fmsg);
6901 }
6902 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
6903
devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg * fmsg,const char * name)6904 int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
6905 const char *name)
6906 {
6907 int err;
6908
6909 if (fmsg->putting_binary)
6910 return -EINVAL;
6911
6912 err = devlink_fmsg_pair_nest_start(fmsg, name);
6913 if (err)
6914 return err;
6915
6916 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
6917 if (err)
6918 return err;
6919
6920 return 0;
6921 }
6922 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
6923
devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg * fmsg)6924 int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
6925 {
6926 int err;
6927
6928 if (fmsg->putting_binary)
6929 return -EINVAL;
6930
6931 err = devlink_fmsg_nest_end(fmsg);
6932 if (err)
6933 return err;
6934
6935 err = devlink_fmsg_nest_end(fmsg);
6936 if (err)
6937 return err;
6938
6939 return 0;
6940 }
6941 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
6942
devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg * fmsg,const char * name)6943 int devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg *fmsg,
6944 const char *name)
6945 {
6946 int err;
6947
6948 err = devlink_fmsg_arr_pair_nest_start(fmsg, name);
6949 if (err)
6950 return err;
6951
6952 fmsg->putting_binary = true;
6953 return err;
6954 }
6955 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_start);
6956
devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg * fmsg)6957 int devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg *fmsg)
6958 {
6959 if (!fmsg->putting_binary)
6960 return -EINVAL;
6961
6962 fmsg->putting_binary = false;
6963 return devlink_fmsg_arr_pair_nest_end(fmsg);
6964 }
6965 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_end);
6966
devlink_fmsg_put_value(struct devlink_fmsg * fmsg,const void * value,u16 value_len,u8 value_nla_type)6967 static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
6968 const void *value, u16 value_len,
6969 u8 value_nla_type)
6970 {
6971 struct devlink_fmsg_item *item;
6972
6973 if (value_len > DEVLINK_FMSG_MAX_SIZE)
6974 return -EMSGSIZE;
6975
6976 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
6977 if (!item)
6978 return -ENOMEM;
6979
6980 item->nla_type = value_nla_type;
6981 item->len = value_len;
6982 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
6983 memcpy(&item->value, value, item->len);
6984 list_add_tail(&item->list, &fmsg->item_list);
6985
6986 return 0;
6987 }
6988
devlink_fmsg_bool_put(struct devlink_fmsg * fmsg,bool value)6989 static int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
6990 {
6991 if (fmsg->putting_binary)
6992 return -EINVAL;
6993
6994 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
6995 }
6996
devlink_fmsg_u8_put(struct devlink_fmsg * fmsg,u8 value)6997 static int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
6998 {
6999 if (fmsg->putting_binary)
7000 return -EINVAL;
7001
7002 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
7003 }
7004
devlink_fmsg_u32_put(struct devlink_fmsg * fmsg,u32 value)7005 int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
7006 {
7007 if (fmsg->putting_binary)
7008 return -EINVAL;
7009
7010 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
7011 }
7012 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
7013
devlink_fmsg_u64_put(struct devlink_fmsg * fmsg,u64 value)7014 static int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
7015 {
7016 if (fmsg->putting_binary)
7017 return -EINVAL;
7018
7019 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
7020 }
7021
devlink_fmsg_string_put(struct devlink_fmsg * fmsg,const char * value)7022 int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
7023 {
7024 if (fmsg->putting_binary)
7025 return -EINVAL;
7026
7027 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
7028 NLA_NUL_STRING);
7029 }
7030 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
7031
devlink_fmsg_binary_put(struct devlink_fmsg * fmsg,const void * value,u16 value_len)7032 int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
7033 u16 value_len)
7034 {
7035 if (!fmsg->putting_binary)
7036 return -EINVAL;
7037
7038 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
7039 }
7040 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
7041
devlink_fmsg_bool_pair_put(struct devlink_fmsg * fmsg,const char * name,bool value)7042 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
7043 bool value)
7044 {
7045 int err;
7046
7047 err = devlink_fmsg_pair_nest_start(fmsg, name);
7048 if (err)
7049 return err;
7050
7051 err = devlink_fmsg_bool_put(fmsg, value);
7052 if (err)
7053 return err;
7054
7055 err = devlink_fmsg_pair_nest_end(fmsg);
7056 if (err)
7057 return err;
7058
7059 return 0;
7060 }
7061 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
7062
devlink_fmsg_u8_pair_put(struct devlink_fmsg * fmsg,const char * name,u8 value)7063 int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
7064 u8 value)
7065 {
7066 int err;
7067
7068 err = devlink_fmsg_pair_nest_start(fmsg, name);
7069 if (err)
7070 return err;
7071
7072 err = devlink_fmsg_u8_put(fmsg, value);
7073 if (err)
7074 return err;
7075
7076 err = devlink_fmsg_pair_nest_end(fmsg);
7077 if (err)
7078 return err;
7079
7080 return 0;
7081 }
7082 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
7083
devlink_fmsg_u32_pair_put(struct devlink_fmsg * fmsg,const char * name,u32 value)7084 int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
7085 u32 value)
7086 {
7087 int err;
7088
7089 err = devlink_fmsg_pair_nest_start(fmsg, name);
7090 if (err)
7091 return err;
7092
7093 err = devlink_fmsg_u32_put(fmsg, value);
7094 if (err)
7095 return err;
7096
7097 err = devlink_fmsg_pair_nest_end(fmsg);
7098 if (err)
7099 return err;
7100
7101 return 0;
7102 }
7103 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
7104
devlink_fmsg_u64_pair_put(struct devlink_fmsg * fmsg,const char * name,u64 value)7105 int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
7106 u64 value)
7107 {
7108 int err;
7109
7110 err = devlink_fmsg_pair_nest_start(fmsg, name);
7111 if (err)
7112 return err;
7113
7114 err = devlink_fmsg_u64_put(fmsg, value);
7115 if (err)
7116 return err;
7117
7118 err = devlink_fmsg_pair_nest_end(fmsg);
7119 if (err)
7120 return err;
7121
7122 return 0;
7123 }
7124 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
7125
devlink_fmsg_string_pair_put(struct devlink_fmsg * fmsg,const char * name,const char * value)7126 int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
7127 const char *value)
7128 {
7129 int err;
7130
7131 err = devlink_fmsg_pair_nest_start(fmsg, name);
7132 if (err)
7133 return err;
7134
7135 err = devlink_fmsg_string_put(fmsg, value);
7136 if (err)
7137 return err;
7138
7139 err = devlink_fmsg_pair_nest_end(fmsg);
7140 if (err)
7141 return err;
7142
7143 return 0;
7144 }
7145 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
7146
devlink_fmsg_binary_pair_put(struct devlink_fmsg * fmsg,const char * name,const void * value,u32 value_len)7147 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
7148 const void *value, u32 value_len)
7149 {
7150 u32 data_size;
7151 int end_err;
7152 u32 offset;
7153 int err;
7154
7155 err = devlink_fmsg_binary_pair_nest_start(fmsg, name);
7156 if (err)
7157 return err;
7158
7159 for (offset = 0; offset < value_len; offset += data_size) {
7160 data_size = value_len - offset;
7161 if (data_size > DEVLINK_FMSG_MAX_SIZE)
7162 data_size = DEVLINK_FMSG_MAX_SIZE;
7163 err = devlink_fmsg_binary_put(fmsg, value + offset, data_size);
7164 if (err)
7165 break;
7166 /* Exit from loop with a break (instead of
7167 * return) to make sure putting_binary is turned off in
7168 * devlink_fmsg_binary_pair_nest_end
7169 */
7170 }
7171
7172 end_err = devlink_fmsg_binary_pair_nest_end(fmsg);
7173 if (end_err)
7174 err = end_err;
7175
7176 return err;
7177 }
7178 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
7179
7180 static int
devlink_fmsg_item_fill_type(struct devlink_fmsg_item * msg,struct sk_buff * skb)7181 devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
7182 {
7183 switch (msg->nla_type) {
7184 case NLA_FLAG:
7185 case NLA_U8:
7186 case NLA_U32:
7187 case NLA_U64:
7188 case NLA_NUL_STRING:
7189 case NLA_BINARY:
7190 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
7191 msg->nla_type);
7192 default:
7193 return -EINVAL;
7194 }
7195 }
7196
7197 static int
devlink_fmsg_item_fill_data(struct devlink_fmsg_item * msg,struct sk_buff * skb)7198 devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
7199 {
7200 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
7201 u8 tmp;
7202
7203 switch (msg->nla_type) {
7204 case NLA_FLAG:
7205 /* Always provide flag data, regardless of its value */
7206 tmp = *(bool *) msg->value;
7207
7208 return nla_put_u8(skb, attrtype, tmp);
7209 case NLA_U8:
7210 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
7211 case NLA_U32:
7212 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
7213 case NLA_U64:
7214 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
7215 DEVLINK_ATTR_PAD);
7216 case NLA_NUL_STRING:
7217 return nla_put_string(skb, attrtype, (char *) &msg->value);
7218 case NLA_BINARY:
7219 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
7220 default:
7221 return -EINVAL;
7222 }
7223 }
7224
7225 static int
devlink_fmsg_prepare_skb(struct devlink_fmsg * fmsg,struct sk_buff * skb,int * start)7226 devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
7227 int *start)
7228 {
7229 struct devlink_fmsg_item *item;
7230 struct nlattr *fmsg_nlattr;
7231 int i = 0;
7232 int err;
7233
7234 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
7235 if (!fmsg_nlattr)
7236 return -EMSGSIZE;
7237
7238 list_for_each_entry(item, &fmsg->item_list, list) {
7239 if (i < *start) {
7240 i++;
7241 continue;
7242 }
7243
7244 switch (item->attrtype) {
7245 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
7246 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
7247 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
7248 case DEVLINK_ATTR_FMSG_NEST_END:
7249 err = nla_put_flag(skb, item->attrtype);
7250 break;
7251 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
7252 err = devlink_fmsg_item_fill_type(item, skb);
7253 if (err)
7254 break;
7255 err = devlink_fmsg_item_fill_data(item, skb);
7256 break;
7257 case DEVLINK_ATTR_FMSG_OBJ_NAME:
7258 err = nla_put_string(skb, item->attrtype,
7259 (char *) &item->value);
7260 break;
7261 default:
7262 err = -EINVAL;
7263 break;
7264 }
7265 if (!err)
7266 *start = ++i;
7267 else
7268 break;
7269 }
7270
7271 nla_nest_end(skb, fmsg_nlattr);
7272 return err;
7273 }
7274
devlink_fmsg_snd(struct devlink_fmsg * fmsg,struct genl_info * info,enum devlink_command cmd,int flags)7275 static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
7276 struct genl_info *info,
7277 enum devlink_command cmd, int flags)
7278 {
7279 struct nlmsghdr *nlh;
7280 struct sk_buff *skb;
7281 bool last = false;
7282 int index = 0;
7283 void *hdr;
7284 int err;
7285
7286 while (!last) {
7287 int tmp_index = index;
7288
7289 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
7290 if (!skb)
7291 return -ENOMEM;
7292
7293 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
7294 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
7295 if (!hdr) {
7296 err = -EMSGSIZE;
7297 goto nla_put_failure;
7298 }
7299
7300 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
7301 if (!err)
7302 last = true;
7303 else if (err != -EMSGSIZE || tmp_index == index)
7304 goto nla_put_failure;
7305
7306 genlmsg_end(skb, hdr);
7307 err = genlmsg_reply(skb, info);
7308 if (err)
7309 return err;
7310 }
7311
7312 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
7313 if (!skb)
7314 return -ENOMEM;
7315 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
7316 NLMSG_DONE, 0, flags | NLM_F_MULTI);
7317 if (!nlh) {
7318 err = -EMSGSIZE;
7319 goto nla_put_failure;
7320 }
7321
7322 return genlmsg_reply(skb, info);
7323
7324 nla_put_failure:
7325 nlmsg_free(skb);
7326 return err;
7327 }
7328
devlink_fmsg_dumpit(struct devlink_fmsg * fmsg,struct sk_buff * skb,struct netlink_callback * cb,enum devlink_command cmd)7329 static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
7330 struct netlink_callback *cb,
7331 enum devlink_command cmd)
7332 {
7333 int index = cb->args[0];
7334 int tmp_index = index;
7335 void *hdr;
7336 int err;
7337
7338 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
7339 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
7340 if (!hdr) {
7341 err = -EMSGSIZE;
7342 goto nla_put_failure;
7343 }
7344
7345 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
7346 if ((err && err != -EMSGSIZE) || tmp_index == index)
7347 goto nla_put_failure;
7348
7349 cb->args[0] = index;
7350 genlmsg_end(skb, hdr);
7351 return skb->len;
7352
7353 nla_put_failure:
7354 genlmsg_cancel(skb, hdr);
7355 return err;
7356 }
7357
7358 struct devlink_health_reporter {
7359 struct list_head list;
7360 void *priv;
7361 const struct devlink_health_reporter_ops *ops;
7362 struct devlink *devlink;
7363 struct devlink_port *devlink_port;
7364 struct devlink_fmsg *dump_fmsg;
7365 struct mutex dump_lock; /* lock parallel read/write from dump buffers */
7366 u64 graceful_period;
7367 bool auto_recover;
7368 bool auto_dump;
7369 u8 health_state;
7370 u64 dump_ts;
7371 u64 dump_real_ts;
7372 u64 error_count;
7373 u64 recovery_count;
7374 u64 last_recovery_ts;
7375 refcount_t refcount;
7376 };
7377
7378 void *
devlink_health_reporter_priv(struct devlink_health_reporter * reporter)7379 devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
7380 {
7381 return reporter->priv;
7382 }
7383 EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
7384
7385 static struct devlink_health_reporter *
__devlink_health_reporter_find_by_name(struct list_head * reporter_list,struct mutex * list_lock,const char * reporter_name)7386 __devlink_health_reporter_find_by_name(struct list_head *reporter_list,
7387 struct mutex *list_lock,
7388 const char *reporter_name)
7389 {
7390 struct devlink_health_reporter *reporter;
7391
7392 lockdep_assert_held(list_lock);
7393 list_for_each_entry(reporter, reporter_list, list)
7394 if (!strcmp(reporter->ops->name, reporter_name))
7395 return reporter;
7396 return NULL;
7397 }
7398
7399 static struct devlink_health_reporter *
devlink_health_reporter_find_by_name(struct devlink * devlink,const char * reporter_name)7400 devlink_health_reporter_find_by_name(struct devlink *devlink,
7401 const char *reporter_name)
7402 {
7403 return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
7404 &devlink->reporters_lock,
7405 reporter_name);
7406 }
7407
7408 static struct devlink_health_reporter *
devlink_port_health_reporter_find_by_name(struct devlink_port * devlink_port,const char * reporter_name)7409 devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
7410 const char *reporter_name)
7411 {
7412 return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
7413 &devlink_port->reporters_lock,
7414 reporter_name);
7415 }
7416
7417 static struct devlink_health_reporter *
__devlink_health_reporter_create(struct devlink * devlink,const struct devlink_health_reporter_ops * ops,u64 graceful_period,void * priv)7418 __devlink_health_reporter_create(struct devlink *devlink,
7419 const struct devlink_health_reporter_ops *ops,
7420 u64 graceful_period, void *priv)
7421 {
7422 struct devlink_health_reporter *reporter;
7423
7424 if (WARN_ON(graceful_period && !ops->recover))
7425 return ERR_PTR(-EINVAL);
7426
7427 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
7428 if (!reporter)
7429 return ERR_PTR(-ENOMEM);
7430
7431 reporter->priv = priv;
7432 reporter->ops = ops;
7433 reporter->devlink = devlink;
7434 reporter->graceful_period = graceful_period;
7435 reporter->auto_recover = !!ops->recover;
7436 reporter->auto_dump = !!ops->dump;
7437 mutex_init(&reporter->dump_lock);
7438 refcount_set(&reporter->refcount, 1);
7439 return reporter;
7440 }
7441
7442 /**
7443 * devlink_port_health_reporter_create - create devlink health reporter for
7444 * specified port instance
7445 *
7446 * @port: devlink_port which should contain the new reporter
7447 * @ops: ops
7448 * @graceful_period: to avoid recovery loops, in msecs
7449 * @priv: priv
7450 */
7451 struct devlink_health_reporter *
devlink_port_health_reporter_create(struct devlink_port * port,const struct devlink_health_reporter_ops * ops,u64 graceful_period,void * priv)7452 devlink_port_health_reporter_create(struct devlink_port *port,
7453 const struct devlink_health_reporter_ops *ops,
7454 u64 graceful_period, void *priv)
7455 {
7456 struct devlink_health_reporter *reporter;
7457
7458 mutex_lock(&port->reporters_lock);
7459 if (__devlink_health_reporter_find_by_name(&port->reporter_list,
7460 &port->reporters_lock, ops->name)) {
7461 reporter = ERR_PTR(-EEXIST);
7462 goto unlock;
7463 }
7464
7465 reporter = __devlink_health_reporter_create(port->devlink, ops,
7466 graceful_period, priv);
7467 if (IS_ERR(reporter))
7468 goto unlock;
7469
7470 reporter->devlink_port = port;
7471 list_add_tail(&reporter->list, &port->reporter_list);
7472 unlock:
7473 mutex_unlock(&port->reporters_lock);
7474 return reporter;
7475 }
7476 EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
7477
7478 /**
7479 * devlink_health_reporter_create - create devlink health reporter
7480 *
7481 * @devlink: devlink
7482 * @ops: ops
7483 * @graceful_period: to avoid recovery loops, in msecs
7484 * @priv: priv
7485 */
7486 struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink * devlink,const struct devlink_health_reporter_ops * ops,u64 graceful_period,void * priv)7487 devlink_health_reporter_create(struct devlink *devlink,
7488 const struct devlink_health_reporter_ops *ops,
7489 u64 graceful_period, void *priv)
7490 {
7491 struct devlink_health_reporter *reporter;
7492
7493 mutex_lock(&devlink->reporters_lock);
7494 if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
7495 reporter = ERR_PTR(-EEXIST);
7496 goto unlock;
7497 }
7498
7499 reporter = __devlink_health_reporter_create(devlink, ops,
7500 graceful_period, priv);
7501 if (IS_ERR(reporter))
7502 goto unlock;
7503
7504 list_add_tail(&reporter->list, &devlink->reporter_list);
7505 unlock:
7506 mutex_unlock(&devlink->reporters_lock);
7507 return reporter;
7508 }
7509 EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
7510
7511 static void
devlink_health_reporter_free(struct devlink_health_reporter * reporter)7512 devlink_health_reporter_free(struct devlink_health_reporter *reporter)
7513 {
7514 mutex_destroy(&reporter->dump_lock);
7515 if (reporter->dump_fmsg)
7516 devlink_fmsg_free(reporter->dump_fmsg);
7517 kfree(reporter);
7518 }
7519
7520 static void
devlink_health_reporter_put(struct devlink_health_reporter * reporter)7521 devlink_health_reporter_put(struct devlink_health_reporter *reporter)
7522 {
7523 if (refcount_dec_and_test(&reporter->refcount))
7524 devlink_health_reporter_free(reporter);
7525 }
7526
7527 static void
__devlink_health_reporter_destroy(struct devlink_health_reporter * reporter)7528 __devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
7529 {
7530 list_del(&reporter->list);
7531 devlink_health_reporter_put(reporter);
7532 }
7533
7534 /**
7535 * devlink_health_reporter_destroy - destroy devlink health reporter
7536 *
7537 * @reporter: devlink health reporter to destroy
7538 */
7539 void
devlink_health_reporter_destroy(struct devlink_health_reporter * reporter)7540 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
7541 {
7542 struct mutex *lock = &reporter->devlink->reporters_lock;
7543
7544 mutex_lock(lock);
7545 __devlink_health_reporter_destroy(reporter);
7546 mutex_unlock(lock);
7547 }
7548 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
7549
7550 /**
7551 * devlink_port_health_reporter_destroy - destroy devlink port health reporter
7552 *
7553 * @reporter: devlink health reporter to destroy
7554 */
7555 void
devlink_port_health_reporter_destroy(struct devlink_health_reporter * reporter)7556 devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter)
7557 {
7558 struct mutex *lock = &reporter->devlink_port->reporters_lock;
7559
7560 mutex_lock(lock);
7561 __devlink_health_reporter_destroy(reporter);
7562 mutex_unlock(lock);
7563 }
7564 EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy);
7565
7566 static int
devlink_nl_health_reporter_fill(struct sk_buff * msg,struct devlink_health_reporter * reporter,enum devlink_command cmd,u32 portid,u32 seq,int flags)7567 devlink_nl_health_reporter_fill(struct sk_buff *msg,
7568 struct devlink_health_reporter *reporter,
7569 enum devlink_command cmd, u32 portid,
7570 u32 seq, int flags)
7571 {
7572 struct devlink *devlink = reporter->devlink;
7573 struct nlattr *reporter_attr;
7574 void *hdr;
7575
7576 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
7577 if (!hdr)
7578 return -EMSGSIZE;
7579
7580 if (devlink_nl_put_handle(msg, devlink))
7581 goto genlmsg_cancel;
7582
7583 if (reporter->devlink_port) {
7584 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, reporter->devlink_port->index))
7585 goto genlmsg_cancel;
7586 }
7587 reporter_attr = nla_nest_start_noflag(msg,
7588 DEVLINK_ATTR_HEALTH_REPORTER);
7589 if (!reporter_attr)
7590 goto genlmsg_cancel;
7591 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
7592 reporter->ops->name))
7593 goto reporter_nest_cancel;
7594 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
7595 reporter->health_state))
7596 goto reporter_nest_cancel;
7597 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
7598 reporter->error_count, DEVLINK_ATTR_PAD))
7599 goto reporter_nest_cancel;
7600 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
7601 reporter->recovery_count, DEVLINK_ATTR_PAD))
7602 goto reporter_nest_cancel;
7603 if (reporter->ops->recover &&
7604 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
7605 reporter->graceful_period,
7606 DEVLINK_ATTR_PAD))
7607 goto reporter_nest_cancel;
7608 if (reporter->ops->recover &&
7609 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
7610 reporter->auto_recover))
7611 goto reporter_nest_cancel;
7612 if (reporter->dump_fmsg &&
7613 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
7614 jiffies_to_msecs(reporter->dump_ts),
7615 DEVLINK_ATTR_PAD))
7616 goto reporter_nest_cancel;
7617 if (reporter->dump_fmsg &&
7618 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
7619 reporter->dump_real_ts, DEVLINK_ATTR_PAD))
7620 goto reporter_nest_cancel;
7621 if (reporter->ops->dump &&
7622 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP,
7623 reporter->auto_dump))
7624 goto reporter_nest_cancel;
7625
7626 nla_nest_end(msg, reporter_attr);
7627 genlmsg_end(msg, hdr);
7628 return 0;
7629
7630 reporter_nest_cancel:
7631 nla_nest_end(msg, reporter_attr);
7632 genlmsg_cancel:
7633 genlmsg_cancel(msg, hdr);
7634 return -EMSGSIZE;
7635 }
7636
devlink_recover_notify(struct devlink_health_reporter * reporter,enum devlink_command cmd)7637 static void devlink_recover_notify(struct devlink_health_reporter *reporter,
7638 enum devlink_command cmd)
7639 {
7640 struct devlink *devlink = reporter->devlink;
7641 struct sk_buff *msg;
7642 int err;
7643
7644 WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
7645 WARN_ON(!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED));
7646
7647 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7648 if (!msg)
7649 return;
7650
7651 err = devlink_nl_health_reporter_fill(msg, reporter, cmd, 0, 0, 0);
7652 if (err) {
7653 nlmsg_free(msg);
7654 return;
7655 }
7656
7657 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
7658 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7659 }
7660
7661 void
devlink_health_reporter_recovery_done(struct devlink_health_reporter * reporter)7662 devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
7663 {
7664 reporter->recovery_count++;
7665 reporter->last_recovery_ts = jiffies;
7666 }
7667 EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
7668
7669 static int
devlink_health_reporter_recover(struct devlink_health_reporter * reporter,void * priv_ctx,struct netlink_ext_ack * extack)7670 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
7671 void *priv_ctx, struct netlink_ext_ack *extack)
7672 {
7673 int err;
7674
7675 if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
7676 return 0;
7677
7678 if (!reporter->ops->recover)
7679 return -EOPNOTSUPP;
7680
7681 err = reporter->ops->recover(reporter, priv_ctx, extack);
7682 if (err)
7683 return err;
7684
7685 devlink_health_reporter_recovery_done(reporter);
7686 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
7687 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
7688
7689 return 0;
7690 }
7691
7692 static void
devlink_health_dump_clear(struct devlink_health_reporter * reporter)7693 devlink_health_dump_clear(struct devlink_health_reporter *reporter)
7694 {
7695 if (!reporter->dump_fmsg)
7696 return;
7697 devlink_fmsg_free(reporter->dump_fmsg);
7698 reporter->dump_fmsg = NULL;
7699 }
7700
devlink_health_do_dump(struct devlink_health_reporter * reporter,void * priv_ctx,struct netlink_ext_ack * extack)7701 static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
7702 void *priv_ctx,
7703 struct netlink_ext_ack *extack)
7704 {
7705 int err;
7706
7707 if (!reporter->ops->dump)
7708 return 0;
7709
7710 if (reporter->dump_fmsg)
7711 return 0;
7712
7713 reporter->dump_fmsg = devlink_fmsg_alloc();
7714 if (!reporter->dump_fmsg) {
7715 err = -ENOMEM;
7716 return err;
7717 }
7718
7719 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
7720 if (err)
7721 goto dump_err;
7722
7723 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
7724 priv_ctx, extack);
7725 if (err)
7726 goto dump_err;
7727
7728 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
7729 if (err)
7730 goto dump_err;
7731
7732 reporter->dump_ts = jiffies;
7733 reporter->dump_real_ts = ktime_get_real_ns();
7734
7735 return 0;
7736
7737 dump_err:
7738 devlink_health_dump_clear(reporter);
7739 return err;
7740 }
7741
devlink_health_report(struct devlink_health_reporter * reporter,const char * msg,void * priv_ctx)7742 int devlink_health_report(struct devlink_health_reporter *reporter,
7743 const char *msg, void *priv_ctx)
7744 {
7745 enum devlink_health_reporter_state prev_health_state;
7746 struct devlink *devlink = reporter->devlink;
7747 unsigned long recover_ts_threshold;
7748 int ret;
7749
7750 /* write a log message of the current error */
7751 WARN_ON(!msg);
7752 trace_devlink_health_report(devlink, reporter->ops->name, msg);
7753 reporter->error_count++;
7754 prev_health_state = reporter->health_state;
7755 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
7756 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
7757
7758 /* abort if the previous error wasn't recovered */
7759 recover_ts_threshold = reporter->last_recovery_ts +
7760 msecs_to_jiffies(reporter->graceful_period);
7761 if (reporter->auto_recover &&
7762 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
7763 (reporter->last_recovery_ts && reporter->recovery_count &&
7764 time_is_after_jiffies(recover_ts_threshold)))) {
7765 trace_devlink_health_recover_aborted(devlink,
7766 reporter->ops->name,
7767 reporter->health_state,
7768 jiffies -
7769 reporter->last_recovery_ts);
7770 return -ECANCELED;
7771 }
7772
7773 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
7774
7775 if (reporter->auto_dump) {
7776 mutex_lock(&reporter->dump_lock);
7777 /* store current dump of current error, for later analysis */
7778 devlink_health_do_dump(reporter, priv_ctx, NULL);
7779 mutex_unlock(&reporter->dump_lock);
7780 }
7781
7782 if (!reporter->auto_recover)
7783 return 0;
7784
7785 devl_lock(devlink);
7786 ret = devlink_health_reporter_recover(reporter, priv_ctx, NULL);
7787 devl_unlock(devlink);
7788
7789 return ret;
7790 }
7791 EXPORT_SYMBOL_GPL(devlink_health_report);
7792
7793 static struct devlink_health_reporter *
devlink_health_reporter_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)7794 devlink_health_reporter_get_from_attrs(struct devlink *devlink,
7795 struct nlattr **attrs)
7796 {
7797 struct devlink_health_reporter *reporter;
7798 struct devlink_port *devlink_port;
7799 char *reporter_name;
7800
7801 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
7802 return NULL;
7803
7804 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
7805 devlink_port = devlink_port_get_from_attrs(devlink, attrs);
7806 if (IS_ERR(devlink_port)) {
7807 mutex_lock(&devlink->reporters_lock);
7808 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
7809 if (reporter)
7810 refcount_inc(&reporter->refcount);
7811 mutex_unlock(&devlink->reporters_lock);
7812 } else {
7813 mutex_lock(&devlink_port->reporters_lock);
7814 reporter = devlink_port_health_reporter_find_by_name(devlink_port, reporter_name);
7815 if (reporter)
7816 refcount_inc(&reporter->refcount);
7817 mutex_unlock(&devlink_port->reporters_lock);
7818 }
7819
7820 return reporter;
7821 }
7822
7823 static struct devlink_health_reporter *
devlink_health_reporter_get_from_info(struct devlink * devlink,struct genl_info * info)7824 devlink_health_reporter_get_from_info(struct devlink *devlink,
7825 struct genl_info *info)
7826 {
7827 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
7828 }
7829
7830 static struct devlink_health_reporter *
devlink_health_reporter_get_from_cb(struct netlink_callback * cb)7831 devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
7832 {
7833 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
7834 struct devlink_health_reporter *reporter;
7835 struct nlattr **attrs = info->attrs;
7836 struct devlink *devlink;
7837
7838 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
7839 if (IS_ERR(devlink))
7840 return NULL;
7841
7842 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
7843 devlink_put(devlink);
7844 return reporter;
7845 }
7846
7847 void
devlink_health_reporter_state_update(struct devlink_health_reporter * reporter,enum devlink_health_reporter_state state)7848 devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
7849 enum devlink_health_reporter_state state)
7850 {
7851 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
7852 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
7853 return;
7854
7855 if (reporter->health_state == state)
7856 return;
7857
7858 reporter->health_state = state;
7859 trace_devlink_health_reporter_state_update(reporter->devlink,
7860 reporter->ops->name, state);
7861 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
7862 }
7863 EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
7864
devlink_nl_cmd_health_reporter_get_doit(struct sk_buff * skb,struct genl_info * info)7865 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
7866 struct genl_info *info)
7867 {
7868 struct devlink *devlink = info->user_ptr[0];
7869 struct devlink_health_reporter *reporter;
7870 struct sk_buff *msg;
7871 int err;
7872
7873 reporter = devlink_health_reporter_get_from_info(devlink, info);
7874 if (!reporter)
7875 return -EINVAL;
7876
7877 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7878 if (!msg) {
7879 err = -ENOMEM;
7880 goto out;
7881 }
7882
7883 err = devlink_nl_health_reporter_fill(msg, reporter,
7884 DEVLINK_CMD_HEALTH_REPORTER_GET,
7885 info->snd_portid, info->snd_seq,
7886 0);
7887 if (err) {
7888 nlmsg_free(msg);
7889 goto out;
7890 }
7891
7892 err = genlmsg_reply(msg, info);
7893 out:
7894 devlink_health_reporter_put(reporter);
7895 return err;
7896 }
7897
7898 static int
devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)7899 devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
7900 struct netlink_callback *cb)
7901 {
7902 struct devlink_health_reporter *reporter;
7903 struct devlink_port *port;
7904 struct devlink *devlink;
7905 int start = cb->args[0];
7906 unsigned long index;
7907 int idx = 0;
7908 int err;
7909
7910 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
7911 mutex_lock(&devlink->reporters_lock);
7912 list_for_each_entry(reporter, &devlink->reporter_list,
7913 list) {
7914 if (idx < start) {
7915 idx++;
7916 continue;
7917 }
7918 err = devlink_nl_health_reporter_fill(
7919 msg, reporter, DEVLINK_CMD_HEALTH_REPORTER_GET,
7920 NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
7921 NLM_F_MULTI);
7922 if (err) {
7923 mutex_unlock(&devlink->reporters_lock);
7924 devlink_put(devlink);
7925 goto out;
7926 }
7927 idx++;
7928 }
7929 mutex_unlock(&devlink->reporters_lock);
7930 devlink_put(devlink);
7931 }
7932
7933 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
7934 devl_lock(devlink);
7935 list_for_each_entry(port, &devlink->port_list, list) {
7936 mutex_lock(&port->reporters_lock);
7937 list_for_each_entry(reporter, &port->reporter_list, list) {
7938 if (idx < start) {
7939 idx++;
7940 continue;
7941 }
7942 err = devlink_nl_health_reporter_fill(
7943 msg, reporter,
7944 DEVLINK_CMD_HEALTH_REPORTER_GET,
7945 NETLINK_CB(cb->skb).portid,
7946 cb->nlh->nlmsg_seq, NLM_F_MULTI);
7947 if (err) {
7948 mutex_unlock(&port->reporters_lock);
7949 devl_unlock(devlink);
7950 devlink_put(devlink);
7951 goto out;
7952 }
7953 idx++;
7954 }
7955 mutex_unlock(&port->reporters_lock);
7956 }
7957 devl_unlock(devlink);
7958 devlink_put(devlink);
7959 }
7960 out:
7961 cb->args[0] = idx;
7962 return msg->len;
7963 }
7964
7965 static int
devlink_nl_cmd_health_reporter_set_doit(struct sk_buff * skb,struct genl_info * info)7966 devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
7967 struct genl_info *info)
7968 {
7969 struct devlink *devlink = info->user_ptr[0];
7970 struct devlink_health_reporter *reporter;
7971 int err;
7972
7973 reporter = devlink_health_reporter_get_from_info(devlink, info);
7974 if (!reporter)
7975 return -EINVAL;
7976
7977 if (!reporter->ops->recover &&
7978 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
7979 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
7980 err = -EOPNOTSUPP;
7981 goto out;
7982 }
7983 if (!reporter->ops->dump &&
7984 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) {
7985 err = -EOPNOTSUPP;
7986 goto out;
7987 }
7988
7989 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
7990 reporter->graceful_period =
7991 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
7992
7993 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
7994 reporter->auto_recover =
7995 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
7996
7997 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
7998 reporter->auto_dump =
7999 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
8000
8001 devlink_health_reporter_put(reporter);
8002 return 0;
8003 out:
8004 devlink_health_reporter_put(reporter);
8005 return err;
8006 }
8007
devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff * skb,struct genl_info * info)8008 static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
8009 struct genl_info *info)
8010 {
8011 struct devlink *devlink = info->user_ptr[0];
8012 struct devlink_health_reporter *reporter;
8013 int err;
8014
8015 reporter = devlink_health_reporter_get_from_info(devlink, info);
8016 if (!reporter)
8017 return -EINVAL;
8018
8019 err = devlink_health_reporter_recover(reporter, NULL, info->extack);
8020
8021 devlink_health_reporter_put(reporter);
8022 return err;
8023 }
8024
devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff * skb,struct genl_info * info)8025 static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
8026 struct genl_info *info)
8027 {
8028 struct devlink *devlink = info->user_ptr[0];
8029 struct devlink_health_reporter *reporter;
8030 struct devlink_fmsg *fmsg;
8031 int err;
8032
8033 reporter = devlink_health_reporter_get_from_info(devlink, info);
8034 if (!reporter)
8035 return -EINVAL;
8036
8037 if (!reporter->ops->diagnose) {
8038 devlink_health_reporter_put(reporter);
8039 return -EOPNOTSUPP;
8040 }
8041
8042 fmsg = devlink_fmsg_alloc();
8043 if (!fmsg) {
8044 devlink_health_reporter_put(reporter);
8045 return -ENOMEM;
8046 }
8047
8048 err = devlink_fmsg_obj_nest_start(fmsg);
8049 if (err)
8050 goto out;
8051
8052 err = reporter->ops->diagnose(reporter, fmsg, info->extack);
8053 if (err)
8054 goto out;
8055
8056 err = devlink_fmsg_obj_nest_end(fmsg);
8057 if (err)
8058 goto out;
8059
8060 err = devlink_fmsg_snd(fmsg, info,
8061 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
8062
8063 out:
8064 devlink_fmsg_free(fmsg);
8065 devlink_health_reporter_put(reporter);
8066 return err;
8067 }
8068
8069 static int
devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)8070 devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
8071 struct netlink_callback *cb)
8072 {
8073 struct devlink_health_reporter *reporter;
8074 u64 start = cb->args[0];
8075 int err;
8076
8077 reporter = devlink_health_reporter_get_from_cb(cb);
8078 if (!reporter)
8079 return -EINVAL;
8080
8081 if (!reporter->ops->dump) {
8082 err = -EOPNOTSUPP;
8083 goto out;
8084 }
8085 mutex_lock(&reporter->dump_lock);
8086 if (!start) {
8087 err = devlink_health_do_dump(reporter, NULL, cb->extack);
8088 if (err)
8089 goto unlock;
8090 cb->args[1] = reporter->dump_ts;
8091 }
8092 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
8093 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
8094 err = -EAGAIN;
8095 goto unlock;
8096 }
8097
8098 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
8099 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
8100 unlock:
8101 mutex_unlock(&reporter->dump_lock);
8102 out:
8103 devlink_health_reporter_put(reporter);
8104 return err;
8105 }
8106
8107 static int
devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff * skb,struct genl_info * info)8108 devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
8109 struct genl_info *info)
8110 {
8111 struct devlink *devlink = info->user_ptr[0];
8112 struct devlink_health_reporter *reporter;
8113
8114 reporter = devlink_health_reporter_get_from_info(devlink, info);
8115 if (!reporter)
8116 return -EINVAL;
8117
8118 if (!reporter->ops->dump) {
8119 devlink_health_reporter_put(reporter);
8120 return -EOPNOTSUPP;
8121 }
8122
8123 mutex_lock(&reporter->dump_lock);
8124 devlink_health_dump_clear(reporter);
8125 mutex_unlock(&reporter->dump_lock);
8126 devlink_health_reporter_put(reporter);
8127 return 0;
8128 }
8129
devlink_nl_cmd_health_reporter_test_doit(struct sk_buff * skb,struct genl_info * info)8130 static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
8131 struct genl_info *info)
8132 {
8133 struct devlink *devlink = info->user_ptr[0];
8134 struct devlink_health_reporter *reporter;
8135 int err;
8136
8137 reporter = devlink_health_reporter_get_from_info(devlink, info);
8138 if (!reporter)
8139 return -EINVAL;
8140
8141 if (!reporter->ops->test) {
8142 devlink_health_reporter_put(reporter);
8143 return -EOPNOTSUPP;
8144 }
8145
8146 err = reporter->ops->test(reporter, info->extack);
8147
8148 devlink_health_reporter_put(reporter);
8149 return err;
8150 }
8151
8152 struct devlink_stats {
8153 u64_stats_t rx_bytes;
8154 u64_stats_t rx_packets;
8155 struct u64_stats_sync syncp;
8156 };
8157
8158 /**
8159 * struct devlink_trap_policer_item - Packet trap policer attributes.
8160 * @policer: Immutable packet trap policer attributes.
8161 * @rate: Rate in packets / sec.
8162 * @burst: Burst size in packets.
8163 * @list: trap_policer_list member.
8164 *
8165 * Describes packet trap policer attributes. Created by devlink during trap
8166 * policer registration.
8167 */
8168 struct devlink_trap_policer_item {
8169 const struct devlink_trap_policer *policer;
8170 u64 rate;
8171 u64 burst;
8172 struct list_head list;
8173 };
8174
8175 /**
8176 * struct devlink_trap_group_item - Packet trap group attributes.
8177 * @group: Immutable packet trap group attributes.
8178 * @policer_item: Associated policer item. Can be NULL.
8179 * @list: trap_group_list member.
8180 * @stats: Trap group statistics.
8181 *
8182 * Describes packet trap group attributes. Created by devlink during trap
8183 * group registration.
8184 */
8185 struct devlink_trap_group_item {
8186 const struct devlink_trap_group *group;
8187 struct devlink_trap_policer_item *policer_item;
8188 struct list_head list;
8189 struct devlink_stats __percpu *stats;
8190 };
8191
8192 /**
8193 * struct devlink_trap_item - Packet trap attributes.
8194 * @trap: Immutable packet trap attributes.
8195 * @group_item: Associated group item.
8196 * @list: trap_list member.
8197 * @action: Trap action.
8198 * @stats: Trap statistics.
8199 * @priv: Driver private information.
8200 *
8201 * Describes both mutable and immutable packet trap attributes. Created by
8202 * devlink during trap registration and used for all trap related operations.
8203 */
8204 struct devlink_trap_item {
8205 const struct devlink_trap *trap;
8206 struct devlink_trap_group_item *group_item;
8207 struct list_head list;
8208 enum devlink_trap_action action;
8209 struct devlink_stats __percpu *stats;
8210 void *priv;
8211 };
8212
8213 static struct devlink_trap_policer_item *
devlink_trap_policer_item_lookup(struct devlink * devlink,u32 id)8214 devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
8215 {
8216 struct devlink_trap_policer_item *policer_item;
8217
8218 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
8219 if (policer_item->policer->id == id)
8220 return policer_item;
8221 }
8222
8223 return NULL;
8224 }
8225
8226 static struct devlink_trap_item *
devlink_trap_item_lookup(struct devlink * devlink,const char * name)8227 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
8228 {
8229 struct devlink_trap_item *trap_item;
8230
8231 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8232 if (!strcmp(trap_item->trap->name, name))
8233 return trap_item;
8234 }
8235
8236 return NULL;
8237 }
8238
8239 static struct devlink_trap_item *
devlink_trap_item_get_from_info(struct devlink * devlink,struct genl_info * info)8240 devlink_trap_item_get_from_info(struct devlink *devlink,
8241 struct genl_info *info)
8242 {
8243 struct nlattr *attr;
8244
8245 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
8246 return NULL;
8247 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
8248
8249 return devlink_trap_item_lookup(devlink, nla_data(attr));
8250 }
8251
8252 static int
devlink_trap_action_get_from_info(struct genl_info * info,enum devlink_trap_action * p_trap_action)8253 devlink_trap_action_get_from_info(struct genl_info *info,
8254 enum devlink_trap_action *p_trap_action)
8255 {
8256 u8 val;
8257
8258 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
8259 switch (val) {
8260 case DEVLINK_TRAP_ACTION_DROP:
8261 case DEVLINK_TRAP_ACTION_TRAP:
8262 case DEVLINK_TRAP_ACTION_MIRROR:
8263 *p_trap_action = val;
8264 break;
8265 default:
8266 return -EINVAL;
8267 }
8268
8269 return 0;
8270 }
8271
devlink_trap_metadata_put(struct sk_buff * msg,const struct devlink_trap * trap)8272 static int devlink_trap_metadata_put(struct sk_buff *msg,
8273 const struct devlink_trap *trap)
8274 {
8275 struct nlattr *attr;
8276
8277 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
8278 if (!attr)
8279 return -EMSGSIZE;
8280
8281 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
8282 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
8283 goto nla_put_failure;
8284 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
8285 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
8286 goto nla_put_failure;
8287
8288 nla_nest_end(msg, attr);
8289
8290 return 0;
8291
8292 nla_put_failure:
8293 nla_nest_cancel(msg, attr);
8294 return -EMSGSIZE;
8295 }
8296
devlink_trap_stats_read(struct devlink_stats __percpu * trap_stats,struct devlink_stats * stats)8297 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
8298 struct devlink_stats *stats)
8299 {
8300 int i;
8301
8302 memset(stats, 0, sizeof(*stats));
8303 for_each_possible_cpu(i) {
8304 struct devlink_stats *cpu_stats;
8305 u64 rx_packets, rx_bytes;
8306 unsigned int start;
8307
8308 cpu_stats = per_cpu_ptr(trap_stats, i);
8309 do {
8310 start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
8311 rx_packets = u64_stats_read(&cpu_stats->rx_packets);
8312 rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
8313 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
8314
8315 u64_stats_add(&stats->rx_packets, rx_packets);
8316 u64_stats_add(&stats->rx_bytes, rx_bytes);
8317 }
8318 }
8319
8320 static int
devlink_trap_group_stats_put(struct sk_buff * msg,struct devlink_stats __percpu * trap_stats)8321 devlink_trap_group_stats_put(struct sk_buff *msg,
8322 struct devlink_stats __percpu *trap_stats)
8323 {
8324 struct devlink_stats stats;
8325 struct nlattr *attr;
8326
8327 devlink_trap_stats_read(trap_stats, &stats);
8328
8329 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8330 if (!attr)
8331 return -EMSGSIZE;
8332
8333 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
8334 u64_stats_read(&stats.rx_packets),
8335 DEVLINK_ATTR_PAD))
8336 goto nla_put_failure;
8337
8338 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
8339 u64_stats_read(&stats.rx_bytes),
8340 DEVLINK_ATTR_PAD))
8341 goto nla_put_failure;
8342
8343 nla_nest_end(msg, attr);
8344
8345 return 0;
8346
8347 nla_put_failure:
8348 nla_nest_cancel(msg, attr);
8349 return -EMSGSIZE;
8350 }
8351
devlink_trap_stats_put(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_item * trap_item)8352 static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink,
8353 const struct devlink_trap_item *trap_item)
8354 {
8355 struct devlink_stats stats;
8356 struct nlattr *attr;
8357 u64 drops = 0;
8358 int err;
8359
8360 if (devlink->ops->trap_drop_counter_get) {
8361 err = devlink->ops->trap_drop_counter_get(devlink,
8362 trap_item->trap,
8363 &drops);
8364 if (err)
8365 return err;
8366 }
8367
8368 devlink_trap_stats_read(trap_item->stats, &stats);
8369
8370 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8371 if (!attr)
8372 return -EMSGSIZE;
8373
8374 if (devlink->ops->trap_drop_counter_get &&
8375 nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
8376 DEVLINK_ATTR_PAD))
8377 goto nla_put_failure;
8378
8379 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
8380 u64_stats_read(&stats.rx_packets),
8381 DEVLINK_ATTR_PAD))
8382 goto nla_put_failure;
8383
8384 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
8385 u64_stats_read(&stats.rx_bytes),
8386 DEVLINK_ATTR_PAD))
8387 goto nla_put_failure;
8388
8389 nla_nest_end(msg, attr);
8390
8391 return 0;
8392
8393 nla_put_failure:
8394 nla_nest_cancel(msg, attr);
8395 return -EMSGSIZE;
8396 }
8397
devlink_nl_trap_fill(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_item * trap_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)8398 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
8399 const struct devlink_trap_item *trap_item,
8400 enum devlink_command cmd, u32 portid, u32 seq,
8401 int flags)
8402 {
8403 struct devlink_trap_group_item *group_item = trap_item->group_item;
8404 void *hdr;
8405 int err;
8406
8407 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8408 if (!hdr)
8409 return -EMSGSIZE;
8410
8411 if (devlink_nl_put_handle(msg, devlink))
8412 goto nla_put_failure;
8413
8414 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
8415 group_item->group->name))
8416 goto nla_put_failure;
8417
8418 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
8419 goto nla_put_failure;
8420
8421 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
8422 goto nla_put_failure;
8423
8424 if (trap_item->trap->generic &&
8425 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
8426 goto nla_put_failure;
8427
8428 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
8429 goto nla_put_failure;
8430
8431 err = devlink_trap_metadata_put(msg, trap_item->trap);
8432 if (err)
8433 goto nla_put_failure;
8434
8435 err = devlink_trap_stats_put(msg, devlink, trap_item);
8436 if (err)
8437 goto nla_put_failure;
8438
8439 genlmsg_end(msg, hdr);
8440
8441 return 0;
8442
8443 nla_put_failure:
8444 genlmsg_cancel(msg, hdr);
8445 return -EMSGSIZE;
8446 }
8447
devlink_nl_cmd_trap_get_doit(struct sk_buff * skb,struct genl_info * info)8448 static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
8449 struct genl_info *info)
8450 {
8451 struct netlink_ext_ack *extack = info->extack;
8452 struct devlink *devlink = info->user_ptr[0];
8453 struct devlink_trap_item *trap_item;
8454 struct sk_buff *msg;
8455 int err;
8456
8457 if (list_empty(&devlink->trap_list))
8458 return -EOPNOTSUPP;
8459
8460 trap_item = devlink_trap_item_get_from_info(devlink, info);
8461 if (!trap_item) {
8462 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
8463 return -ENOENT;
8464 }
8465
8466 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8467 if (!msg)
8468 return -ENOMEM;
8469
8470 err = devlink_nl_trap_fill(msg, devlink, trap_item,
8471 DEVLINK_CMD_TRAP_NEW, info->snd_portid,
8472 info->snd_seq, 0);
8473 if (err)
8474 goto err_trap_fill;
8475
8476 return genlmsg_reply(msg, info);
8477
8478 err_trap_fill:
8479 nlmsg_free(msg);
8480 return err;
8481 }
8482
devlink_nl_cmd_trap_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)8483 static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
8484 struct netlink_callback *cb)
8485 {
8486 struct devlink_trap_item *trap_item;
8487 struct devlink *devlink;
8488 int start = cb->args[0];
8489 unsigned long index;
8490 int idx = 0;
8491 int err;
8492
8493 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
8494 devl_lock(devlink);
8495 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8496 if (idx < start) {
8497 idx++;
8498 continue;
8499 }
8500 err = devlink_nl_trap_fill(msg, devlink, trap_item,
8501 DEVLINK_CMD_TRAP_NEW,
8502 NETLINK_CB(cb->skb).portid,
8503 cb->nlh->nlmsg_seq,
8504 NLM_F_MULTI);
8505 if (err) {
8506 devl_unlock(devlink);
8507 devlink_put(devlink);
8508 goto out;
8509 }
8510 idx++;
8511 }
8512 devl_unlock(devlink);
8513 devlink_put(devlink);
8514 }
8515 out:
8516 cb->args[0] = idx;
8517 return msg->len;
8518 }
8519
__devlink_trap_action_set(struct devlink * devlink,struct devlink_trap_item * trap_item,enum devlink_trap_action trap_action,struct netlink_ext_ack * extack)8520 static int __devlink_trap_action_set(struct devlink *devlink,
8521 struct devlink_trap_item *trap_item,
8522 enum devlink_trap_action trap_action,
8523 struct netlink_ext_ack *extack)
8524 {
8525 int err;
8526
8527 if (trap_item->action != trap_action &&
8528 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
8529 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
8530 return 0;
8531 }
8532
8533 err = devlink->ops->trap_action_set(devlink, trap_item->trap,
8534 trap_action, extack);
8535 if (err)
8536 return err;
8537
8538 trap_item->action = trap_action;
8539
8540 return 0;
8541 }
8542
devlink_trap_action_set(struct devlink * devlink,struct devlink_trap_item * trap_item,struct genl_info * info)8543 static int devlink_trap_action_set(struct devlink *devlink,
8544 struct devlink_trap_item *trap_item,
8545 struct genl_info *info)
8546 {
8547 enum devlink_trap_action trap_action;
8548 int err;
8549
8550 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
8551 return 0;
8552
8553 err = devlink_trap_action_get_from_info(info, &trap_action);
8554 if (err) {
8555 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
8556 return -EINVAL;
8557 }
8558
8559 return __devlink_trap_action_set(devlink, trap_item, trap_action,
8560 info->extack);
8561 }
8562
devlink_nl_cmd_trap_set_doit(struct sk_buff * skb,struct genl_info * info)8563 static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
8564 struct genl_info *info)
8565 {
8566 struct netlink_ext_ack *extack = info->extack;
8567 struct devlink *devlink = info->user_ptr[0];
8568 struct devlink_trap_item *trap_item;
8569
8570 if (list_empty(&devlink->trap_list))
8571 return -EOPNOTSUPP;
8572
8573 trap_item = devlink_trap_item_get_from_info(devlink, info);
8574 if (!trap_item) {
8575 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
8576 return -ENOENT;
8577 }
8578
8579 return devlink_trap_action_set(devlink, trap_item, info);
8580 }
8581
8582 static struct devlink_trap_group_item *
devlink_trap_group_item_lookup(struct devlink * devlink,const char * name)8583 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
8584 {
8585 struct devlink_trap_group_item *group_item;
8586
8587 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
8588 if (!strcmp(group_item->group->name, name))
8589 return group_item;
8590 }
8591
8592 return NULL;
8593 }
8594
8595 static struct devlink_trap_group_item *
devlink_trap_group_item_lookup_by_id(struct devlink * devlink,u16 id)8596 devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
8597 {
8598 struct devlink_trap_group_item *group_item;
8599
8600 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
8601 if (group_item->group->id == id)
8602 return group_item;
8603 }
8604
8605 return NULL;
8606 }
8607
8608 static struct devlink_trap_group_item *
devlink_trap_group_item_get_from_info(struct devlink * devlink,struct genl_info * info)8609 devlink_trap_group_item_get_from_info(struct devlink *devlink,
8610 struct genl_info *info)
8611 {
8612 char *name;
8613
8614 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
8615 return NULL;
8616 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
8617
8618 return devlink_trap_group_item_lookup(devlink, name);
8619 }
8620
8621 static int
devlink_nl_trap_group_fill(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_group_item * group_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)8622 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
8623 const struct devlink_trap_group_item *group_item,
8624 enum devlink_command cmd, u32 portid, u32 seq,
8625 int flags)
8626 {
8627 void *hdr;
8628 int err;
8629
8630 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8631 if (!hdr)
8632 return -EMSGSIZE;
8633
8634 if (devlink_nl_put_handle(msg, devlink))
8635 goto nla_put_failure;
8636
8637 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
8638 group_item->group->name))
8639 goto nla_put_failure;
8640
8641 if (group_item->group->generic &&
8642 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
8643 goto nla_put_failure;
8644
8645 if (group_item->policer_item &&
8646 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
8647 group_item->policer_item->policer->id))
8648 goto nla_put_failure;
8649
8650 err = devlink_trap_group_stats_put(msg, group_item->stats);
8651 if (err)
8652 goto nla_put_failure;
8653
8654 genlmsg_end(msg, hdr);
8655
8656 return 0;
8657
8658 nla_put_failure:
8659 genlmsg_cancel(msg, hdr);
8660 return -EMSGSIZE;
8661 }
8662
devlink_nl_cmd_trap_group_get_doit(struct sk_buff * skb,struct genl_info * info)8663 static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
8664 struct genl_info *info)
8665 {
8666 struct netlink_ext_ack *extack = info->extack;
8667 struct devlink *devlink = info->user_ptr[0];
8668 struct devlink_trap_group_item *group_item;
8669 struct sk_buff *msg;
8670 int err;
8671
8672 if (list_empty(&devlink->trap_group_list))
8673 return -EOPNOTSUPP;
8674
8675 group_item = devlink_trap_group_item_get_from_info(devlink, info);
8676 if (!group_item) {
8677 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
8678 return -ENOENT;
8679 }
8680
8681 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8682 if (!msg)
8683 return -ENOMEM;
8684
8685 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
8686 DEVLINK_CMD_TRAP_GROUP_NEW,
8687 info->snd_portid, info->snd_seq, 0);
8688 if (err)
8689 goto err_trap_group_fill;
8690
8691 return genlmsg_reply(msg, info);
8692
8693 err_trap_group_fill:
8694 nlmsg_free(msg);
8695 return err;
8696 }
8697
devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)8698 static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
8699 struct netlink_callback *cb)
8700 {
8701 enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
8702 struct devlink_trap_group_item *group_item;
8703 u32 portid = NETLINK_CB(cb->skb).portid;
8704 struct devlink *devlink;
8705 int start = cb->args[0];
8706 unsigned long index;
8707 int idx = 0;
8708 int err;
8709
8710 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
8711 devl_lock(devlink);
8712 list_for_each_entry(group_item, &devlink->trap_group_list,
8713 list) {
8714 if (idx < start) {
8715 idx++;
8716 continue;
8717 }
8718 err = devlink_nl_trap_group_fill(msg, devlink,
8719 group_item, cmd,
8720 portid,
8721 cb->nlh->nlmsg_seq,
8722 NLM_F_MULTI);
8723 if (err) {
8724 devl_unlock(devlink);
8725 devlink_put(devlink);
8726 goto out;
8727 }
8728 idx++;
8729 }
8730 devl_unlock(devlink);
8731 devlink_put(devlink);
8732 }
8733 out:
8734 cb->args[0] = idx;
8735 return msg->len;
8736 }
8737
8738 static int
__devlink_trap_group_action_set(struct devlink * devlink,struct devlink_trap_group_item * group_item,enum devlink_trap_action trap_action,struct netlink_ext_ack * extack)8739 __devlink_trap_group_action_set(struct devlink *devlink,
8740 struct devlink_trap_group_item *group_item,
8741 enum devlink_trap_action trap_action,
8742 struct netlink_ext_ack *extack)
8743 {
8744 const char *group_name = group_item->group->name;
8745 struct devlink_trap_item *trap_item;
8746 int err;
8747
8748 if (devlink->ops->trap_group_action_set) {
8749 err = devlink->ops->trap_group_action_set(devlink, group_item->group,
8750 trap_action, extack);
8751 if (err)
8752 return err;
8753
8754 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8755 if (strcmp(trap_item->group_item->group->name, group_name))
8756 continue;
8757 if (trap_item->action != trap_action &&
8758 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP)
8759 continue;
8760 trap_item->action = trap_action;
8761 }
8762
8763 return 0;
8764 }
8765
8766 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8767 if (strcmp(trap_item->group_item->group->name, group_name))
8768 continue;
8769 err = __devlink_trap_action_set(devlink, trap_item,
8770 trap_action, extack);
8771 if (err)
8772 return err;
8773 }
8774
8775 return 0;
8776 }
8777
8778 static int
devlink_trap_group_action_set(struct devlink * devlink,struct devlink_trap_group_item * group_item,struct genl_info * info,bool * p_modified)8779 devlink_trap_group_action_set(struct devlink *devlink,
8780 struct devlink_trap_group_item *group_item,
8781 struct genl_info *info, bool *p_modified)
8782 {
8783 enum devlink_trap_action trap_action;
8784 int err;
8785
8786 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
8787 return 0;
8788
8789 err = devlink_trap_action_get_from_info(info, &trap_action);
8790 if (err) {
8791 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
8792 return -EINVAL;
8793 }
8794
8795 err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
8796 info->extack);
8797 if (err)
8798 return err;
8799
8800 *p_modified = true;
8801
8802 return 0;
8803 }
8804
devlink_trap_group_set(struct devlink * devlink,struct devlink_trap_group_item * group_item,struct genl_info * info)8805 static int devlink_trap_group_set(struct devlink *devlink,
8806 struct devlink_trap_group_item *group_item,
8807 struct genl_info *info)
8808 {
8809 struct devlink_trap_policer_item *policer_item;
8810 struct netlink_ext_ack *extack = info->extack;
8811 const struct devlink_trap_policer *policer;
8812 struct nlattr **attrs = info->attrs;
8813 int err;
8814
8815 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
8816 return 0;
8817
8818 if (!devlink->ops->trap_group_set)
8819 return -EOPNOTSUPP;
8820
8821 policer_item = group_item->policer_item;
8822 if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
8823 u32 policer_id;
8824
8825 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
8826 policer_item = devlink_trap_policer_item_lookup(devlink,
8827 policer_id);
8828 if (policer_id && !policer_item) {
8829 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
8830 return -ENOENT;
8831 }
8832 }
8833 policer = policer_item ? policer_item->policer : NULL;
8834
8835 err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
8836 extack);
8837 if (err)
8838 return err;
8839
8840 group_item->policer_item = policer_item;
8841
8842 return 0;
8843 }
8844
devlink_nl_cmd_trap_group_set_doit(struct sk_buff * skb,struct genl_info * info)8845 static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
8846 struct genl_info *info)
8847 {
8848 struct netlink_ext_ack *extack = info->extack;
8849 struct devlink *devlink = info->user_ptr[0];
8850 struct devlink_trap_group_item *group_item;
8851 bool modified = false;
8852 int err;
8853
8854 if (list_empty(&devlink->trap_group_list))
8855 return -EOPNOTSUPP;
8856
8857 group_item = devlink_trap_group_item_get_from_info(devlink, info);
8858 if (!group_item) {
8859 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
8860 return -ENOENT;
8861 }
8862
8863 err = devlink_trap_group_action_set(devlink, group_item, info,
8864 &modified);
8865 if (err)
8866 return err;
8867
8868 err = devlink_trap_group_set(devlink, group_item, info);
8869 if (err)
8870 goto err_trap_group_set;
8871
8872 return 0;
8873
8874 err_trap_group_set:
8875 if (modified)
8876 NL_SET_ERR_MSG_MOD(extack, "Trap group set failed, but some changes were committed already");
8877 return err;
8878 }
8879
8880 static struct devlink_trap_policer_item *
devlink_trap_policer_item_get_from_info(struct devlink * devlink,struct genl_info * info)8881 devlink_trap_policer_item_get_from_info(struct devlink *devlink,
8882 struct genl_info *info)
8883 {
8884 u32 id;
8885
8886 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
8887 return NULL;
8888 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
8889
8890 return devlink_trap_policer_item_lookup(devlink, id);
8891 }
8892
8893 static int
devlink_trap_policer_stats_put(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_policer * policer)8894 devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
8895 const struct devlink_trap_policer *policer)
8896 {
8897 struct nlattr *attr;
8898 u64 drops;
8899 int err;
8900
8901 if (!devlink->ops->trap_policer_counter_get)
8902 return 0;
8903
8904 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
8905 if (err)
8906 return err;
8907
8908 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8909 if (!attr)
8910 return -EMSGSIZE;
8911
8912 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
8913 DEVLINK_ATTR_PAD))
8914 goto nla_put_failure;
8915
8916 nla_nest_end(msg, attr);
8917
8918 return 0;
8919
8920 nla_put_failure:
8921 nla_nest_cancel(msg, attr);
8922 return -EMSGSIZE;
8923 }
8924
8925 static int
devlink_nl_trap_policer_fill(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_policer_item * policer_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)8926 devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
8927 const struct devlink_trap_policer_item *policer_item,
8928 enum devlink_command cmd, u32 portid, u32 seq,
8929 int flags)
8930 {
8931 void *hdr;
8932 int err;
8933
8934 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8935 if (!hdr)
8936 return -EMSGSIZE;
8937
8938 if (devlink_nl_put_handle(msg, devlink))
8939 goto nla_put_failure;
8940
8941 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
8942 policer_item->policer->id))
8943 goto nla_put_failure;
8944
8945 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
8946 policer_item->rate, DEVLINK_ATTR_PAD))
8947 goto nla_put_failure;
8948
8949 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
8950 policer_item->burst, DEVLINK_ATTR_PAD))
8951 goto nla_put_failure;
8952
8953 err = devlink_trap_policer_stats_put(msg, devlink,
8954 policer_item->policer);
8955 if (err)
8956 goto nla_put_failure;
8957
8958 genlmsg_end(msg, hdr);
8959
8960 return 0;
8961
8962 nla_put_failure:
8963 genlmsg_cancel(msg, hdr);
8964 return -EMSGSIZE;
8965 }
8966
devlink_nl_cmd_trap_policer_get_doit(struct sk_buff * skb,struct genl_info * info)8967 static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb,
8968 struct genl_info *info)
8969 {
8970 struct devlink_trap_policer_item *policer_item;
8971 struct netlink_ext_ack *extack = info->extack;
8972 struct devlink *devlink = info->user_ptr[0];
8973 struct sk_buff *msg;
8974 int err;
8975
8976 if (list_empty(&devlink->trap_policer_list))
8977 return -EOPNOTSUPP;
8978
8979 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
8980 if (!policer_item) {
8981 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
8982 return -ENOENT;
8983 }
8984
8985 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8986 if (!msg)
8987 return -ENOMEM;
8988
8989 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
8990 DEVLINK_CMD_TRAP_POLICER_NEW,
8991 info->snd_portid, info->snd_seq, 0);
8992 if (err)
8993 goto err_trap_policer_fill;
8994
8995 return genlmsg_reply(msg, info);
8996
8997 err_trap_policer_fill:
8998 nlmsg_free(msg);
8999 return err;
9000 }
9001
devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)9002 static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg,
9003 struct netlink_callback *cb)
9004 {
9005 enum devlink_command cmd = DEVLINK_CMD_TRAP_POLICER_NEW;
9006 struct devlink_trap_policer_item *policer_item;
9007 u32 portid = NETLINK_CB(cb->skb).portid;
9008 struct devlink *devlink;
9009 int start = cb->args[0];
9010 unsigned long index;
9011 int idx = 0;
9012 int err;
9013
9014 devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
9015 devl_lock(devlink);
9016 list_for_each_entry(policer_item, &devlink->trap_policer_list,
9017 list) {
9018 if (idx < start) {
9019 idx++;
9020 continue;
9021 }
9022 err = devlink_nl_trap_policer_fill(msg, devlink,
9023 policer_item, cmd,
9024 portid,
9025 cb->nlh->nlmsg_seq,
9026 NLM_F_MULTI);
9027 if (err) {
9028 devl_unlock(devlink);
9029 devlink_put(devlink);
9030 goto out;
9031 }
9032 idx++;
9033 }
9034 devl_unlock(devlink);
9035 devlink_put(devlink);
9036 }
9037 out:
9038 cb->args[0] = idx;
9039 return msg->len;
9040 }
9041
9042 static int
devlink_trap_policer_set(struct devlink * devlink,struct devlink_trap_policer_item * policer_item,struct genl_info * info)9043 devlink_trap_policer_set(struct devlink *devlink,
9044 struct devlink_trap_policer_item *policer_item,
9045 struct genl_info *info)
9046 {
9047 struct netlink_ext_ack *extack = info->extack;
9048 struct nlattr **attrs = info->attrs;
9049 u64 rate, burst;
9050 int err;
9051
9052 rate = policer_item->rate;
9053 burst = policer_item->burst;
9054
9055 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
9056 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
9057
9058 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
9059 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
9060
9061 if (rate < policer_item->policer->min_rate) {
9062 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
9063 return -EINVAL;
9064 }
9065
9066 if (rate > policer_item->policer->max_rate) {
9067 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
9068 return -EINVAL;
9069 }
9070
9071 if (burst < policer_item->policer->min_burst) {
9072 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
9073 return -EINVAL;
9074 }
9075
9076 if (burst > policer_item->policer->max_burst) {
9077 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
9078 return -EINVAL;
9079 }
9080
9081 err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
9082 rate, burst, info->extack);
9083 if (err)
9084 return err;
9085
9086 policer_item->rate = rate;
9087 policer_item->burst = burst;
9088
9089 return 0;
9090 }
9091
devlink_nl_cmd_trap_policer_set_doit(struct sk_buff * skb,struct genl_info * info)9092 static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
9093 struct genl_info *info)
9094 {
9095 struct devlink_trap_policer_item *policer_item;
9096 struct netlink_ext_ack *extack = info->extack;
9097 struct devlink *devlink = info->user_ptr[0];
9098
9099 if (list_empty(&devlink->trap_policer_list))
9100 return -EOPNOTSUPP;
9101
9102 if (!devlink->ops->trap_policer_set)
9103 return -EOPNOTSUPP;
9104
9105 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
9106 if (!policer_item) {
9107 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
9108 return -ENOENT;
9109 }
9110
9111 return devlink_trap_policer_set(devlink, policer_item, info);
9112 }
9113
9114 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
9115 [DEVLINK_ATTR_UNSPEC] = { .strict_start_type =
9116 DEVLINK_ATTR_TRAP_POLICER_ID },
9117 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
9118 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
9119 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
9120 [DEVLINK_ATTR_PORT_TYPE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_PORT_TYPE_AUTO,
9121 DEVLINK_PORT_TYPE_IB),
9122 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
9123 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
9124 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
9125 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
9126 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
9127 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
9128 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
9129 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
9130 [DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_ESWITCH_MODE_LEGACY,
9131 DEVLINK_ESWITCH_MODE_SWITCHDEV),
9132 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
9133 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
9134 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
9135 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
9136 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
9137 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
9138 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
9139 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
9140 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
9141 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
9142 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
9143 [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
9144 [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
9145 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
9146 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
9147 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
9148 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
9149 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
9150 [DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK] =
9151 NLA_POLICY_BITFIELD32(DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS),
9152 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
9153 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
9154 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
9155 [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
9156 [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
9157 [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
9158 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP] = { .type = NLA_U8 },
9159 [DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
9160 [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
9161 [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
9162 [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED },
9163 [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
9164 DEVLINK_RELOAD_ACTION_MAX),
9165 [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK),
9166 [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NLA_U16 },
9167 [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16 },
9168 [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NLA_U32 },
9169 [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NLA_U32 },
9170 [DEVLINK_ATTR_RATE_TYPE] = { .type = NLA_U16 },
9171 [DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64 },
9172 [DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64 },
9173 [DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING },
9174 [DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING },
9175 [DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 },
9176 [DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING },
9177 [DEVLINK_ATTR_SELFTESTS] = { .type = NLA_NESTED },
9178 };
9179
9180 static const struct genl_small_ops devlink_nl_ops[] = {
9181 {
9182 .cmd = DEVLINK_CMD_GET,
9183 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9184 .doit = devlink_nl_cmd_get_doit,
9185 .dumpit = devlink_nl_cmd_get_dumpit,
9186 /* can be retrieved by unprivileged users */
9187 },
9188 {
9189 .cmd = DEVLINK_CMD_PORT_GET,
9190 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9191 .doit = devlink_nl_cmd_port_get_doit,
9192 .dumpit = devlink_nl_cmd_port_get_dumpit,
9193 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9194 /* can be retrieved by unprivileged users */
9195 },
9196 {
9197 .cmd = DEVLINK_CMD_PORT_SET,
9198 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9199 .doit = devlink_nl_cmd_port_set_doit,
9200 .flags = GENL_ADMIN_PERM,
9201 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9202 },
9203 {
9204 .cmd = DEVLINK_CMD_RATE_GET,
9205 .doit = devlink_nl_cmd_rate_get_doit,
9206 .dumpit = devlink_nl_cmd_rate_get_dumpit,
9207 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE,
9208 /* can be retrieved by unprivileged users */
9209 },
9210 {
9211 .cmd = DEVLINK_CMD_RATE_SET,
9212 .doit = devlink_nl_cmd_rate_set_doit,
9213 .flags = GENL_ADMIN_PERM,
9214 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE,
9215 },
9216 {
9217 .cmd = DEVLINK_CMD_RATE_NEW,
9218 .doit = devlink_nl_cmd_rate_new_doit,
9219 .flags = GENL_ADMIN_PERM,
9220 },
9221 {
9222 .cmd = DEVLINK_CMD_RATE_DEL,
9223 .doit = devlink_nl_cmd_rate_del_doit,
9224 .flags = GENL_ADMIN_PERM,
9225 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE_NODE,
9226 },
9227 {
9228 .cmd = DEVLINK_CMD_PORT_SPLIT,
9229 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9230 .doit = devlink_nl_cmd_port_split_doit,
9231 .flags = GENL_ADMIN_PERM,
9232 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9233 },
9234 {
9235 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
9236 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9237 .doit = devlink_nl_cmd_port_unsplit_doit,
9238 .flags = GENL_ADMIN_PERM,
9239 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9240 },
9241 {
9242 .cmd = DEVLINK_CMD_PORT_NEW,
9243 .doit = devlink_nl_cmd_port_new_doit,
9244 .flags = GENL_ADMIN_PERM,
9245 },
9246 {
9247 .cmd = DEVLINK_CMD_PORT_DEL,
9248 .doit = devlink_nl_cmd_port_del_doit,
9249 .flags = GENL_ADMIN_PERM,
9250 },
9251 {
9252 .cmd = DEVLINK_CMD_LINECARD_GET,
9253 .doit = devlink_nl_cmd_linecard_get_doit,
9254 .dumpit = devlink_nl_cmd_linecard_get_dumpit,
9255 .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
9256 /* can be retrieved by unprivileged users */
9257 },
9258 {
9259 .cmd = DEVLINK_CMD_LINECARD_SET,
9260 .doit = devlink_nl_cmd_linecard_set_doit,
9261 .flags = GENL_ADMIN_PERM,
9262 .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
9263 },
9264 {
9265 .cmd = DEVLINK_CMD_SB_GET,
9266 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9267 .doit = devlink_nl_cmd_sb_get_doit,
9268 .dumpit = devlink_nl_cmd_sb_get_dumpit,
9269 /* can be retrieved by unprivileged users */
9270 },
9271 {
9272 .cmd = DEVLINK_CMD_SB_POOL_GET,
9273 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9274 .doit = devlink_nl_cmd_sb_pool_get_doit,
9275 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
9276 /* can be retrieved by unprivileged users */
9277 },
9278 {
9279 .cmd = DEVLINK_CMD_SB_POOL_SET,
9280 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9281 .doit = devlink_nl_cmd_sb_pool_set_doit,
9282 .flags = GENL_ADMIN_PERM,
9283 },
9284 {
9285 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
9286 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9287 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
9288 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
9289 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9290 /* can be retrieved by unprivileged users */
9291 },
9292 {
9293 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
9294 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9295 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
9296 .flags = GENL_ADMIN_PERM,
9297 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9298 },
9299 {
9300 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
9301 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9302 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
9303 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
9304 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9305 /* can be retrieved by unprivileged users */
9306 },
9307 {
9308 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
9309 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9310 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
9311 .flags = GENL_ADMIN_PERM,
9312 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9313 },
9314 {
9315 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
9316 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9317 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
9318 .flags = GENL_ADMIN_PERM,
9319 },
9320 {
9321 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
9322 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9323 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
9324 .flags = GENL_ADMIN_PERM,
9325 },
9326 {
9327 .cmd = DEVLINK_CMD_ESWITCH_GET,
9328 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9329 .doit = devlink_nl_cmd_eswitch_get_doit,
9330 .flags = GENL_ADMIN_PERM,
9331 },
9332 {
9333 .cmd = DEVLINK_CMD_ESWITCH_SET,
9334 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9335 .doit = devlink_nl_cmd_eswitch_set_doit,
9336 .flags = GENL_ADMIN_PERM,
9337 },
9338 {
9339 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
9340 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9341 .doit = devlink_nl_cmd_dpipe_table_get,
9342 /* can be retrieved by unprivileged users */
9343 },
9344 {
9345 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
9346 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9347 .doit = devlink_nl_cmd_dpipe_entries_get,
9348 /* can be retrieved by unprivileged users */
9349 },
9350 {
9351 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
9352 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9353 .doit = devlink_nl_cmd_dpipe_headers_get,
9354 /* can be retrieved by unprivileged users */
9355 },
9356 {
9357 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
9358 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9359 .doit = devlink_nl_cmd_dpipe_table_counters_set,
9360 .flags = GENL_ADMIN_PERM,
9361 },
9362 {
9363 .cmd = DEVLINK_CMD_RESOURCE_SET,
9364 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9365 .doit = devlink_nl_cmd_resource_set,
9366 .flags = GENL_ADMIN_PERM,
9367 },
9368 {
9369 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
9370 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9371 .doit = devlink_nl_cmd_resource_dump,
9372 /* can be retrieved by unprivileged users */
9373 },
9374 {
9375 .cmd = DEVLINK_CMD_RELOAD,
9376 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9377 .doit = devlink_nl_cmd_reload,
9378 .flags = GENL_ADMIN_PERM,
9379 },
9380 {
9381 .cmd = DEVLINK_CMD_PARAM_GET,
9382 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9383 .doit = devlink_nl_cmd_param_get_doit,
9384 .dumpit = devlink_nl_cmd_param_get_dumpit,
9385 /* can be retrieved by unprivileged users */
9386 },
9387 {
9388 .cmd = DEVLINK_CMD_PARAM_SET,
9389 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9390 .doit = devlink_nl_cmd_param_set_doit,
9391 .flags = GENL_ADMIN_PERM,
9392 },
9393 {
9394 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
9395 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9396 .doit = devlink_nl_cmd_port_param_get_doit,
9397 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
9398 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9399 /* can be retrieved by unprivileged users */
9400 },
9401 {
9402 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
9403 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9404 .doit = devlink_nl_cmd_port_param_set_doit,
9405 .flags = GENL_ADMIN_PERM,
9406 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9407 },
9408 {
9409 .cmd = DEVLINK_CMD_REGION_GET,
9410 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9411 .doit = devlink_nl_cmd_region_get_doit,
9412 .dumpit = devlink_nl_cmd_region_get_dumpit,
9413 .flags = GENL_ADMIN_PERM,
9414 },
9415 {
9416 .cmd = DEVLINK_CMD_REGION_NEW,
9417 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9418 .doit = devlink_nl_cmd_region_new,
9419 .flags = GENL_ADMIN_PERM,
9420 },
9421 {
9422 .cmd = DEVLINK_CMD_REGION_DEL,
9423 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9424 .doit = devlink_nl_cmd_region_del,
9425 .flags = GENL_ADMIN_PERM,
9426 },
9427 {
9428 .cmd = DEVLINK_CMD_REGION_READ,
9429 .validate = GENL_DONT_VALIDATE_STRICT |
9430 GENL_DONT_VALIDATE_DUMP_STRICT,
9431 .dumpit = devlink_nl_cmd_region_read_dumpit,
9432 .flags = GENL_ADMIN_PERM,
9433 },
9434 {
9435 .cmd = DEVLINK_CMD_INFO_GET,
9436 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9437 .doit = devlink_nl_cmd_info_get_doit,
9438 .dumpit = devlink_nl_cmd_info_get_dumpit,
9439 /* can be retrieved by unprivileged users */
9440 },
9441 {
9442 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
9443 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9444 .doit = devlink_nl_cmd_health_reporter_get_doit,
9445 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
9446 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9447 /* can be retrieved by unprivileged users */
9448 },
9449 {
9450 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
9451 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9452 .doit = devlink_nl_cmd_health_reporter_set_doit,
9453 .flags = GENL_ADMIN_PERM,
9454 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9455 },
9456 {
9457 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
9458 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9459 .doit = devlink_nl_cmd_health_reporter_recover_doit,
9460 .flags = GENL_ADMIN_PERM,
9461 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9462 },
9463 {
9464 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
9465 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9466 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
9467 .flags = GENL_ADMIN_PERM,
9468 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9469 },
9470 {
9471 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
9472 .validate = GENL_DONT_VALIDATE_STRICT |
9473 GENL_DONT_VALIDATE_DUMP_STRICT,
9474 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
9475 .flags = GENL_ADMIN_PERM,
9476 },
9477 {
9478 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
9479 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9480 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
9481 .flags = GENL_ADMIN_PERM,
9482 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9483 },
9484 {
9485 .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST,
9486 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9487 .doit = devlink_nl_cmd_health_reporter_test_doit,
9488 .flags = GENL_ADMIN_PERM,
9489 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
9490 },
9491 {
9492 .cmd = DEVLINK_CMD_FLASH_UPDATE,
9493 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9494 .doit = devlink_nl_cmd_flash_update,
9495 .flags = GENL_ADMIN_PERM,
9496 },
9497 {
9498 .cmd = DEVLINK_CMD_TRAP_GET,
9499 .doit = devlink_nl_cmd_trap_get_doit,
9500 .dumpit = devlink_nl_cmd_trap_get_dumpit,
9501 /* can be retrieved by unprivileged users */
9502 },
9503 {
9504 .cmd = DEVLINK_CMD_TRAP_SET,
9505 .doit = devlink_nl_cmd_trap_set_doit,
9506 .flags = GENL_ADMIN_PERM,
9507 },
9508 {
9509 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
9510 .doit = devlink_nl_cmd_trap_group_get_doit,
9511 .dumpit = devlink_nl_cmd_trap_group_get_dumpit,
9512 /* can be retrieved by unprivileged users */
9513 },
9514 {
9515 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
9516 .doit = devlink_nl_cmd_trap_group_set_doit,
9517 .flags = GENL_ADMIN_PERM,
9518 },
9519 {
9520 .cmd = DEVLINK_CMD_TRAP_POLICER_GET,
9521 .doit = devlink_nl_cmd_trap_policer_get_doit,
9522 .dumpit = devlink_nl_cmd_trap_policer_get_dumpit,
9523 /* can be retrieved by unprivileged users */
9524 },
9525 {
9526 .cmd = DEVLINK_CMD_TRAP_POLICER_SET,
9527 .doit = devlink_nl_cmd_trap_policer_set_doit,
9528 .flags = GENL_ADMIN_PERM,
9529 },
9530 {
9531 .cmd = DEVLINK_CMD_SELFTESTS_GET,
9532 .doit = devlink_nl_cmd_selftests_get_doit,
9533 .dumpit = devlink_nl_cmd_selftests_get_dumpit
9534 /* can be retrieved by unprivileged users */
9535 },
9536 {
9537 .cmd = DEVLINK_CMD_SELFTESTS_RUN,
9538 .doit = devlink_nl_cmd_selftests_run,
9539 .flags = GENL_ADMIN_PERM,
9540 },
9541 };
9542
9543 static struct genl_family devlink_nl_family __ro_after_init = {
9544 .name = DEVLINK_GENL_NAME,
9545 .version = DEVLINK_GENL_VERSION,
9546 .maxattr = DEVLINK_ATTR_MAX,
9547 .policy = devlink_nl_policy,
9548 .netnsok = true,
9549 .parallel_ops = true,
9550 .pre_doit = devlink_nl_pre_doit,
9551 .post_doit = devlink_nl_post_doit,
9552 .module = THIS_MODULE,
9553 .small_ops = devlink_nl_ops,
9554 .n_small_ops = ARRAY_SIZE(devlink_nl_ops),
9555 .resv_start_op = DEVLINK_CMD_SELFTESTS_RUN + 1,
9556 .mcgrps = devlink_nl_mcgrps,
9557 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
9558 };
9559
devlink_reload_actions_valid(const struct devlink_ops * ops)9560 static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
9561 {
9562 const struct devlink_reload_combination *comb;
9563 int i;
9564
9565 if (!devlink_reload_supported(ops)) {
9566 if (WARN_ON(ops->reload_actions))
9567 return false;
9568 return true;
9569 }
9570
9571 if (WARN_ON(!ops->reload_actions ||
9572 ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
9573 ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
9574 return false;
9575
9576 if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
9577 ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
9578 return false;
9579
9580 for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++) {
9581 comb = &devlink_reload_invalid_combinations[i];
9582 if (ops->reload_actions == BIT(comb->action) &&
9583 ops->reload_limits == BIT(comb->limit))
9584 return false;
9585 }
9586 return true;
9587 }
9588
9589 /**
9590 * devlink_set_features - Set devlink supported features
9591 *
9592 * @devlink: devlink
9593 * @features: devlink support features
9594 *
9595 * This interface allows us to set reload ops separatelly from
9596 * the devlink_alloc.
9597 */
devlink_set_features(struct devlink * devlink,u64 features)9598 void devlink_set_features(struct devlink *devlink, u64 features)
9599 {
9600 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
9601
9602 WARN_ON(features & DEVLINK_F_RELOAD &&
9603 !devlink_reload_supported(devlink->ops));
9604 devlink->features = features;
9605 }
9606 EXPORT_SYMBOL_GPL(devlink_set_features);
9607
9608 /**
9609 * devlink_alloc_ns - Allocate new devlink instance resources
9610 * in specific namespace
9611 *
9612 * @ops: ops
9613 * @priv_size: size of user private data
9614 * @net: net namespace
9615 * @dev: parent device
9616 *
9617 * Allocate new devlink instance resources, including devlink index
9618 * and name.
9619 */
devlink_alloc_ns(const struct devlink_ops * ops,size_t priv_size,struct net * net,struct device * dev)9620 struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
9621 size_t priv_size, struct net *net,
9622 struct device *dev)
9623 {
9624 struct devlink *devlink;
9625 static u32 last_id;
9626 int ret;
9627
9628 WARN_ON(!ops || !dev);
9629 if (!devlink_reload_actions_valid(ops))
9630 return NULL;
9631
9632 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
9633 if (!devlink)
9634 return NULL;
9635
9636 ret = xa_alloc_cyclic(&devlinks, &devlink->index, devlink, xa_limit_31b,
9637 &last_id, GFP_KERNEL);
9638 if (ret < 0) {
9639 kfree(devlink);
9640 return NULL;
9641 }
9642
9643 devlink->dev = dev;
9644 devlink->ops = ops;
9645 xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
9646 write_pnet(&devlink->_net, net);
9647 INIT_LIST_HEAD(&devlink->port_list);
9648 INIT_LIST_HEAD(&devlink->rate_list);
9649 INIT_LIST_HEAD(&devlink->linecard_list);
9650 INIT_LIST_HEAD(&devlink->sb_list);
9651 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
9652 INIT_LIST_HEAD(&devlink->resource_list);
9653 INIT_LIST_HEAD(&devlink->param_list);
9654 INIT_LIST_HEAD(&devlink->region_list);
9655 INIT_LIST_HEAD(&devlink->reporter_list);
9656 INIT_LIST_HEAD(&devlink->trap_list);
9657 INIT_LIST_HEAD(&devlink->trap_group_list);
9658 INIT_LIST_HEAD(&devlink->trap_policer_list);
9659 lockdep_register_key(&devlink->lock_key);
9660 mutex_init(&devlink->lock);
9661 lockdep_set_class(&devlink->lock, &devlink->lock_key);
9662 mutex_init(&devlink->reporters_lock);
9663 mutex_init(&devlink->linecards_lock);
9664 refcount_set(&devlink->refcount, 1);
9665 init_completion(&devlink->comp);
9666
9667 return devlink;
9668 }
9669 EXPORT_SYMBOL_GPL(devlink_alloc_ns);
9670
9671 static void
9672 devlink_trap_policer_notify(struct devlink *devlink,
9673 const struct devlink_trap_policer_item *policer_item,
9674 enum devlink_command cmd);
9675 static void
9676 devlink_trap_group_notify(struct devlink *devlink,
9677 const struct devlink_trap_group_item *group_item,
9678 enum devlink_command cmd);
9679 static void devlink_trap_notify(struct devlink *devlink,
9680 const struct devlink_trap_item *trap_item,
9681 enum devlink_command cmd);
9682
devlink_notify_register(struct devlink * devlink)9683 static void devlink_notify_register(struct devlink *devlink)
9684 {
9685 struct devlink_trap_policer_item *policer_item;
9686 struct devlink_trap_group_item *group_item;
9687 struct devlink_param_item *param_item;
9688 struct devlink_trap_item *trap_item;
9689 struct devlink_port *devlink_port;
9690 struct devlink_linecard *linecard;
9691 struct devlink_rate *rate_node;
9692 struct devlink_region *region;
9693
9694 devlink_notify(devlink, DEVLINK_CMD_NEW);
9695 list_for_each_entry(linecard, &devlink->linecard_list, list)
9696 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
9697
9698 list_for_each_entry(devlink_port, &devlink->port_list, list)
9699 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
9700
9701 list_for_each_entry(policer_item, &devlink->trap_policer_list, list)
9702 devlink_trap_policer_notify(devlink, policer_item,
9703 DEVLINK_CMD_TRAP_POLICER_NEW);
9704
9705 list_for_each_entry(group_item, &devlink->trap_group_list, list)
9706 devlink_trap_group_notify(devlink, group_item,
9707 DEVLINK_CMD_TRAP_GROUP_NEW);
9708
9709 list_for_each_entry(trap_item, &devlink->trap_list, list)
9710 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
9711
9712 list_for_each_entry(rate_node, &devlink->rate_list, list)
9713 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
9714
9715 list_for_each_entry(region, &devlink->region_list, list)
9716 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
9717
9718 list_for_each_entry(param_item, &devlink->param_list, list)
9719 devlink_param_notify(devlink, 0, param_item,
9720 DEVLINK_CMD_PARAM_NEW);
9721 }
9722
devlink_notify_unregister(struct devlink * devlink)9723 static void devlink_notify_unregister(struct devlink *devlink)
9724 {
9725 struct devlink_trap_policer_item *policer_item;
9726 struct devlink_trap_group_item *group_item;
9727 struct devlink_param_item *param_item;
9728 struct devlink_trap_item *trap_item;
9729 struct devlink_port *devlink_port;
9730 struct devlink_rate *rate_node;
9731 struct devlink_region *region;
9732
9733 list_for_each_entry_reverse(param_item, &devlink->param_list, list)
9734 devlink_param_notify(devlink, 0, param_item,
9735 DEVLINK_CMD_PARAM_DEL);
9736
9737 list_for_each_entry_reverse(region, &devlink->region_list, list)
9738 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
9739
9740 list_for_each_entry_reverse(rate_node, &devlink->rate_list, list)
9741 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL);
9742
9743 list_for_each_entry_reverse(trap_item, &devlink->trap_list, list)
9744 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
9745
9746 list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list)
9747 devlink_trap_group_notify(devlink, group_item,
9748 DEVLINK_CMD_TRAP_GROUP_DEL);
9749 list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list,
9750 list)
9751 devlink_trap_policer_notify(devlink, policer_item,
9752 DEVLINK_CMD_TRAP_POLICER_DEL);
9753
9754 list_for_each_entry_reverse(devlink_port, &devlink->port_list, list)
9755 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
9756 devlink_notify(devlink, DEVLINK_CMD_DEL);
9757 }
9758
9759 /**
9760 * devlink_register - Register devlink instance
9761 *
9762 * @devlink: devlink
9763 */
devlink_register(struct devlink * devlink)9764 void devlink_register(struct devlink *devlink)
9765 {
9766 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
9767 /* Make sure that we are in .probe() routine */
9768
9769 xa_set_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
9770 devlink_notify_register(devlink);
9771 }
9772 EXPORT_SYMBOL_GPL(devlink_register);
9773
9774 /**
9775 * devlink_unregister - Unregister devlink instance
9776 *
9777 * @devlink: devlink
9778 */
devlink_unregister(struct devlink * devlink)9779 void devlink_unregister(struct devlink *devlink)
9780 {
9781 ASSERT_DEVLINK_REGISTERED(devlink);
9782 /* Make sure that we are in .remove() routine */
9783
9784 xa_set_mark(&devlinks, devlink->index, DEVLINK_UNREGISTERING);
9785 devlink_put(devlink);
9786 wait_for_completion(&devlink->comp);
9787
9788 devlink_notify_unregister(devlink);
9789 xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
9790 xa_clear_mark(&devlinks, devlink->index, DEVLINK_UNREGISTERING);
9791 }
9792 EXPORT_SYMBOL_GPL(devlink_unregister);
9793
9794 /**
9795 * devlink_free - Free devlink instance resources
9796 *
9797 * @devlink: devlink
9798 */
devlink_free(struct devlink * devlink)9799 void devlink_free(struct devlink *devlink)
9800 {
9801 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
9802
9803 mutex_destroy(&devlink->linecards_lock);
9804 mutex_destroy(&devlink->reporters_lock);
9805 mutex_destroy(&devlink->lock);
9806 lockdep_unregister_key(&devlink->lock_key);
9807 WARN_ON(!list_empty(&devlink->trap_policer_list));
9808 WARN_ON(!list_empty(&devlink->trap_group_list));
9809 WARN_ON(!list_empty(&devlink->trap_list));
9810 WARN_ON(!list_empty(&devlink->reporter_list));
9811 WARN_ON(!list_empty(&devlink->region_list));
9812 WARN_ON(!list_empty(&devlink->param_list));
9813 WARN_ON(!list_empty(&devlink->resource_list));
9814 WARN_ON(!list_empty(&devlink->dpipe_table_list));
9815 WARN_ON(!list_empty(&devlink->sb_list));
9816 WARN_ON(!list_empty(&devlink->rate_list));
9817 WARN_ON(!list_empty(&devlink->linecard_list));
9818 WARN_ON(!list_empty(&devlink->port_list));
9819
9820 xa_destroy(&devlink->snapshot_ids);
9821 xa_erase(&devlinks, devlink->index);
9822
9823 kfree(devlink);
9824 }
9825 EXPORT_SYMBOL_GPL(devlink_free);
9826
devlink_port_type_warn(struct work_struct * work)9827 static void devlink_port_type_warn(struct work_struct *work)
9828 {
9829 WARN(true, "Type was not set for devlink port.");
9830 }
9831
devlink_port_type_should_warn(struct devlink_port * devlink_port)9832 static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
9833 {
9834 /* Ignore CPU and DSA flavours. */
9835 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
9836 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA &&
9837 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_UNUSED;
9838 }
9839
9840 #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
9841
devlink_port_type_warn_schedule(struct devlink_port * devlink_port)9842 static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
9843 {
9844 if (!devlink_port_type_should_warn(devlink_port))
9845 return;
9846 /* Schedule a work to WARN in case driver does not set port
9847 * type within timeout.
9848 */
9849 schedule_delayed_work(&devlink_port->type_warn_dw,
9850 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
9851 }
9852
devlink_port_type_warn_cancel(struct devlink_port * devlink_port)9853 static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
9854 {
9855 if (!devlink_port_type_should_warn(devlink_port))
9856 return;
9857 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
9858 }
9859
9860 /**
9861 * devlink_port_init() - Init devlink port
9862 *
9863 * @devlink: devlink
9864 * @devlink_port: devlink port
9865 *
9866 * Initialize essencial stuff that is needed for functions
9867 * that may be called before devlink port registration.
9868 * Call to this function is optional and not needed
9869 * in case the driver does not use such functions.
9870 */
devlink_port_init(struct devlink * devlink,struct devlink_port * devlink_port)9871 void devlink_port_init(struct devlink *devlink,
9872 struct devlink_port *devlink_port)
9873 {
9874 if (devlink_port->initialized)
9875 return;
9876 devlink_port->devlink = devlink;
9877 INIT_LIST_HEAD(&devlink_port->region_list);
9878 devlink_port->initialized = true;
9879 }
9880 EXPORT_SYMBOL_GPL(devlink_port_init);
9881
9882 /**
9883 * devlink_port_fini() - Deinitialize devlink port
9884 *
9885 * @devlink_port: devlink port
9886 *
9887 * Deinitialize essencial stuff that is in use for functions
9888 * that may be called after devlink port unregistration.
9889 * Call to this function is optional and not needed
9890 * in case the driver does not use such functions.
9891 */
devlink_port_fini(struct devlink_port * devlink_port)9892 void devlink_port_fini(struct devlink_port *devlink_port)
9893 {
9894 WARN_ON(!list_empty(&devlink_port->region_list));
9895 }
9896 EXPORT_SYMBOL_GPL(devlink_port_fini);
9897
9898 /**
9899 * devl_port_register() - Register devlink port
9900 *
9901 * @devlink: devlink
9902 * @devlink_port: devlink port
9903 * @port_index: driver-specific numerical identifier of the port
9904 *
9905 * Register devlink port with provided port index. User can use
9906 * any indexing, even hw-related one. devlink_port structure
9907 * is convenient to be embedded inside user driver private structure.
9908 * Note that the caller should take care of zeroing the devlink_port
9909 * structure.
9910 */
devl_port_register(struct devlink * devlink,struct devlink_port * devlink_port,unsigned int port_index)9911 int devl_port_register(struct devlink *devlink,
9912 struct devlink_port *devlink_port,
9913 unsigned int port_index)
9914 {
9915 devl_assert_locked(devlink);
9916
9917 if (devlink_port_index_exists(devlink, port_index))
9918 return -EEXIST;
9919
9920 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9921
9922 devlink_port_init(devlink, devlink_port);
9923 devlink_port->registered = true;
9924 devlink_port->index = port_index;
9925 spin_lock_init(&devlink_port->type_lock);
9926 INIT_LIST_HEAD(&devlink_port->reporter_list);
9927 mutex_init(&devlink_port->reporters_lock);
9928 list_add_tail(&devlink_port->list, &devlink->port_list);
9929
9930 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
9931 devlink_port_type_warn_schedule(devlink_port);
9932 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
9933 return 0;
9934 }
9935 EXPORT_SYMBOL_GPL(devl_port_register);
9936
9937 /**
9938 * devlink_port_register - Register devlink port
9939 *
9940 * @devlink: devlink
9941 * @devlink_port: devlink port
9942 * @port_index: driver-specific numerical identifier of the port
9943 *
9944 * Register devlink port with provided port index. User can use
9945 * any indexing, even hw-related one. devlink_port structure
9946 * is convenient to be embedded inside user driver private structure.
9947 * Note that the caller should take care of zeroing the devlink_port
9948 * structure.
9949 *
9950 * Context: Takes and release devlink->lock <mutex>.
9951 */
devlink_port_register(struct devlink * devlink,struct devlink_port * devlink_port,unsigned int port_index)9952 int devlink_port_register(struct devlink *devlink,
9953 struct devlink_port *devlink_port,
9954 unsigned int port_index)
9955 {
9956 int err;
9957
9958 devl_lock(devlink);
9959 err = devl_port_register(devlink, devlink_port, port_index);
9960 devl_unlock(devlink);
9961 return err;
9962 }
9963 EXPORT_SYMBOL_GPL(devlink_port_register);
9964
9965 /**
9966 * devl_port_unregister() - Unregister devlink port
9967 *
9968 * @devlink_port: devlink port
9969 */
devl_port_unregister(struct devlink_port * devlink_port)9970 void devl_port_unregister(struct devlink_port *devlink_port)
9971 {
9972 lockdep_assert_held(&devlink_port->devlink->lock);
9973
9974 devlink_port_type_warn_cancel(devlink_port);
9975 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
9976 list_del(&devlink_port->list);
9977 WARN_ON(!list_empty(&devlink_port->reporter_list));
9978 mutex_destroy(&devlink_port->reporters_lock);
9979 devlink_port->registered = false;
9980 }
9981 EXPORT_SYMBOL_GPL(devl_port_unregister);
9982
9983 /**
9984 * devlink_port_unregister - Unregister devlink port
9985 *
9986 * @devlink_port: devlink port
9987 *
9988 * Context: Takes and release devlink->lock <mutex>.
9989 */
devlink_port_unregister(struct devlink_port * devlink_port)9990 void devlink_port_unregister(struct devlink_port *devlink_port)
9991 {
9992 struct devlink *devlink = devlink_port->devlink;
9993
9994 devl_lock(devlink);
9995 devl_port_unregister(devlink_port);
9996 devl_unlock(devlink);
9997 }
9998 EXPORT_SYMBOL_GPL(devlink_port_unregister);
9999
__devlink_port_type_set(struct devlink_port * devlink_port,enum devlink_port_type type,void * type_dev)10000 static void __devlink_port_type_set(struct devlink_port *devlink_port,
10001 enum devlink_port_type type,
10002 void *type_dev)
10003 {
10004 ASSERT_DEVLINK_PORT_REGISTERED(devlink_port);
10005
10006 devlink_port_type_warn_cancel(devlink_port);
10007 spin_lock_bh(&devlink_port->type_lock);
10008 devlink_port->type = type;
10009 devlink_port->type_dev = type_dev;
10010 spin_unlock_bh(&devlink_port->type_lock);
10011 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
10012 }
10013
devlink_port_type_netdev_checks(struct devlink_port * devlink_port,struct net_device * netdev)10014 static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port,
10015 struct net_device *netdev)
10016 {
10017 const struct net_device_ops *ops = netdev->netdev_ops;
10018
10019 /* If driver registers devlink port, it should set devlink port
10020 * attributes accordingly so the compat functions are called
10021 * and the original ops are not used.
10022 */
10023 if (ops->ndo_get_phys_port_name) {
10024 /* Some drivers use the same set of ndos for netdevs
10025 * that have devlink_port registered and also for
10026 * those who don't. Make sure that ndo_get_phys_port_name
10027 * returns -EOPNOTSUPP here in case it is defined.
10028 * Warn if not.
10029 */
10030 char name[IFNAMSIZ];
10031 int err;
10032
10033 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
10034 WARN_ON(err != -EOPNOTSUPP);
10035 }
10036 if (ops->ndo_get_port_parent_id) {
10037 /* Some drivers use the same set of ndos for netdevs
10038 * that have devlink_port registered and also for
10039 * those who don't. Make sure that ndo_get_port_parent_id
10040 * returns -EOPNOTSUPP here in case it is defined.
10041 * Warn if not.
10042 */
10043 struct netdev_phys_item_id ppid;
10044 int err;
10045
10046 err = ops->ndo_get_port_parent_id(netdev, &ppid);
10047 WARN_ON(err != -EOPNOTSUPP);
10048 }
10049 }
10050
10051 /**
10052 * devlink_port_type_eth_set - Set port type to Ethernet
10053 *
10054 * @devlink_port: devlink port
10055 * @netdev: related netdevice
10056 */
devlink_port_type_eth_set(struct devlink_port * devlink_port,struct net_device * netdev)10057 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
10058 struct net_device *netdev)
10059 {
10060 if (netdev)
10061 devlink_port_type_netdev_checks(devlink_port, netdev);
10062 else
10063 dev_warn(devlink_port->devlink->dev,
10064 "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
10065 devlink_port->index);
10066
10067 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
10068 }
10069 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
10070
10071 /**
10072 * devlink_port_type_ib_set - Set port type to InfiniBand
10073 *
10074 * @devlink_port: devlink port
10075 * @ibdev: related IB device
10076 */
devlink_port_type_ib_set(struct devlink_port * devlink_port,struct ib_device * ibdev)10077 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
10078 struct ib_device *ibdev)
10079 {
10080 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
10081 }
10082 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
10083
10084 /**
10085 * devlink_port_type_clear - Clear port type
10086 *
10087 * @devlink_port: devlink port
10088 */
devlink_port_type_clear(struct devlink_port * devlink_port)10089 void devlink_port_type_clear(struct devlink_port *devlink_port)
10090 {
10091 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
10092 devlink_port_type_warn_schedule(devlink_port);
10093 }
10094 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
10095
__devlink_port_attrs_set(struct devlink_port * devlink_port,enum devlink_port_flavour flavour)10096 static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
10097 enum devlink_port_flavour flavour)
10098 {
10099 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10100
10101 devlink_port->attrs_set = true;
10102 attrs->flavour = flavour;
10103 if (attrs->switch_id.id_len) {
10104 devlink_port->switch_port = true;
10105 if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN))
10106 attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN;
10107 } else {
10108 devlink_port->switch_port = false;
10109 }
10110 return 0;
10111 }
10112
10113 /**
10114 * devlink_port_attrs_set - Set port attributes
10115 *
10116 * @devlink_port: devlink port
10117 * @attrs: devlink port attrs
10118 */
devlink_port_attrs_set(struct devlink_port * devlink_port,struct devlink_port_attrs * attrs)10119 void devlink_port_attrs_set(struct devlink_port *devlink_port,
10120 struct devlink_port_attrs *attrs)
10121 {
10122 int ret;
10123
10124 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10125
10126 devlink_port->attrs = *attrs;
10127 ret = __devlink_port_attrs_set(devlink_port, attrs->flavour);
10128 if (ret)
10129 return;
10130 WARN_ON(attrs->splittable && attrs->split);
10131 }
10132 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
10133
10134 /**
10135 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
10136 *
10137 * @devlink_port: devlink port
10138 * @controller: associated controller number for the devlink port instance
10139 * @pf: associated PF for the devlink port instance
10140 * @external: indicates if the port is for an external controller
10141 */
devlink_port_attrs_pci_pf_set(struct devlink_port * devlink_port,u32 controller,u16 pf,bool external)10142 void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
10143 u16 pf, bool external)
10144 {
10145 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10146 int ret;
10147
10148 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10149
10150 ret = __devlink_port_attrs_set(devlink_port,
10151 DEVLINK_PORT_FLAVOUR_PCI_PF);
10152 if (ret)
10153 return;
10154 attrs->pci_pf.controller = controller;
10155 attrs->pci_pf.pf = pf;
10156 attrs->pci_pf.external = external;
10157 }
10158 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
10159
10160 /**
10161 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
10162 *
10163 * @devlink_port: devlink port
10164 * @controller: associated controller number for the devlink port instance
10165 * @pf: associated PF for the devlink port instance
10166 * @vf: associated VF of a PF for the devlink port instance
10167 * @external: indicates if the port is for an external controller
10168 */
devlink_port_attrs_pci_vf_set(struct devlink_port * devlink_port,u32 controller,u16 pf,u16 vf,bool external)10169 void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
10170 u16 pf, u16 vf, bool external)
10171 {
10172 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10173 int ret;
10174
10175 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10176
10177 ret = __devlink_port_attrs_set(devlink_port,
10178 DEVLINK_PORT_FLAVOUR_PCI_VF);
10179 if (ret)
10180 return;
10181 attrs->pci_vf.controller = controller;
10182 attrs->pci_vf.pf = pf;
10183 attrs->pci_vf.vf = vf;
10184 attrs->pci_vf.external = external;
10185 }
10186 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
10187
10188 /**
10189 * devlink_port_attrs_pci_sf_set - Set PCI SF port attributes
10190 *
10191 * @devlink_port: devlink port
10192 * @controller: associated controller number for the devlink port instance
10193 * @pf: associated PF for the devlink port instance
10194 * @sf: associated SF of a PF for the devlink port instance
10195 * @external: indicates if the port is for an external controller
10196 */
devlink_port_attrs_pci_sf_set(struct devlink_port * devlink_port,u32 controller,u16 pf,u32 sf,bool external)10197 void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller,
10198 u16 pf, u32 sf, bool external)
10199 {
10200 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10201 int ret;
10202
10203 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10204
10205 ret = __devlink_port_attrs_set(devlink_port,
10206 DEVLINK_PORT_FLAVOUR_PCI_SF);
10207 if (ret)
10208 return;
10209 attrs->pci_sf.controller = controller;
10210 attrs->pci_sf.pf = pf;
10211 attrs->pci_sf.sf = sf;
10212 attrs->pci_sf.external = external;
10213 }
10214 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_sf_set);
10215
10216 /**
10217 * devl_rate_leaf_create - create devlink rate leaf
10218 * @devlink_port: devlink port object to create rate object on
10219 * @priv: driver private data
10220 *
10221 * Create devlink rate object of type leaf on provided @devlink_port.
10222 */
devl_rate_leaf_create(struct devlink_port * devlink_port,void * priv)10223 int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv)
10224 {
10225 struct devlink *devlink = devlink_port->devlink;
10226 struct devlink_rate *devlink_rate;
10227
10228 devl_assert_locked(devlink_port->devlink);
10229
10230 if (WARN_ON(devlink_port->devlink_rate))
10231 return -EBUSY;
10232
10233 devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL);
10234 if (!devlink_rate)
10235 return -ENOMEM;
10236
10237 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF;
10238 devlink_rate->devlink = devlink;
10239 devlink_rate->devlink_port = devlink_port;
10240 devlink_rate->priv = priv;
10241 list_add_tail(&devlink_rate->list, &devlink->rate_list);
10242 devlink_port->devlink_rate = devlink_rate;
10243 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW);
10244
10245 return 0;
10246 }
10247 EXPORT_SYMBOL_GPL(devl_rate_leaf_create);
10248
10249 /**
10250 * devl_rate_leaf_destroy - destroy devlink rate leaf
10251 *
10252 * @devlink_port: devlink port linked to the rate object
10253 *
10254 * Destroy the devlink rate object of type leaf on provided @devlink_port.
10255 */
devl_rate_leaf_destroy(struct devlink_port * devlink_port)10256 void devl_rate_leaf_destroy(struct devlink_port *devlink_port)
10257 {
10258 struct devlink_rate *devlink_rate = devlink_port->devlink_rate;
10259
10260 devl_assert_locked(devlink_port->devlink);
10261 if (!devlink_rate)
10262 return;
10263
10264 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL);
10265 if (devlink_rate->parent)
10266 refcount_dec(&devlink_rate->parent->refcnt);
10267 list_del(&devlink_rate->list);
10268 devlink_port->devlink_rate = NULL;
10269 kfree(devlink_rate);
10270 }
10271 EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy);
10272
10273 /**
10274 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device
10275 * @devlink: devlink instance
10276 *
10277 * Unset parent for all rate objects and destroy all rate nodes
10278 * on specified device.
10279 */
devl_rate_nodes_destroy(struct devlink * devlink)10280 void devl_rate_nodes_destroy(struct devlink *devlink)
10281 {
10282 static struct devlink_rate *devlink_rate, *tmp;
10283 const struct devlink_ops *ops = devlink->ops;
10284
10285 devl_assert_locked(devlink);
10286
10287 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
10288 if (!devlink_rate->parent)
10289 continue;
10290
10291 refcount_dec(&devlink_rate->parent->refcnt);
10292 if (devlink_rate_is_leaf(devlink_rate))
10293 ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv,
10294 NULL, NULL);
10295 else if (devlink_rate_is_node(devlink_rate))
10296 ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv,
10297 NULL, NULL);
10298 }
10299 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) {
10300 if (devlink_rate_is_node(devlink_rate)) {
10301 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL);
10302 list_del(&devlink_rate->list);
10303 kfree(devlink_rate->name);
10304 kfree(devlink_rate);
10305 }
10306 }
10307 }
10308 EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy);
10309
10310 /**
10311 * devlink_port_linecard_set - Link port with a linecard
10312 *
10313 * @devlink_port: devlink port
10314 * @linecard: devlink linecard
10315 */
devlink_port_linecard_set(struct devlink_port * devlink_port,struct devlink_linecard * linecard)10316 void devlink_port_linecard_set(struct devlink_port *devlink_port,
10317 struct devlink_linecard *linecard)
10318 {
10319 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10320
10321 devlink_port->linecard = linecard;
10322 }
10323 EXPORT_SYMBOL_GPL(devlink_port_linecard_set);
10324
__devlink_port_phys_port_name_get(struct devlink_port * devlink_port,char * name,size_t len)10325 static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
10326 char *name, size_t len)
10327 {
10328 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10329 int n = 0;
10330
10331 if (!devlink_port->attrs_set)
10332 return -EOPNOTSUPP;
10333
10334 switch (attrs->flavour) {
10335 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
10336 if (devlink_port->linecard)
10337 n = snprintf(name, len, "l%u",
10338 devlink_port->linecard->index);
10339 if (n < len)
10340 n += snprintf(name + n, len - n, "p%u",
10341 attrs->phys.port_number);
10342 if (n < len && attrs->split)
10343 n += snprintf(name + n, len - n, "s%u",
10344 attrs->phys.split_subport_number);
10345 break;
10346 case DEVLINK_PORT_FLAVOUR_CPU:
10347 case DEVLINK_PORT_FLAVOUR_DSA:
10348 case DEVLINK_PORT_FLAVOUR_UNUSED:
10349 /* As CPU and DSA ports do not have a netdevice associated
10350 * case should not ever happen.
10351 */
10352 WARN_ON(1);
10353 return -EINVAL;
10354 case DEVLINK_PORT_FLAVOUR_PCI_PF:
10355 if (attrs->pci_pf.external) {
10356 n = snprintf(name, len, "c%u", attrs->pci_pf.controller);
10357 if (n >= len)
10358 return -EINVAL;
10359 len -= n;
10360 name += n;
10361 }
10362 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
10363 break;
10364 case DEVLINK_PORT_FLAVOUR_PCI_VF:
10365 if (attrs->pci_vf.external) {
10366 n = snprintf(name, len, "c%u", attrs->pci_vf.controller);
10367 if (n >= len)
10368 return -EINVAL;
10369 len -= n;
10370 name += n;
10371 }
10372 n = snprintf(name, len, "pf%uvf%u",
10373 attrs->pci_vf.pf, attrs->pci_vf.vf);
10374 break;
10375 case DEVLINK_PORT_FLAVOUR_PCI_SF:
10376 if (attrs->pci_sf.external) {
10377 n = snprintf(name, len, "c%u", attrs->pci_sf.controller);
10378 if (n >= len)
10379 return -EINVAL;
10380 len -= n;
10381 name += n;
10382 }
10383 n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf,
10384 attrs->pci_sf.sf);
10385 break;
10386 case DEVLINK_PORT_FLAVOUR_VIRTUAL:
10387 return -EOPNOTSUPP;
10388 }
10389
10390 if (n >= len)
10391 return -EINVAL;
10392
10393 return 0;
10394 }
10395
devlink_linecard_types_init(struct devlink_linecard * linecard)10396 static int devlink_linecard_types_init(struct devlink_linecard *linecard)
10397 {
10398 struct devlink_linecard_type *linecard_type;
10399 unsigned int count;
10400 int i;
10401
10402 count = linecard->ops->types_count(linecard, linecard->priv);
10403 linecard->types = kmalloc_array(count, sizeof(*linecard_type),
10404 GFP_KERNEL);
10405 if (!linecard->types)
10406 return -ENOMEM;
10407 linecard->types_count = count;
10408
10409 for (i = 0; i < count; i++) {
10410 linecard_type = &linecard->types[i];
10411 linecard->ops->types_get(linecard, linecard->priv, i,
10412 &linecard_type->type,
10413 &linecard_type->priv);
10414 }
10415 return 0;
10416 }
10417
devlink_linecard_types_fini(struct devlink_linecard * linecard)10418 static void devlink_linecard_types_fini(struct devlink_linecard *linecard)
10419 {
10420 kfree(linecard->types);
10421 }
10422
10423 /**
10424 * devlink_linecard_create - Create devlink linecard
10425 *
10426 * @devlink: devlink
10427 * @linecard_index: driver-specific numerical identifier of the linecard
10428 * @ops: linecards ops
10429 * @priv: user priv pointer
10430 *
10431 * Create devlink linecard instance with provided linecard index.
10432 * Caller can use any indexing, even hw-related one.
10433 *
10434 * Return: Line card structure or an ERR_PTR() encoded error code.
10435 */
10436 struct devlink_linecard *
devlink_linecard_create(struct devlink * devlink,unsigned int linecard_index,const struct devlink_linecard_ops * ops,void * priv)10437 devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
10438 const struct devlink_linecard_ops *ops, void *priv)
10439 {
10440 struct devlink_linecard *linecard;
10441 int err;
10442
10443 if (WARN_ON(!ops || !ops->provision || !ops->unprovision ||
10444 !ops->types_count || !ops->types_get))
10445 return ERR_PTR(-EINVAL);
10446
10447 mutex_lock(&devlink->linecards_lock);
10448 if (devlink_linecard_index_exists(devlink, linecard_index)) {
10449 mutex_unlock(&devlink->linecards_lock);
10450 return ERR_PTR(-EEXIST);
10451 }
10452
10453 linecard = kzalloc(sizeof(*linecard), GFP_KERNEL);
10454 if (!linecard) {
10455 mutex_unlock(&devlink->linecards_lock);
10456 return ERR_PTR(-ENOMEM);
10457 }
10458
10459 linecard->devlink = devlink;
10460 linecard->index = linecard_index;
10461 linecard->ops = ops;
10462 linecard->priv = priv;
10463 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
10464 mutex_init(&linecard->state_lock);
10465
10466 err = devlink_linecard_types_init(linecard);
10467 if (err) {
10468 mutex_destroy(&linecard->state_lock);
10469 kfree(linecard);
10470 mutex_unlock(&devlink->linecards_lock);
10471 return ERR_PTR(err);
10472 }
10473
10474 list_add_tail(&linecard->list, &devlink->linecard_list);
10475 refcount_set(&linecard->refcount, 1);
10476 mutex_unlock(&devlink->linecards_lock);
10477 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10478 return linecard;
10479 }
10480 EXPORT_SYMBOL_GPL(devlink_linecard_create);
10481
10482 /**
10483 * devlink_linecard_destroy - Destroy devlink linecard
10484 *
10485 * @linecard: devlink linecard
10486 */
devlink_linecard_destroy(struct devlink_linecard * linecard)10487 void devlink_linecard_destroy(struct devlink_linecard *linecard)
10488 {
10489 struct devlink *devlink = linecard->devlink;
10490
10491 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
10492 mutex_lock(&devlink->linecards_lock);
10493 list_del(&linecard->list);
10494 devlink_linecard_types_fini(linecard);
10495 mutex_unlock(&devlink->linecards_lock);
10496 devlink_linecard_put(linecard);
10497 }
10498 EXPORT_SYMBOL_GPL(devlink_linecard_destroy);
10499
10500 /**
10501 * devlink_linecard_provision_set - Set provisioning on linecard
10502 *
10503 * @linecard: devlink linecard
10504 * @type: linecard type
10505 *
10506 * This is either called directly from the provision() op call or
10507 * as a result of the provision() op call asynchronously.
10508 */
devlink_linecard_provision_set(struct devlink_linecard * linecard,const char * type)10509 void devlink_linecard_provision_set(struct devlink_linecard *linecard,
10510 const char *type)
10511 {
10512 mutex_lock(&linecard->state_lock);
10513 WARN_ON(linecard->type && strcmp(linecard->type, type));
10514 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
10515 linecard->type = type;
10516 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10517 mutex_unlock(&linecard->state_lock);
10518 }
10519 EXPORT_SYMBOL_GPL(devlink_linecard_provision_set);
10520
10521 /**
10522 * devlink_linecard_provision_clear - Clear provisioning on linecard
10523 *
10524 * @linecard: devlink linecard
10525 *
10526 * This is either called directly from the unprovision() op call or
10527 * as a result of the unprovision() op call asynchronously.
10528 */
devlink_linecard_provision_clear(struct devlink_linecard * linecard)10529 void devlink_linecard_provision_clear(struct devlink_linecard *linecard)
10530 {
10531 mutex_lock(&linecard->state_lock);
10532 WARN_ON(linecard->nested_devlink);
10533 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
10534 linecard->type = NULL;
10535 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10536 mutex_unlock(&linecard->state_lock);
10537 }
10538 EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear);
10539
10540 /**
10541 * devlink_linecard_provision_fail - Fail provisioning on linecard
10542 *
10543 * @linecard: devlink linecard
10544 *
10545 * This is either called directly from the provision() op call or
10546 * as a result of the provision() op call asynchronously.
10547 */
devlink_linecard_provision_fail(struct devlink_linecard * linecard)10548 void devlink_linecard_provision_fail(struct devlink_linecard *linecard)
10549 {
10550 mutex_lock(&linecard->state_lock);
10551 WARN_ON(linecard->nested_devlink);
10552 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED;
10553 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10554 mutex_unlock(&linecard->state_lock);
10555 }
10556 EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail);
10557
10558 /**
10559 * devlink_linecard_activate - Set linecard active
10560 *
10561 * @linecard: devlink linecard
10562 */
devlink_linecard_activate(struct devlink_linecard * linecard)10563 void devlink_linecard_activate(struct devlink_linecard *linecard)
10564 {
10565 mutex_lock(&linecard->state_lock);
10566 WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED);
10567 linecard->state = DEVLINK_LINECARD_STATE_ACTIVE;
10568 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10569 mutex_unlock(&linecard->state_lock);
10570 }
10571 EXPORT_SYMBOL_GPL(devlink_linecard_activate);
10572
10573 /**
10574 * devlink_linecard_deactivate - Set linecard inactive
10575 *
10576 * @linecard: devlink linecard
10577 */
devlink_linecard_deactivate(struct devlink_linecard * linecard)10578 void devlink_linecard_deactivate(struct devlink_linecard *linecard)
10579 {
10580 mutex_lock(&linecard->state_lock);
10581 switch (linecard->state) {
10582 case DEVLINK_LINECARD_STATE_ACTIVE:
10583 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
10584 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10585 break;
10586 case DEVLINK_LINECARD_STATE_UNPROVISIONING:
10587 /* Line card is being deactivated as part
10588 * of unprovisioning flow.
10589 */
10590 break;
10591 default:
10592 WARN_ON(1);
10593 break;
10594 }
10595 mutex_unlock(&linecard->state_lock);
10596 }
10597 EXPORT_SYMBOL_GPL(devlink_linecard_deactivate);
10598
10599 /**
10600 * devlink_linecard_nested_dl_set - Attach/detach nested devlink
10601 * instance to linecard.
10602 *
10603 * @linecard: devlink linecard
10604 * @nested_devlink: devlink instance to attach or NULL to detach
10605 */
devlink_linecard_nested_dl_set(struct devlink_linecard * linecard,struct devlink * nested_devlink)10606 void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard,
10607 struct devlink *nested_devlink)
10608 {
10609 mutex_lock(&linecard->state_lock);
10610 linecard->nested_devlink = nested_devlink;
10611 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10612 mutex_unlock(&linecard->state_lock);
10613 }
10614 EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set);
10615
devl_sb_register(struct devlink * devlink,unsigned int sb_index,u32 size,u16 ingress_pools_count,u16 egress_pools_count,u16 ingress_tc_count,u16 egress_tc_count)10616 int devl_sb_register(struct devlink *devlink, unsigned int sb_index,
10617 u32 size, u16 ingress_pools_count,
10618 u16 egress_pools_count, u16 ingress_tc_count,
10619 u16 egress_tc_count)
10620 {
10621 struct devlink_sb *devlink_sb;
10622
10623 lockdep_assert_held(&devlink->lock);
10624
10625 if (devlink_sb_index_exists(devlink, sb_index))
10626 return -EEXIST;
10627
10628 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
10629 if (!devlink_sb)
10630 return -ENOMEM;
10631 devlink_sb->index = sb_index;
10632 devlink_sb->size = size;
10633 devlink_sb->ingress_pools_count = ingress_pools_count;
10634 devlink_sb->egress_pools_count = egress_pools_count;
10635 devlink_sb->ingress_tc_count = ingress_tc_count;
10636 devlink_sb->egress_tc_count = egress_tc_count;
10637 list_add_tail(&devlink_sb->list, &devlink->sb_list);
10638 return 0;
10639 }
10640 EXPORT_SYMBOL_GPL(devl_sb_register);
10641
devlink_sb_register(struct devlink * devlink,unsigned int sb_index,u32 size,u16 ingress_pools_count,u16 egress_pools_count,u16 ingress_tc_count,u16 egress_tc_count)10642 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
10643 u32 size, u16 ingress_pools_count,
10644 u16 egress_pools_count, u16 ingress_tc_count,
10645 u16 egress_tc_count)
10646 {
10647 int err;
10648
10649 devl_lock(devlink);
10650 err = devl_sb_register(devlink, sb_index, size, ingress_pools_count,
10651 egress_pools_count, ingress_tc_count,
10652 egress_tc_count);
10653 devl_unlock(devlink);
10654 return err;
10655 }
10656 EXPORT_SYMBOL_GPL(devlink_sb_register);
10657
devl_sb_unregister(struct devlink * devlink,unsigned int sb_index)10658 void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
10659 {
10660 struct devlink_sb *devlink_sb;
10661
10662 lockdep_assert_held(&devlink->lock);
10663
10664 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
10665 WARN_ON(!devlink_sb);
10666 list_del(&devlink_sb->list);
10667 kfree(devlink_sb);
10668 }
10669 EXPORT_SYMBOL_GPL(devl_sb_unregister);
10670
devlink_sb_unregister(struct devlink * devlink,unsigned int sb_index)10671 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
10672 {
10673 devl_lock(devlink);
10674 devl_sb_unregister(devlink, sb_index);
10675 devl_unlock(devlink);
10676 }
10677 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
10678
10679 /**
10680 * devl_dpipe_headers_register - register dpipe headers
10681 *
10682 * @devlink: devlink
10683 * @dpipe_headers: dpipe header array
10684 *
10685 * Register the headers supported by hardware.
10686 */
devl_dpipe_headers_register(struct devlink * devlink,struct devlink_dpipe_headers * dpipe_headers)10687 void devl_dpipe_headers_register(struct devlink *devlink,
10688 struct devlink_dpipe_headers *dpipe_headers)
10689 {
10690 lockdep_assert_held(&devlink->lock);
10691
10692 devlink->dpipe_headers = dpipe_headers;
10693 }
10694 EXPORT_SYMBOL_GPL(devl_dpipe_headers_register);
10695
10696 /**
10697 * devl_dpipe_headers_unregister - unregister dpipe headers
10698 *
10699 * @devlink: devlink
10700 *
10701 * Unregister the headers supported by hardware.
10702 */
devl_dpipe_headers_unregister(struct devlink * devlink)10703 void devl_dpipe_headers_unregister(struct devlink *devlink)
10704 {
10705 lockdep_assert_held(&devlink->lock);
10706
10707 devlink->dpipe_headers = NULL;
10708 }
10709 EXPORT_SYMBOL_GPL(devl_dpipe_headers_unregister);
10710
10711 /**
10712 * devlink_dpipe_table_counter_enabled - check if counter allocation
10713 * required
10714 * @devlink: devlink
10715 * @table_name: tables name
10716 *
10717 * Used by driver to check if counter allocation is required.
10718 * After counter allocation is turned on the table entries
10719 * are updated to include counter statistics.
10720 *
10721 * After that point on the driver must respect the counter
10722 * state so that each entry added to the table is added
10723 * with a counter.
10724 */
devlink_dpipe_table_counter_enabled(struct devlink * devlink,const char * table_name)10725 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
10726 const char *table_name)
10727 {
10728 struct devlink_dpipe_table *table;
10729 bool enabled;
10730
10731 rcu_read_lock();
10732 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
10733 table_name, devlink);
10734 enabled = false;
10735 if (table)
10736 enabled = table->counters_enabled;
10737 rcu_read_unlock();
10738 return enabled;
10739 }
10740 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
10741
10742 /**
10743 * devl_dpipe_table_register - register dpipe table
10744 *
10745 * @devlink: devlink
10746 * @table_name: table name
10747 * @table_ops: table ops
10748 * @priv: priv
10749 * @counter_control_extern: external control for counters
10750 */
devl_dpipe_table_register(struct devlink * devlink,const char * table_name,struct devlink_dpipe_table_ops * table_ops,void * priv,bool counter_control_extern)10751 int devl_dpipe_table_register(struct devlink *devlink,
10752 const char *table_name,
10753 struct devlink_dpipe_table_ops *table_ops,
10754 void *priv, bool counter_control_extern)
10755 {
10756 struct devlink_dpipe_table *table;
10757
10758 lockdep_assert_held(&devlink->lock);
10759
10760 if (WARN_ON(!table_ops->size_get))
10761 return -EINVAL;
10762
10763 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
10764 devlink))
10765 return -EEXIST;
10766
10767 table = kzalloc(sizeof(*table), GFP_KERNEL);
10768 if (!table)
10769 return -ENOMEM;
10770
10771 table->name = table_name;
10772 table->table_ops = table_ops;
10773 table->priv = priv;
10774 table->counter_control_extern = counter_control_extern;
10775
10776 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
10777
10778 return 0;
10779 }
10780 EXPORT_SYMBOL_GPL(devl_dpipe_table_register);
10781
10782 /**
10783 * devl_dpipe_table_unregister - unregister dpipe table
10784 *
10785 * @devlink: devlink
10786 * @table_name: table name
10787 */
devl_dpipe_table_unregister(struct devlink * devlink,const char * table_name)10788 void devl_dpipe_table_unregister(struct devlink *devlink,
10789 const char *table_name)
10790 {
10791 struct devlink_dpipe_table *table;
10792
10793 lockdep_assert_held(&devlink->lock);
10794
10795 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
10796 table_name, devlink);
10797 if (!table)
10798 return;
10799 list_del_rcu(&table->list);
10800 kfree_rcu(table, rcu);
10801 }
10802 EXPORT_SYMBOL_GPL(devl_dpipe_table_unregister);
10803
10804 /**
10805 * devl_resource_register - devlink resource register
10806 *
10807 * @devlink: devlink
10808 * @resource_name: resource's name
10809 * @resource_size: resource's size
10810 * @resource_id: resource's id
10811 * @parent_resource_id: resource's parent id
10812 * @size_params: size parameters
10813 *
10814 * Generic resources should reuse the same names across drivers.
10815 * Please see the generic resources list at:
10816 * Documentation/networking/devlink/devlink-resource.rst
10817 */
devl_resource_register(struct devlink * devlink,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * size_params)10818 int devl_resource_register(struct devlink *devlink,
10819 const char *resource_name,
10820 u64 resource_size,
10821 u64 resource_id,
10822 u64 parent_resource_id,
10823 const struct devlink_resource_size_params *size_params)
10824 {
10825 struct devlink_resource *resource;
10826 struct list_head *resource_list;
10827 bool top_hierarchy;
10828
10829 lockdep_assert_held(&devlink->lock);
10830
10831 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
10832
10833 resource = devlink_resource_find(devlink, NULL, resource_id);
10834 if (resource)
10835 return -EINVAL;
10836
10837 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
10838 if (!resource)
10839 return -ENOMEM;
10840
10841 if (top_hierarchy) {
10842 resource_list = &devlink->resource_list;
10843 } else {
10844 struct devlink_resource *parent_resource;
10845
10846 parent_resource = devlink_resource_find(devlink, NULL,
10847 parent_resource_id);
10848 if (parent_resource) {
10849 resource_list = &parent_resource->resource_list;
10850 resource->parent = parent_resource;
10851 } else {
10852 kfree(resource);
10853 return -EINVAL;
10854 }
10855 }
10856
10857 resource->name = resource_name;
10858 resource->size = resource_size;
10859 resource->size_new = resource_size;
10860 resource->id = resource_id;
10861 resource->size_valid = true;
10862 memcpy(&resource->size_params, size_params,
10863 sizeof(resource->size_params));
10864 INIT_LIST_HEAD(&resource->resource_list);
10865 list_add_tail(&resource->list, resource_list);
10866
10867 return 0;
10868 }
10869 EXPORT_SYMBOL_GPL(devl_resource_register);
10870
10871 /**
10872 * devlink_resource_register - devlink resource register
10873 *
10874 * @devlink: devlink
10875 * @resource_name: resource's name
10876 * @resource_size: resource's size
10877 * @resource_id: resource's id
10878 * @parent_resource_id: resource's parent id
10879 * @size_params: size parameters
10880 *
10881 * Generic resources should reuse the same names across drivers.
10882 * Please see the generic resources list at:
10883 * Documentation/networking/devlink/devlink-resource.rst
10884 *
10885 * Context: Takes and release devlink->lock <mutex>.
10886 */
devlink_resource_register(struct devlink * devlink,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * size_params)10887 int devlink_resource_register(struct devlink *devlink,
10888 const char *resource_name,
10889 u64 resource_size,
10890 u64 resource_id,
10891 u64 parent_resource_id,
10892 const struct devlink_resource_size_params *size_params)
10893 {
10894 int err;
10895
10896 devl_lock(devlink);
10897 err = devl_resource_register(devlink, resource_name, resource_size,
10898 resource_id, parent_resource_id, size_params);
10899 devl_unlock(devlink);
10900 return err;
10901 }
10902 EXPORT_SYMBOL_GPL(devlink_resource_register);
10903
devlink_resource_unregister(struct devlink * devlink,struct devlink_resource * resource)10904 static void devlink_resource_unregister(struct devlink *devlink,
10905 struct devlink_resource *resource)
10906 {
10907 struct devlink_resource *tmp, *child_resource;
10908
10909 list_for_each_entry_safe(child_resource, tmp, &resource->resource_list,
10910 list) {
10911 devlink_resource_unregister(devlink, child_resource);
10912 list_del(&child_resource->list);
10913 kfree(child_resource);
10914 }
10915 }
10916
10917 /**
10918 * devl_resources_unregister - free all resources
10919 *
10920 * @devlink: devlink
10921 */
devl_resources_unregister(struct devlink * devlink)10922 void devl_resources_unregister(struct devlink *devlink)
10923 {
10924 struct devlink_resource *tmp, *child_resource;
10925
10926 lockdep_assert_held(&devlink->lock);
10927
10928 list_for_each_entry_safe(child_resource, tmp, &devlink->resource_list,
10929 list) {
10930 devlink_resource_unregister(devlink, child_resource);
10931 list_del(&child_resource->list);
10932 kfree(child_resource);
10933 }
10934 }
10935 EXPORT_SYMBOL_GPL(devl_resources_unregister);
10936
10937 /**
10938 * devlink_resources_unregister - free all resources
10939 *
10940 * @devlink: devlink
10941 *
10942 * Context: Takes and release devlink->lock <mutex>.
10943 */
devlink_resources_unregister(struct devlink * devlink)10944 void devlink_resources_unregister(struct devlink *devlink)
10945 {
10946 devl_lock(devlink);
10947 devl_resources_unregister(devlink);
10948 devl_unlock(devlink);
10949 }
10950 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
10951
10952 /**
10953 * devl_resource_size_get - get and update size
10954 *
10955 * @devlink: devlink
10956 * @resource_id: the requested resource id
10957 * @p_resource_size: ptr to update
10958 */
devl_resource_size_get(struct devlink * devlink,u64 resource_id,u64 * p_resource_size)10959 int devl_resource_size_get(struct devlink *devlink,
10960 u64 resource_id,
10961 u64 *p_resource_size)
10962 {
10963 struct devlink_resource *resource;
10964
10965 lockdep_assert_held(&devlink->lock);
10966
10967 resource = devlink_resource_find(devlink, NULL, resource_id);
10968 if (!resource)
10969 return -EINVAL;
10970 *p_resource_size = resource->size_new;
10971 resource->size = resource->size_new;
10972 return 0;
10973 }
10974 EXPORT_SYMBOL_GPL(devl_resource_size_get);
10975
10976 /**
10977 * devl_dpipe_table_resource_set - set the resource id
10978 *
10979 * @devlink: devlink
10980 * @table_name: table name
10981 * @resource_id: resource id
10982 * @resource_units: number of resource's units consumed per table's entry
10983 */
devl_dpipe_table_resource_set(struct devlink * devlink,const char * table_name,u64 resource_id,u64 resource_units)10984 int devl_dpipe_table_resource_set(struct devlink *devlink,
10985 const char *table_name, u64 resource_id,
10986 u64 resource_units)
10987 {
10988 struct devlink_dpipe_table *table;
10989
10990 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
10991 table_name, devlink);
10992 if (!table)
10993 return -EINVAL;
10994
10995 table->resource_id = resource_id;
10996 table->resource_units = resource_units;
10997 table->resource_valid = true;
10998 return 0;
10999 }
11000 EXPORT_SYMBOL_GPL(devl_dpipe_table_resource_set);
11001
11002 /**
11003 * devl_resource_occ_get_register - register occupancy getter
11004 *
11005 * @devlink: devlink
11006 * @resource_id: resource id
11007 * @occ_get: occupancy getter callback
11008 * @occ_get_priv: occupancy getter callback priv
11009 */
devl_resource_occ_get_register(struct devlink * devlink,u64 resource_id,devlink_resource_occ_get_t * occ_get,void * occ_get_priv)11010 void devl_resource_occ_get_register(struct devlink *devlink,
11011 u64 resource_id,
11012 devlink_resource_occ_get_t *occ_get,
11013 void *occ_get_priv)
11014 {
11015 struct devlink_resource *resource;
11016
11017 lockdep_assert_held(&devlink->lock);
11018
11019 resource = devlink_resource_find(devlink, NULL, resource_id);
11020 if (WARN_ON(!resource))
11021 return;
11022 WARN_ON(resource->occ_get);
11023
11024 resource->occ_get = occ_get;
11025 resource->occ_get_priv = occ_get_priv;
11026 }
11027 EXPORT_SYMBOL_GPL(devl_resource_occ_get_register);
11028
11029 /**
11030 * devlink_resource_occ_get_register - register occupancy getter
11031 *
11032 * @devlink: devlink
11033 * @resource_id: resource id
11034 * @occ_get: occupancy getter callback
11035 * @occ_get_priv: occupancy getter callback priv
11036 *
11037 * Context: Takes and release devlink->lock <mutex>.
11038 */
devlink_resource_occ_get_register(struct devlink * devlink,u64 resource_id,devlink_resource_occ_get_t * occ_get,void * occ_get_priv)11039 void devlink_resource_occ_get_register(struct devlink *devlink,
11040 u64 resource_id,
11041 devlink_resource_occ_get_t *occ_get,
11042 void *occ_get_priv)
11043 {
11044 devl_lock(devlink);
11045 devl_resource_occ_get_register(devlink, resource_id,
11046 occ_get, occ_get_priv);
11047 devl_unlock(devlink);
11048 }
11049 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
11050
11051 /**
11052 * devl_resource_occ_get_unregister - unregister occupancy getter
11053 *
11054 * @devlink: devlink
11055 * @resource_id: resource id
11056 */
devl_resource_occ_get_unregister(struct devlink * devlink,u64 resource_id)11057 void devl_resource_occ_get_unregister(struct devlink *devlink,
11058 u64 resource_id)
11059 {
11060 struct devlink_resource *resource;
11061
11062 lockdep_assert_held(&devlink->lock);
11063
11064 resource = devlink_resource_find(devlink, NULL, resource_id);
11065 if (WARN_ON(!resource))
11066 return;
11067 WARN_ON(!resource->occ_get);
11068
11069 resource->occ_get = NULL;
11070 resource->occ_get_priv = NULL;
11071 }
11072 EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister);
11073
11074 /**
11075 * devlink_resource_occ_get_unregister - unregister occupancy getter
11076 *
11077 * @devlink: devlink
11078 * @resource_id: resource id
11079 *
11080 * Context: Takes and release devlink->lock <mutex>.
11081 */
devlink_resource_occ_get_unregister(struct devlink * devlink,u64 resource_id)11082 void devlink_resource_occ_get_unregister(struct devlink *devlink,
11083 u64 resource_id)
11084 {
11085 devl_lock(devlink);
11086 devl_resource_occ_get_unregister(devlink, resource_id);
11087 devl_unlock(devlink);
11088 }
11089 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
11090
devlink_param_verify(const struct devlink_param * param)11091 static int devlink_param_verify(const struct devlink_param *param)
11092 {
11093 if (!param || !param->name || !param->supported_cmodes)
11094 return -EINVAL;
11095 if (param->generic)
11096 return devlink_param_generic_verify(param);
11097 else
11098 return devlink_param_driver_verify(param);
11099 }
11100
11101 /**
11102 * devlink_params_register - register configuration parameters
11103 *
11104 * @devlink: devlink
11105 * @params: configuration parameters array
11106 * @params_count: number of parameters provided
11107 *
11108 * Register the configuration parameters supported by the driver.
11109 */
devlink_params_register(struct devlink * devlink,const struct devlink_param * params,size_t params_count)11110 int devlink_params_register(struct devlink *devlink,
11111 const struct devlink_param *params,
11112 size_t params_count)
11113 {
11114 const struct devlink_param *param = params;
11115 int i, err;
11116
11117 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
11118
11119 for (i = 0; i < params_count; i++, param++) {
11120 err = devlink_param_register(devlink, param);
11121 if (err)
11122 goto rollback;
11123 }
11124 return 0;
11125
11126 rollback:
11127 if (!i)
11128 return err;
11129
11130 for (param--; i > 0; i--, param--)
11131 devlink_param_unregister(devlink, param);
11132 return err;
11133 }
11134 EXPORT_SYMBOL_GPL(devlink_params_register);
11135
11136 /**
11137 * devlink_params_unregister - unregister configuration parameters
11138 * @devlink: devlink
11139 * @params: configuration parameters to unregister
11140 * @params_count: number of parameters provided
11141 */
devlink_params_unregister(struct devlink * devlink,const struct devlink_param * params,size_t params_count)11142 void devlink_params_unregister(struct devlink *devlink,
11143 const struct devlink_param *params,
11144 size_t params_count)
11145 {
11146 const struct devlink_param *param = params;
11147 int i;
11148
11149 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
11150
11151 for (i = 0; i < params_count; i++, param++)
11152 devlink_param_unregister(devlink, param);
11153 }
11154 EXPORT_SYMBOL_GPL(devlink_params_unregister);
11155
11156 /**
11157 * devlink_param_register - register one configuration parameter
11158 *
11159 * @devlink: devlink
11160 * @param: one configuration parameter
11161 *
11162 * Register the configuration parameter supported by the driver.
11163 * Return: returns 0 on successful registration or error code otherwise.
11164 */
devlink_param_register(struct devlink * devlink,const struct devlink_param * param)11165 int devlink_param_register(struct devlink *devlink,
11166 const struct devlink_param *param)
11167 {
11168 struct devlink_param_item *param_item;
11169
11170 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
11171
11172 WARN_ON(devlink_param_verify(param));
11173 WARN_ON(devlink_param_find_by_name(&devlink->param_list, param->name));
11174
11175 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
11176 WARN_ON(param->get || param->set);
11177 else
11178 WARN_ON(!param->get || !param->set);
11179
11180 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
11181 if (!param_item)
11182 return -ENOMEM;
11183
11184 param_item->param = param;
11185
11186 list_add_tail(¶m_item->list, &devlink->param_list);
11187 return 0;
11188 }
11189 EXPORT_SYMBOL_GPL(devlink_param_register);
11190
11191 /**
11192 * devlink_param_unregister - unregister one configuration parameter
11193 * @devlink: devlink
11194 * @param: configuration parameter to unregister
11195 */
devlink_param_unregister(struct devlink * devlink,const struct devlink_param * param)11196 void devlink_param_unregister(struct devlink *devlink,
11197 const struct devlink_param *param)
11198 {
11199 struct devlink_param_item *param_item;
11200
11201 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
11202
11203 param_item =
11204 devlink_param_find_by_name(&devlink->param_list, param->name);
11205 WARN_ON(!param_item);
11206 list_del(¶m_item->list);
11207 kfree(param_item);
11208 }
11209 EXPORT_SYMBOL_GPL(devlink_param_unregister);
11210
11211 /**
11212 * devlink_param_driverinit_value_get - get configuration parameter
11213 * value for driver initializing
11214 *
11215 * @devlink: devlink
11216 * @param_id: parameter ID
11217 * @init_val: value of parameter in driverinit configuration mode
11218 *
11219 * This function should be used by the driver to get driverinit
11220 * configuration for initialization after reload command.
11221 */
devlink_param_driverinit_value_get(struct devlink * devlink,u32 param_id,union devlink_param_value * init_val)11222 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
11223 union devlink_param_value *init_val)
11224 {
11225 struct devlink_param_item *param_item;
11226
11227 if (!devlink_reload_supported(devlink->ops))
11228 return -EOPNOTSUPP;
11229
11230 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
11231 if (!param_item)
11232 return -EINVAL;
11233
11234 if (!param_item->driverinit_value_valid ||
11235 !devlink_param_cmode_is_supported(param_item->param,
11236 DEVLINK_PARAM_CMODE_DRIVERINIT))
11237 return -EOPNOTSUPP;
11238
11239 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
11240 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
11241 else
11242 *init_val = param_item->driverinit_value;
11243
11244 return 0;
11245 }
11246 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
11247
11248 /**
11249 * devlink_param_driverinit_value_set - set value of configuration
11250 * parameter for driverinit
11251 * configuration mode
11252 *
11253 * @devlink: devlink
11254 * @param_id: parameter ID
11255 * @init_val: value of parameter to set for driverinit configuration mode
11256 *
11257 * This function should be used by the driver to set driverinit
11258 * configuration mode default value.
11259 */
devlink_param_driverinit_value_set(struct devlink * devlink,u32 param_id,union devlink_param_value init_val)11260 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
11261 union devlink_param_value init_val)
11262 {
11263 struct devlink_param_item *param_item;
11264
11265 ASSERT_DEVLINK_NOT_REGISTERED(devlink);
11266
11267 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
11268 if (!param_item)
11269 return -EINVAL;
11270
11271 if (!devlink_param_cmode_is_supported(param_item->param,
11272 DEVLINK_PARAM_CMODE_DRIVERINIT))
11273 return -EOPNOTSUPP;
11274
11275 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
11276 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
11277 else
11278 param_item->driverinit_value = init_val;
11279 param_item->driverinit_value_valid = true;
11280 return 0;
11281 }
11282 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
11283
11284 /**
11285 * devlink_param_value_changed - notify devlink on a parameter's value
11286 * change. Should be called by the driver
11287 * right after the change.
11288 *
11289 * @devlink: devlink
11290 * @param_id: parameter ID
11291 *
11292 * This function should be used by the driver to notify devlink on value
11293 * change, excluding driverinit configuration mode.
11294 * For driverinit configuration mode driver should use the function
11295 */
devlink_param_value_changed(struct devlink * devlink,u32 param_id)11296 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
11297 {
11298 struct devlink_param_item *param_item;
11299
11300 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
11301 WARN_ON(!param_item);
11302
11303 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
11304 }
11305 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
11306
11307 /**
11308 * devl_region_create - create a new address region
11309 *
11310 * @devlink: devlink
11311 * @ops: region operations and name
11312 * @region_max_snapshots: Maximum supported number of snapshots for region
11313 * @region_size: size of region
11314 */
devl_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)11315 struct devlink_region *devl_region_create(struct devlink *devlink,
11316 const struct devlink_region_ops *ops,
11317 u32 region_max_snapshots,
11318 u64 region_size)
11319 {
11320 struct devlink_region *region;
11321
11322 devl_assert_locked(devlink);
11323
11324 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
11325 return ERR_PTR(-EINVAL);
11326
11327 if (devlink_region_get_by_name(devlink, ops->name))
11328 return ERR_PTR(-EEXIST);
11329
11330 region = kzalloc(sizeof(*region), GFP_KERNEL);
11331 if (!region)
11332 return ERR_PTR(-ENOMEM);
11333
11334 region->devlink = devlink;
11335 region->max_snapshots = region_max_snapshots;
11336 region->ops = ops;
11337 region->size = region_size;
11338 INIT_LIST_HEAD(®ion->snapshot_list);
11339 mutex_init(®ion->snapshot_lock);
11340 list_add_tail(®ion->list, &devlink->region_list);
11341 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
11342
11343 return region;
11344 }
11345 EXPORT_SYMBOL_GPL(devl_region_create);
11346
11347 /**
11348 * devlink_region_create - create a new address region
11349 *
11350 * @devlink: devlink
11351 * @ops: region operations and name
11352 * @region_max_snapshots: Maximum supported number of snapshots for region
11353 * @region_size: size of region
11354 *
11355 * Context: Takes and release devlink->lock <mutex>.
11356 */
11357 struct devlink_region *
devlink_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)11358 devlink_region_create(struct devlink *devlink,
11359 const struct devlink_region_ops *ops,
11360 u32 region_max_snapshots, u64 region_size)
11361 {
11362 struct devlink_region *region;
11363
11364 devl_lock(devlink);
11365 region = devl_region_create(devlink, ops, region_max_snapshots,
11366 region_size);
11367 devl_unlock(devlink);
11368 return region;
11369 }
11370 EXPORT_SYMBOL_GPL(devlink_region_create);
11371
11372 /**
11373 * devlink_port_region_create - create a new address region for a port
11374 *
11375 * @port: devlink port
11376 * @ops: region operations and name
11377 * @region_max_snapshots: Maximum supported number of snapshots for region
11378 * @region_size: size of region
11379 *
11380 * Context: Takes and release devlink->lock <mutex>.
11381 */
11382 struct devlink_region *
devlink_port_region_create(struct devlink_port * port,const struct devlink_port_region_ops * ops,u32 region_max_snapshots,u64 region_size)11383 devlink_port_region_create(struct devlink_port *port,
11384 const struct devlink_port_region_ops *ops,
11385 u32 region_max_snapshots, u64 region_size)
11386 {
11387 struct devlink *devlink = port->devlink;
11388 struct devlink_region *region;
11389 int err = 0;
11390
11391 ASSERT_DEVLINK_PORT_INITIALIZED(port);
11392
11393 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
11394 return ERR_PTR(-EINVAL);
11395
11396 devl_lock(devlink);
11397
11398 if (devlink_port_region_get_by_name(port, ops->name)) {
11399 err = -EEXIST;
11400 goto unlock;
11401 }
11402
11403 region = kzalloc(sizeof(*region), GFP_KERNEL);
11404 if (!region) {
11405 err = -ENOMEM;
11406 goto unlock;
11407 }
11408
11409 region->devlink = devlink;
11410 region->port = port;
11411 region->max_snapshots = region_max_snapshots;
11412 region->port_ops = ops;
11413 region->size = region_size;
11414 INIT_LIST_HEAD(®ion->snapshot_list);
11415 mutex_init(®ion->snapshot_lock);
11416 list_add_tail(®ion->list, &port->region_list);
11417 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
11418
11419 devl_unlock(devlink);
11420 return region;
11421
11422 unlock:
11423 devl_unlock(devlink);
11424 return ERR_PTR(err);
11425 }
11426 EXPORT_SYMBOL_GPL(devlink_port_region_create);
11427
11428 /**
11429 * devl_region_destroy - destroy address region
11430 *
11431 * @region: devlink region to destroy
11432 */
devl_region_destroy(struct devlink_region * region)11433 void devl_region_destroy(struct devlink_region *region)
11434 {
11435 struct devlink *devlink = region->devlink;
11436 struct devlink_snapshot *snapshot, *ts;
11437
11438 devl_assert_locked(devlink);
11439
11440 /* Free all snapshots of region */
11441 mutex_lock(®ion->snapshot_lock);
11442 list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list)
11443 devlink_region_snapshot_del(region, snapshot);
11444 mutex_unlock(®ion->snapshot_lock);
11445
11446 list_del(®ion->list);
11447 mutex_destroy(®ion->snapshot_lock);
11448
11449 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
11450 kfree(region);
11451 }
11452 EXPORT_SYMBOL_GPL(devl_region_destroy);
11453
11454 /**
11455 * devlink_region_destroy - destroy address region
11456 *
11457 * @region: devlink region to destroy
11458 *
11459 * Context: Takes and release devlink->lock <mutex>.
11460 */
devlink_region_destroy(struct devlink_region * region)11461 void devlink_region_destroy(struct devlink_region *region)
11462 {
11463 struct devlink *devlink = region->devlink;
11464
11465 devl_lock(devlink);
11466 devl_region_destroy(region);
11467 devl_unlock(devlink);
11468 }
11469 EXPORT_SYMBOL_GPL(devlink_region_destroy);
11470
11471 /**
11472 * devlink_region_snapshot_id_get - get snapshot ID
11473 *
11474 * This callback should be called when adding a new snapshot,
11475 * Driver should use the same id for multiple snapshots taken
11476 * on multiple regions at the same time/by the same trigger.
11477 *
11478 * The caller of this function must use devlink_region_snapshot_id_put
11479 * when finished creating regions using this id.
11480 *
11481 * Returns zero on success, or a negative error code on failure.
11482 *
11483 * @devlink: devlink
11484 * @id: storage to return id
11485 */
devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)11486 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
11487 {
11488 return __devlink_region_snapshot_id_get(devlink, id);
11489 }
11490 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
11491
11492 /**
11493 * devlink_region_snapshot_id_put - put snapshot ID reference
11494 *
11495 * This should be called by a driver after finishing creating snapshots
11496 * with an id. Doing so ensures that the ID can later be released in the
11497 * event that all snapshots using it have been destroyed.
11498 *
11499 * @devlink: devlink
11500 * @id: id to release reference on
11501 */
devlink_region_snapshot_id_put(struct devlink * devlink,u32 id)11502 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
11503 {
11504 __devlink_snapshot_id_decrement(devlink, id);
11505 }
11506 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
11507
11508 /**
11509 * devlink_region_snapshot_create - create a new snapshot
11510 * This will add a new snapshot of a region. The snapshot
11511 * will be stored on the region struct and can be accessed
11512 * from devlink. This is useful for future analyses of snapshots.
11513 * Multiple snapshots can be created on a region.
11514 * The @snapshot_id should be obtained using the getter function.
11515 *
11516 * @region: devlink region of the snapshot
11517 * @data: snapshot data
11518 * @snapshot_id: snapshot id to be created
11519 */
devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)11520 int devlink_region_snapshot_create(struct devlink_region *region,
11521 u8 *data, u32 snapshot_id)
11522 {
11523 int err;
11524
11525 mutex_lock(®ion->snapshot_lock);
11526 err = __devlink_region_snapshot_create(region, data, snapshot_id);
11527 mutex_unlock(®ion->snapshot_lock);
11528 return err;
11529 }
11530 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
11531
11532 #define DEVLINK_TRAP(_id, _type) \
11533 { \
11534 .type = DEVLINK_TRAP_TYPE_##_type, \
11535 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
11536 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
11537 }
11538
11539 static const struct devlink_trap devlink_trap_generic[] = {
11540 DEVLINK_TRAP(SMAC_MC, DROP),
11541 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
11542 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
11543 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
11544 DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
11545 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
11546 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
11547 DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
11548 DEVLINK_TRAP(TAIL_DROP, DROP),
11549 DEVLINK_TRAP(NON_IP_PACKET, DROP),
11550 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
11551 DEVLINK_TRAP(DIP_LB, DROP),
11552 DEVLINK_TRAP(SIP_MC, DROP),
11553 DEVLINK_TRAP(SIP_LB, DROP),
11554 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
11555 DEVLINK_TRAP(IPV4_SIP_BC, DROP),
11556 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
11557 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
11558 DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
11559 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
11560 DEVLINK_TRAP(RPF, EXCEPTION),
11561 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
11562 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
11563 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
11564 DEVLINK_TRAP(NON_ROUTABLE, DROP),
11565 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
11566 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
11567 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
11568 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
11569 DEVLINK_TRAP(STP, CONTROL),
11570 DEVLINK_TRAP(LACP, CONTROL),
11571 DEVLINK_TRAP(LLDP, CONTROL),
11572 DEVLINK_TRAP(IGMP_QUERY, CONTROL),
11573 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
11574 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
11575 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
11576 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
11577 DEVLINK_TRAP(MLD_QUERY, CONTROL),
11578 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
11579 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
11580 DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
11581 DEVLINK_TRAP(IPV4_DHCP, CONTROL),
11582 DEVLINK_TRAP(IPV6_DHCP, CONTROL),
11583 DEVLINK_TRAP(ARP_REQUEST, CONTROL),
11584 DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
11585 DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
11586 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
11587 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
11588 DEVLINK_TRAP(IPV4_BFD, CONTROL),
11589 DEVLINK_TRAP(IPV6_BFD, CONTROL),
11590 DEVLINK_TRAP(IPV4_OSPF, CONTROL),
11591 DEVLINK_TRAP(IPV6_OSPF, CONTROL),
11592 DEVLINK_TRAP(IPV4_BGP, CONTROL),
11593 DEVLINK_TRAP(IPV6_BGP, CONTROL),
11594 DEVLINK_TRAP(IPV4_VRRP, CONTROL),
11595 DEVLINK_TRAP(IPV6_VRRP, CONTROL),
11596 DEVLINK_TRAP(IPV4_PIM, CONTROL),
11597 DEVLINK_TRAP(IPV6_PIM, CONTROL),
11598 DEVLINK_TRAP(UC_LB, CONTROL),
11599 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
11600 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
11601 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
11602 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
11603 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
11604 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
11605 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
11606 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
11607 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
11608 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
11609 DEVLINK_TRAP(PTP_EVENT, CONTROL),
11610 DEVLINK_TRAP(PTP_GENERAL, CONTROL),
11611 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
11612 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
11613 DEVLINK_TRAP(EARLY_DROP, DROP),
11614 DEVLINK_TRAP(VXLAN_PARSING, DROP),
11615 DEVLINK_TRAP(LLC_SNAP_PARSING, DROP),
11616 DEVLINK_TRAP(VLAN_PARSING, DROP),
11617 DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP),
11618 DEVLINK_TRAP(MPLS_PARSING, DROP),
11619 DEVLINK_TRAP(ARP_PARSING, DROP),
11620 DEVLINK_TRAP(IP_1_PARSING, DROP),
11621 DEVLINK_TRAP(IP_N_PARSING, DROP),
11622 DEVLINK_TRAP(GRE_PARSING, DROP),
11623 DEVLINK_TRAP(UDP_PARSING, DROP),
11624 DEVLINK_TRAP(TCP_PARSING, DROP),
11625 DEVLINK_TRAP(IPSEC_PARSING, DROP),
11626 DEVLINK_TRAP(SCTP_PARSING, DROP),
11627 DEVLINK_TRAP(DCCP_PARSING, DROP),
11628 DEVLINK_TRAP(GTP_PARSING, DROP),
11629 DEVLINK_TRAP(ESP_PARSING, DROP),
11630 DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP),
11631 DEVLINK_TRAP(DMAC_FILTER, DROP),
11632 };
11633
11634 #define DEVLINK_TRAP_GROUP(_id) \
11635 { \
11636 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
11637 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
11638 }
11639
11640 static const struct devlink_trap_group devlink_trap_group_generic[] = {
11641 DEVLINK_TRAP_GROUP(L2_DROPS),
11642 DEVLINK_TRAP_GROUP(L3_DROPS),
11643 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
11644 DEVLINK_TRAP_GROUP(BUFFER_DROPS),
11645 DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
11646 DEVLINK_TRAP_GROUP(ACL_DROPS),
11647 DEVLINK_TRAP_GROUP(STP),
11648 DEVLINK_TRAP_GROUP(LACP),
11649 DEVLINK_TRAP_GROUP(LLDP),
11650 DEVLINK_TRAP_GROUP(MC_SNOOPING),
11651 DEVLINK_TRAP_GROUP(DHCP),
11652 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
11653 DEVLINK_TRAP_GROUP(BFD),
11654 DEVLINK_TRAP_GROUP(OSPF),
11655 DEVLINK_TRAP_GROUP(BGP),
11656 DEVLINK_TRAP_GROUP(VRRP),
11657 DEVLINK_TRAP_GROUP(PIM),
11658 DEVLINK_TRAP_GROUP(UC_LB),
11659 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
11660 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
11661 DEVLINK_TRAP_GROUP(IPV6),
11662 DEVLINK_TRAP_GROUP(PTP_EVENT),
11663 DEVLINK_TRAP_GROUP(PTP_GENERAL),
11664 DEVLINK_TRAP_GROUP(ACL_SAMPLE),
11665 DEVLINK_TRAP_GROUP(ACL_TRAP),
11666 DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
11667 };
11668
devlink_trap_generic_verify(const struct devlink_trap * trap)11669 static int devlink_trap_generic_verify(const struct devlink_trap *trap)
11670 {
11671 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
11672 return -EINVAL;
11673
11674 if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
11675 return -EINVAL;
11676
11677 if (trap->type != devlink_trap_generic[trap->id].type)
11678 return -EINVAL;
11679
11680 return 0;
11681 }
11682
devlink_trap_driver_verify(const struct devlink_trap * trap)11683 static int devlink_trap_driver_verify(const struct devlink_trap *trap)
11684 {
11685 int i;
11686
11687 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
11688 return -EINVAL;
11689
11690 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
11691 if (!strcmp(trap->name, devlink_trap_generic[i].name))
11692 return -EEXIST;
11693 }
11694
11695 return 0;
11696 }
11697
devlink_trap_verify(const struct devlink_trap * trap)11698 static int devlink_trap_verify(const struct devlink_trap *trap)
11699 {
11700 if (!trap || !trap->name)
11701 return -EINVAL;
11702
11703 if (trap->generic)
11704 return devlink_trap_generic_verify(trap);
11705 else
11706 return devlink_trap_driver_verify(trap);
11707 }
11708
11709 static int
devlink_trap_group_generic_verify(const struct devlink_trap_group * group)11710 devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
11711 {
11712 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
11713 return -EINVAL;
11714
11715 if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
11716 return -EINVAL;
11717
11718 return 0;
11719 }
11720
11721 static int
devlink_trap_group_driver_verify(const struct devlink_trap_group * group)11722 devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
11723 {
11724 int i;
11725
11726 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
11727 return -EINVAL;
11728
11729 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
11730 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
11731 return -EEXIST;
11732 }
11733
11734 return 0;
11735 }
11736
devlink_trap_group_verify(const struct devlink_trap_group * group)11737 static int devlink_trap_group_verify(const struct devlink_trap_group *group)
11738 {
11739 if (group->generic)
11740 return devlink_trap_group_generic_verify(group);
11741 else
11742 return devlink_trap_group_driver_verify(group);
11743 }
11744
11745 static void
devlink_trap_group_notify(struct devlink * devlink,const struct devlink_trap_group_item * group_item,enum devlink_command cmd)11746 devlink_trap_group_notify(struct devlink *devlink,
11747 const struct devlink_trap_group_item *group_item,
11748 enum devlink_command cmd)
11749 {
11750 struct sk_buff *msg;
11751 int err;
11752
11753 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
11754 cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
11755 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
11756 return;
11757
11758 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11759 if (!msg)
11760 return;
11761
11762 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
11763 0);
11764 if (err) {
11765 nlmsg_free(msg);
11766 return;
11767 }
11768
11769 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
11770 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
11771 }
11772
11773 static int
devlink_trap_item_group_link(struct devlink * devlink,struct devlink_trap_item * trap_item)11774 devlink_trap_item_group_link(struct devlink *devlink,
11775 struct devlink_trap_item *trap_item)
11776 {
11777 u16 group_id = trap_item->trap->init_group_id;
11778 struct devlink_trap_group_item *group_item;
11779
11780 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
11781 if (WARN_ON_ONCE(!group_item))
11782 return -EINVAL;
11783
11784 trap_item->group_item = group_item;
11785
11786 return 0;
11787 }
11788
devlink_trap_notify(struct devlink * devlink,const struct devlink_trap_item * trap_item,enum devlink_command cmd)11789 static void devlink_trap_notify(struct devlink *devlink,
11790 const struct devlink_trap_item *trap_item,
11791 enum devlink_command cmd)
11792 {
11793 struct sk_buff *msg;
11794 int err;
11795
11796 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
11797 cmd != DEVLINK_CMD_TRAP_DEL);
11798 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
11799 return;
11800
11801 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11802 if (!msg)
11803 return;
11804
11805 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
11806 if (err) {
11807 nlmsg_free(msg);
11808 return;
11809 }
11810
11811 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
11812 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
11813 }
11814
11815 static int
devlink_trap_register(struct devlink * devlink,const struct devlink_trap * trap,void * priv)11816 devlink_trap_register(struct devlink *devlink,
11817 const struct devlink_trap *trap, void *priv)
11818 {
11819 struct devlink_trap_item *trap_item;
11820 int err;
11821
11822 if (devlink_trap_item_lookup(devlink, trap->name))
11823 return -EEXIST;
11824
11825 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
11826 if (!trap_item)
11827 return -ENOMEM;
11828
11829 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
11830 if (!trap_item->stats) {
11831 err = -ENOMEM;
11832 goto err_stats_alloc;
11833 }
11834
11835 trap_item->trap = trap;
11836 trap_item->action = trap->init_action;
11837 trap_item->priv = priv;
11838
11839 err = devlink_trap_item_group_link(devlink, trap_item);
11840 if (err)
11841 goto err_group_link;
11842
11843 err = devlink->ops->trap_init(devlink, trap, trap_item);
11844 if (err)
11845 goto err_trap_init;
11846
11847 list_add_tail(&trap_item->list, &devlink->trap_list);
11848 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
11849
11850 return 0;
11851
11852 err_trap_init:
11853 err_group_link:
11854 free_percpu(trap_item->stats);
11855 err_stats_alloc:
11856 kfree(trap_item);
11857 return err;
11858 }
11859
devlink_trap_unregister(struct devlink * devlink,const struct devlink_trap * trap)11860 static void devlink_trap_unregister(struct devlink *devlink,
11861 const struct devlink_trap *trap)
11862 {
11863 struct devlink_trap_item *trap_item;
11864
11865 trap_item = devlink_trap_item_lookup(devlink, trap->name);
11866 if (WARN_ON_ONCE(!trap_item))
11867 return;
11868
11869 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
11870 list_del(&trap_item->list);
11871 if (devlink->ops->trap_fini)
11872 devlink->ops->trap_fini(devlink, trap, trap_item);
11873 free_percpu(trap_item->stats);
11874 kfree(trap_item);
11875 }
11876
devlink_trap_disable(struct devlink * devlink,const struct devlink_trap * trap)11877 static void devlink_trap_disable(struct devlink *devlink,
11878 const struct devlink_trap *trap)
11879 {
11880 struct devlink_trap_item *trap_item;
11881
11882 trap_item = devlink_trap_item_lookup(devlink, trap->name);
11883 if (WARN_ON_ONCE(!trap_item))
11884 return;
11885
11886 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
11887 NULL);
11888 trap_item->action = DEVLINK_TRAP_ACTION_DROP;
11889 }
11890
11891 /**
11892 * devl_traps_register - Register packet traps with devlink.
11893 * @devlink: devlink.
11894 * @traps: Packet traps.
11895 * @traps_count: Count of provided packet traps.
11896 * @priv: Driver private information.
11897 *
11898 * Return: Non-zero value on failure.
11899 */
devl_traps_register(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count,void * priv)11900 int devl_traps_register(struct devlink *devlink,
11901 const struct devlink_trap *traps,
11902 size_t traps_count, void *priv)
11903 {
11904 int i, err;
11905
11906 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
11907 return -EINVAL;
11908
11909 devl_assert_locked(devlink);
11910 for (i = 0; i < traps_count; i++) {
11911 const struct devlink_trap *trap = &traps[i];
11912
11913 err = devlink_trap_verify(trap);
11914 if (err)
11915 goto err_trap_verify;
11916
11917 err = devlink_trap_register(devlink, trap, priv);
11918 if (err)
11919 goto err_trap_register;
11920 }
11921
11922 return 0;
11923
11924 err_trap_register:
11925 err_trap_verify:
11926 for (i--; i >= 0; i--)
11927 devlink_trap_unregister(devlink, &traps[i]);
11928 return err;
11929 }
11930 EXPORT_SYMBOL_GPL(devl_traps_register);
11931
11932 /**
11933 * devlink_traps_register - Register packet traps with devlink.
11934 * @devlink: devlink.
11935 * @traps: Packet traps.
11936 * @traps_count: Count of provided packet traps.
11937 * @priv: Driver private information.
11938 *
11939 * Context: Takes and release devlink->lock <mutex>.
11940 *
11941 * Return: Non-zero value on failure.
11942 */
devlink_traps_register(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count,void * priv)11943 int devlink_traps_register(struct devlink *devlink,
11944 const struct devlink_trap *traps,
11945 size_t traps_count, void *priv)
11946 {
11947 int err;
11948
11949 devl_lock(devlink);
11950 err = devl_traps_register(devlink, traps, traps_count, priv);
11951 devl_unlock(devlink);
11952 return err;
11953 }
11954 EXPORT_SYMBOL_GPL(devlink_traps_register);
11955
11956 /**
11957 * devl_traps_unregister - Unregister packet traps from devlink.
11958 * @devlink: devlink.
11959 * @traps: Packet traps.
11960 * @traps_count: Count of provided packet traps.
11961 */
devl_traps_unregister(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count)11962 void devl_traps_unregister(struct devlink *devlink,
11963 const struct devlink_trap *traps,
11964 size_t traps_count)
11965 {
11966 int i;
11967
11968 devl_assert_locked(devlink);
11969 /* Make sure we do not have any packets in-flight while unregistering
11970 * traps by disabling all of them and waiting for a grace period.
11971 */
11972 for (i = traps_count - 1; i >= 0; i--)
11973 devlink_trap_disable(devlink, &traps[i]);
11974 synchronize_rcu();
11975 for (i = traps_count - 1; i >= 0; i--)
11976 devlink_trap_unregister(devlink, &traps[i]);
11977 }
11978 EXPORT_SYMBOL_GPL(devl_traps_unregister);
11979
11980 /**
11981 * devlink_traps_unregister - Unregister packet traps from devlink.
11982 * @devlink: devlink.
11983 * @traps: Packet traps.
11984 * @traps_count: Count of provided packet traps.
11985 *
11986 * Context: Takes and release devlink->lock <mutex>.
11987 */
devlink_traps_unregister(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count)11988 void devlink_traps_unregister(struct devlink *devlink,
11989 const struct devlink_trap *traps,
11990 size_t traps_count)
11991 {
11992 devl_lock(devlink);
11993 devl_traps_unregister(devlink, traps, traps_count);
11994 devl_unlock(devlink);
11995 }
11996 EXPORT_SYMBOL_GPL(devlink_traps_unregister);
11997
11998 static void
devlink_trap_stats_update(struct devlink_stats __percpu * trap_stats,size_t skb_len)11999 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
12000 size_t skb_len)
12001 {
12002 struct devlink_stats *stats;
12003
12004 stats = this_cpu_ptr(trap_stats);
12005 u64_stats_update_begin(&stats->syncp);
12006 u64_stats_add(&stats->rx_bytes, skb_len);
12007 u64_stats_inc(&stats->rx_packets);
12008 u64_stats_update_end(&stats->syncp);
12009 }
12010
12011 static void
devlink_trap_report_metadata_set(struct devlink_trap_metadata * metadata,const struct devlink_trap_item * trap_item,struct devlink_port * in_devlink_port,const struct flow_action_cookie * fa_cookie)12012 devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
12013 const struct devlink_trap_item *trap_item,
12014 struct devlink_port *in_devlink_port,
12015 const struct flow_action_cookie *fa_cookie)
12016 {
12017 metadata->trap_name = trap_item->trap->name;
12018 metadata->trap_group_name = trap_item->group_item->group->name;
12019 metadata->fa_cookie = fa_cookie;
12020 metadata->trap_type = trap_item->trap->type;
12021
12022 spin_lock(&in_devlink_port->type_lock);
12023 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
12024 metadata->input_dev = in_devlink_port->type_dev;
12025 spin_unlock(&in_devlink_port->type_lock);
12026 }
12027
12028 /**
12029 * devlink_trap_report - Report trapped packet to drop monitor.
12030 * @devlink: devlink.
12031 * @skb: Trapped packet.
12032 * @trap_ctx: Trap context.
12033 * @in_devlink_port: Input devlink port.
12034 * @fa_cookie: Flow action cookie. Could be NULL.
12035 */
devlink_trap_report(struct devlink * devlink,struct sk_buff * skb,void * trap_ctx,struct devlink_port * in_devlink_port,const struct flow_action_cookie * fa_cookie)12036 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
12037 void *trap_ctx, struct devlink_port *in_devlink_port,
12038 const struct flow_action_cookie *fa_cookie)
12039
12040 {
12041 struct devlink_trap_item *trap_item = trap_ctx;
12042
12043 devlink_trap_stats_update(trap_item->stats, skb->len);
12044 devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
12045
12046 if (trace_devlink_trap_report_enabled()) {
12047 struct devlink_trap_metadata metadata = {};
12048
12049 devlink_trap_report_metadata_set(&metadata, trap_item,
12050 in_devlink_port, fa_cookie);
12051 trace_devlink_trap_report(devlink, skb, &metadata);
12052 }
12053 }
12054 EXPORT_SYMBOL_GPL(devlink_trap_report);
12055
12056 /**
12057 * devlink_trap_ctx_priv - Trap context to driver private information.
12058 * @trap_ctx: Trap context.
12059 *
12060 * Return: Driver private information passed during registration.
12061 */
devlink_trap_ctx_priv(void * trap_ctx)12062 void *devlink_trap_ctx_priv(void *trap_ctx)
12063 {
12064 struct devlink_trap_item *trap_item = trap_ctx;
12065
12066 return trap_item->priv;
12067 }
12068 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
12069
12070 static int
devlink_trap_group_item_policer_link(struct devlink * devlink,struct devlink_trap_group_item * group_item)12071 devlink_trap_group_item_policer_link(struct devlink *devlink,
12072 struct devlink_trap_group_item *group_item)
12073 {
12074 u32 policer_id = group_item->group->init_policer_id;
12075 struct devlink_trap_policer_item *policer_item;
12076
12077 if (policer_id == 0)
12078 return 0;
12079
12080 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
12081 if (WARN_ON_ONCE(!policer_item))
12082 return -EINVAL;
12083
12084 group_item->policer_item = policer_item;
12085
12086 return 0;
12087 }
12088
12089 static int
devlink_trap_group_register(struct devlink * devlink,const struct devlink_trap_group * group)12090 devlink_trap_group_register(struct devlink *devlink,
12091 const struct devlink_trap_group *group)
12092 {
12093 struct devlink_trap_group_item *group_item;
12094 int err;
12095
12096 if (devlink_trap_group_item_lookup(devlink, group->name))
12097 return -EEXIST;
12098
12099 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
12100 if (!group_item)
12101 return -ENOMEM;
12102
12103 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
12104 if (!group_item->stats) {
12105 err = -ENOMEM;
12106 goto err_stats_alloc;
12107 }
12108
12109 group_item->group = group;
12110
12111 err = devlink_trap_group_item_policer_link(devlink, group_item);
12112 if (err)
12113 goto err_policer_link;
12114
12115 if (devlink->ops->trap_group_init) {
12116 err = devlink->ops->trap_group_init(devlink, group);
12117 if (err)
12118 goto err_group_init;
12119 }
12120
12121 list_add_tail(&group_item->list, &devlink->trap_group_list);
12122 devlink_trap_group_notify(devlink, group_item,
12123 DEVLINK_CMD_TRAP_GROUP_NEW);
12124
12125 return 0;
12126
12127 err_group_init:
12128 err_policer_link:
12129 free_percpu(group_item->stats);
12130 err_stats_alloc:
12131 kfree(group_item);
12132 return err;
12133 }
12134
12135 static void
devlink_trap_group_unregister(struct devlink * devlink,const struct devlink_trap_group * group)12136 devlink_trap_group_unregister(struct devlink *devlink,
12137 const struct devlink_trap_group *group)
12138 {
12139 struct devlink_trap_group_item *group_item;
12140
12141 group_item = devlink_trap_group_item_lookup(devlink, group->name);
12142 if (WARN_ON_ONCE(!group_item))
12143 return;
12144
12145 devlink_trap_group_notify(devlink, group_item,
12146 DEVLINK_CMD_TRAP_GROUP_DEL);
12147 list_del(&group_item->list);
12148 free_percpu(group_item->stats);
12149 kfree(group_item);
12150 }
12151
12152 /**
12153 * devl_trap_groups_register - Register packet trap groups with devlink.
12154 * @devlink: devlink.
12155 * @groups: Packet trap groups.
12156 * @groups_count: Count of provided packet trap groups.
12157 *
12158 * Return: Non-zero value on failure.
12159 */
devl_trap_groups_register(struct devlink * devlink,const struct devlink_trap_group * groups,size_t groups_count)12160 int devl_trap_groups_register(struct devlink *devlink,
12161 const struct devlink_trap_group *groups,
12162 size_t groups_count)
12163 {
12164 int i, err;
12165
12166 devl_assert_locked(devlink);
12167 for (i = 0; i < groups_count; i++) {
12168 const struct devlink_trap_group *group = &groups[i];
12169
12170 err = devlink_trap_group_verify(group);
12171 if (err)
12172 goto err_trap_group_verify;
12173
12174 err = devlink_trap_group_register(devlink, group);
12175 if (err)
12176 goto err_trap_group_register;
12177 }
12178
12179 return 0;
12180
12181 err_trap_group_register:
12182 err_trap_group_verify:
12183 for (i--; i >= 0; i--)
12184 devlink_trap_group_unregister(devlink, &groups[i]);
12185 return err;
12186 }
12187 EXPORT_SYMBOL_GPL(devl_trap_groups_register);
12188
12189 /**
12190 * devlink_trap_groups_register - Register packet trap groups with devlink.
12191 * @devlink: devlink.
12192 * @groups: Packet trap groups.
12193 * @groups_count: Count of provided packet trap groups.
12194 *
12195 * Context: Takes and release devlink->lock <mutex>.
12196 *
12197 * Return: Non-zero value on failure.
12198 */
devlink_trap_groups_register(struct devlink * devlink,const struct devlink_trap_group * groups,size_t groups_count)12199 int devlink_trap_groups_register(struct devlink *devlink,
12200 const struct devlink_trap_group *groups,
12201 size_t groups_count)
12202 {
12203 int err;
12204
12205 devl_lock(devlink);
12206 err = devl_trap_groups_register(devlink, groups, groups_count);
12207 devl_unlock(devlink);
12208 return err;
12209 }
12210 EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
12211
12212 /**
12213 * devl_trap_groups_unregister - Unregister packet trap groups from devlink.
12214 * @devlink: devlink.
12215 * @groups: Packet trap groups.
12216 * @groups_count: Count of provided packet trap groups.
12217 */
devl_trap_groups_unregister(struct devlink * devlink,const struct devlink_trap_group * groups,size_t groups_count)12218 void devl_trap_groups_unregister(struct devlink *devlink,
12219 const struct devlink_trap_group *groups,
12220 size_t groups_count)
12221 {
12222 int i;
12223
12224 devl_assert_locked(devlink);
12225 for (i = groups_count - 1; i >= 0; i--)
12226 devlink_trap_group_unregister(devlink, &groups[i]);
12227 }
12228 EXPORT_SYMBOL_GPL(devl_trap_groups_unregister);
12229
12230 /**
12231 * devlink_trap_groups_unregister - Unregister packet trap groups from devlink.
12232 * @devlink: devlink.
12233 * @groups: Packet trap groups.
12234 * @groups_count: Count of provided packet trap groups.
12235 *
12236 * Context: Takes and release devlink->lock <mutex>.
12237 */
devlink_trap_groups_unregister(struct devlink * devlink,const struct devlink_trap_group * groups,size_t groups_count)12238 void devlink_trap_groups_unregister(struct devlink *devlink,
12239 const struct devlink_trap_group *groups,
12240 size_t groups_count)
12241 {
12242 devl_lock(devlink);
12243 devl_trap_groups_unregister(devlink, groups, groups_count);
12244 devl_unlock(devlink);
12245 }
12246 EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
12247
12248 static void
devlink_trap_policer_notify(struct devlink * devlink,const struct devlink_trap_policer_item * policer_item,enum devlink_command cmd)12249 devlink_trap_policer_notify(struct devlink *devlink,
12250 const struct devlink_trap_policer_item *policer_item,
12251 enum devlink_command cmd)
12252 {
12253 struct sk_buff *msg;
12254 int err;
12255
12256 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
12257 cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
12258 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
12259 return;
12260
12261 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12262 if (!msg)
12263 return;
12264
12265 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
12266 0, 0);
12267 if (err) {
12268 nlmsg_free(msg);
12269 return;
12270 }
12271
12272 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
12273 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
12274 }
12275
12276 static int
devlink_trap_policer_register(struct devlink * devlink,const struct devlink_trap_policer * policer)12277 devlink_trap_policer_register(struct devlink *devlink,
12278 const struct devlink_trap_policer *policer)
12279 {
12280 struct devlink_trap_policer_item *policer_item;
12281 int err;
12282
12283 if (devlink_trap_policer_item_lookup(devlink, policer->id))
12284 return -EEXIST;
12285
12286 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
12287 if (!policer_item)
12288 return -ENOMEM;
12289
12290 policer_item->policer = policer;
12291 policer_item->rate = policer->init_rate;
12292 policer_item->burst = policer->init_burst;
12293
12294 if (devlink->ops->trap_policer_init) {
12295 err = devlink->ops->trap_policer_init(devlink, policer);
12296 if (err)
12297 goto err_policer_init;
12298 }
12299
12300 list_add_tail(&policer_item->list, &devlink->trap_policer_list);
12301 devlink_trap_policer_notify(devlink, policer_item,
12302 DEVLINK_CMD_TRAP_POLICER_NEW);
12303
12304 return 0;
12305
12306 err_policer_init:
12307 kfree(policer_item);
12308 return err;
12309 }
12310
12311 static void
devlink_trap_policer_unregister(struct devlink * devlink,const struct devlink_trap_policer * policer)12312 devlink_trap_policer_unregister(struct devlink *devlink,
12313 const struct devlink_trap_policer *policer)
12314 {
12315 struct devlink_trap_policer_item *policer_item;
12316
12317 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
12318 if (WARN_ON_ONCE(!policer_item))
12319 return;
12320
12321 devlink_trap_policer_notify(devlink, policer_item,
12322 DEVLINK_CMD_TRAP_POLICER_DEL);
12323 list_del(&policer_item->list);
12324 if (devlink->ops->trap_policer_fini)
12325 devlink->ops->trap_policer_fini(devlink, policer);
12326 kfree(policer_item);
12327 }
12328
12329 /**
12330 * devl_trap_policers_register - Register packet trap policers with devlink.
12331 * @devlink: devlink.
12332 * @policers: Packet trap policers.
12333 * @policers_count: Count of provided packet trap policers.
12334 *
12335 * Return: Non-zero value on failure.
12336 */
12337 int
devl_trap_policers_register(struct devlink * devlink,const struct devlink_trap_policer * policers,size_t policers_count)12338 devl_trap_policers_register(struct devlink *devlink,
12339 const struct devlink_trap_policer *policers,
12340 size_t policers_count)
12341 {
12342 int i, err;
12343
12344 devl_assert_locked(devlink);
12345 for (i = 0; i < policers_count; i++) {
12346 const struct devlink_trap_policer *policer = &policers[i];
12347
12348 if (WARN_ON(policer->id == 0 ||
12349 policer->max_rate < policer->min_rate ||
12350 policer->max_burst < policer->min_burst)) {
12351 err = -EINVAL;
12352 goto err_trap_policer_verify;
12353 }
12354
12355 err = devlink_trap_policer_register(devlink, policer);
12356 if (err)
12357 goto err_trap_policer_register;
12358 }
12359 return 0;
12360
12361 err_trap_policer_register:
12362 err_trap_policer_verify:
12363 for (i--; i >= 0; i--)
12364 devlink_trap_policer_unregister(devlink, &policers[i]);
12365 return err;
12366 }
12367 EXPORT_SYMBOL_GPL(devl_trap_policers_register);
12368
12369 /**
12370 * devl_trap_policers_unregister - Unregister packet trap policers from devlink.
12371 * @devlink: devlink.
12372 * @policers: Packet trap policers.
12373 * @policers_count: Count of provided packet trap policers.
12374 */
12375 void
devl_trap_policers_unregister(struct devlink * devlink,const struct devlink_trap_policer * policers,size_t policers_count)12376 devl_trap_policers_unregister(struct devlink *devlink,
12377 const struct devlink_trap_policer *policers,
12378 size_t policers_count)
12379 {
12380 int i;
12381
12382 devl_assert_locked(devlink);
12383 for (i = policers_count - 1; i >= 0; i--)
12384 devlink_trap_policer_unregister(devlink, &policers[i]);
12385 }
12386 EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);
12387
__devlink_compat_running_version(struct devlink * devlink,char * buf,size_t len)12388 static void __devlink_compat_running_version(struct devlink *devlink,
12389 char *buf, size_t len)
12390 {
12391 struct devlink_info_req req = {};
12392 const struct nlattr *nlattr;
12393 struct sk_buff *msg;
12394 int rem, err;
12395
12396 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12397 if (!msg)
12398 return;
12399
12400 req.msg = msg;
12401 err = devlink->ops->info_get(devlink, &req, NULL);
12402 if (err)
12403 goto free_msg;
12404
12405 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
12406 const struct nlattr *kv;
12407 int rem_kv;
12408
12409 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
12410 continue;
12411
12412 nla_for_each_nested(kv, nlattr, rem_kv) {
12413 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
12414 continue;
12415
12416 strlcat(buf, nla_data(kv), len);
12417 strlcat(buf, " ", len);
12418 }
12419 }
12420 free_msg:
12421 nlmsg_free(msg);
12422 }
12423
netdev_to_devlink_port(struct net_device * dev)12424 static struct devlink_port *netdev_to_devlink_port(struct net_device *dev)
12425 {
12426 if (!dev->netdev_ops->ndo_get_devlink_port)
12427 return NULL;
12428
12429 return dev->netdev_ops->ndo_get_devlink_port(dev);
12430 }
12431
devlink_compat_running_version(struct devlink * devlink,char * buf,size_t len)12432 void devlink_compat_running_version(struct devlink *devlink,
12433 char *buf, size_t len)
12434 {
12435 if (!devlink->ops->info_get)
12436 return;
12437
12438 devl_lock(devlink);
12439 __devlink_compat_running_version(devlink, buf, len);
12440 devl_unlock(devlink);
12441 }
12442
devlink_compat_flash_update(struct devlink * devlink,const char * file_name)12443 int devlink_compat_flash_update(struct devlink *devlink, const char *file_name)
12444 {
12445 struct devlink_flash_update_params params = {};
12446 int ret;
12447
12448 if (!devlink->ops->flash_update)
12449 return -EOPNOTSUPP;
12450
12451 ret = request_firmware(¶ms.fw, file_name, devlink->dev);
12452 if (ret)
12453 return ret;
12454
12455 devl_lock(devlink);
12456 devlink_flash_update_begin_notify(devlink);
12457 ret = devlink->ops->flash_update(devlink, ¶ms, NULL);
12458 devlink_flash_update_end_notify(devlink);
12459 devl_unlock(devlink);
12460
12461 release_firmware(params.fw);
12462
12463 return ret;
12464 }
12465
devlink_compat_phys_port_name_get(struct net_device * dev,char * name,size_t len)12466 int devlink_compat_phys_port_name_get(struct net_device *dev,
12467 char *name, size_t len)
12468 {
12469 struct devlink_port *devlink_port;
12470
12471 /* RTNL mutex is held here which ensures that devlink_port
12472 * instance cannot disappear in the middle. No need to take
12473 * any devlink lock as only permanent values are accessed.
12474 */
12475 ASSERT_RTNL();
12476
12477 devlink_port = netdev_to_devlink_port(dev);
12478 if (!devlink_port)
12479 return -EOPNOTSUPP;
12480
12481 return __devlink_port_phys_port_name_get(devlink_port, name, len);
12482 }
12483
devlink_compat_switch_id_get(struct net_device * dev,struct netdev_phys_item_id * ppid)12484 int devlink_compat_switch_id_get(struct net_device *dev,
12485 struct netdev_phys_item_id *ppid)
12486 {
12487 struct devlink_port *devlink_port;
12488
12489 /* Caller must hold RTNL mutex or reference to dev, which ensures that
12490 * devlink_port instance cannot disappear in the middle. No need to take
12491 * any devlink lock as only permanent values are accessed.
12492 */
12493 devlink_port = netdev_to_devlink_port(dev);
12494 if (!devlink_port || !devlink_port->switch_port)
12495 return -EOPNOTSUPP;
12496
12497 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
12498
12499 return 0;
12500 }
12501
devlink_pernet_pre_exit(struct net * net)12502 static void __net_exit devlink_pernet_pre_exit(struct net *net)
12503 {
12504 struct devlink *devlink;
12505 u32 actions_performed;
12506 unsigned long index;
12507 int err;
12508
12509 /* In case network namespace is getting destroyed, reload
12510 * all devlink instances from this namespace into init_net.
12511 */
12512 devlinks_xa_for_each_registered_get(net, index, devlink) {
12513 WARN_ON(!(devlink->features & DEVLINK_F_RELOAD));
12514 mutex_lock(&devlink->lock);
12515 err = devlink_reload(devlink, &init_net,
12516 DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
12517 DEVLINK_RELOAD_LIMIT_UNSPEC,
12518 &actions_performed, NULL);
12519 mutex_unlock(&devlink->lock);
12520 if (err && err != -EOPNOTSUPP)
12521 pr_warn("Failed to reload devlink instance into init_net\n");
12522 devlink_put(devlink);
12523 }
12524 }
12525
12526 static struct pernet_operations devlink_pernet_ops __net_initdata = {
12527 .pre_exit = devlink_pernet_pre_exit,
12528 };
12529
devlink_init(void)12530 static int __init devlink_init(void)
12531 {
12532 int err;
12533
12534 err = genl_register_family(&devlink_nl_family);
12535 if (err)
12536 goto out;
12537 err = register_pernet_subsys(&devlink_pernet_ops);
12538
12539 out:
12540 WARN_ON(err);
12541 return err;
12542 }
12543
12544 subsys_initcall(devlink_init);
12545