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