GNU Linux-libre 5.4.207-gnu1
[releases.git] / net / core / devlink.c
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/kernel.h>
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/gfp.h>
15 #include <linux/device.h>
16 #include <linux/list.h>
17 #include <linux/netdevice.h>
18 #include <linux/spinlock.h>
19 #include <linux/refcount.h>
20 #include <linux/workqueue.h>
21 #include <linux/u64_stats_sync.h>
22 #include <linux/timekeeping.h>
23 #include <rdma/ib_verbs.h>
24 #include <net/netlink.h>
25 #include <net/genetlink.h>
26 #include <net/rtnetlink.h>
27 #include <net/net_namespace.h>
28 #include <net/sock.h>
29 #include <net/devlink.h>
30 #include <net/drop_monitor.h>
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/devlink.h>
33
34 static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
35         {
36                 .name = "destination mac",
37                 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
38                 .bitwidth = 48,
39         },
40 };
41
42 struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
43         .name = "ethernet",
44         .id = DEVLINK_DPIPE_HEADER_ETHERNET,
45         .fields = devlink_dpipe_fields_ethernet,
46         .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
47         .global = true,
48 };
49 EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
50
51 static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
52         {
53                 .name = "destination ip",
54                 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
55                 .bitwidth = 32,
56         },
57 };
58
59 struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
60         .name = "ipv4",
61         .id = DEVLINK_DPIPE_HEADER_IPV4,
62         .fields = devlink_dpipe_fields_ipv4,
63         .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
64         .global = true,
65 };
66 EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
67
68 static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
69         {
70                 .name = "destination ip",
71                 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
72                 .bitwidth = 128,
73         },
74 };
75
76 struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
77         .name = "ipv6",
78         .id = DEVLINK_DPIPE_HEADER_IPV6,
79         .fields = devlink_dpipe_fields_ipv6,
80         .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
81         .global = true,
82 };
83 EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
84
85 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
86 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
87
88 static LIST_HEAD(devlink_list);
89
90 /* devlink_mutex
91  *
92  * An overall lock guarding every operation coming from userspace.
93  * It also guards devlink devices list and it is taken when
94  * driver registers/unregisters it.
95  */
96 static DEFINE_MUTEX(devlink_mutex);
97
98 static struct net *devlink_net(const struct devlink *devlink)
99 {
100         return read_pnet(&devlink->_net);
101 }
102
103 static void devlink_net_set(struct devlink *devlink, struct net *net)
104 {
105         write_pnet(&devlink->_net, net);
106 }
107
108 static struct devlink *devlink_get_from_attrs(struct net *net,
109                                               struct nlattr **attrs)
110 {
111         struct devlink *devlink;
112         char *busname;
113         char *devname;
114
115         if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
116                 return ERR_PTR(-EINVAL);
117
118         busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
119         devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
120
121         lockdep_assert_held(&devlink_mutex);
122
123         list_for_each_entry(devlink, &devlink_list, list) {
124                 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
125                     strcmp(dev_name(devlink->dev), devname) == 0 &&
126                     net_eq(devlink_net(devlink), net))
127                         return devlink;
128         }
129
130         return ERR_PTR(-ENODEV);
131 }
132
133 static struct devlink *devlink_get_from_info(struct genl_info *info)
134 {
135         return devlink_get_from_attrs(genl_info_net(info), info->attrs);
136 }
137
138 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
139                                                       unsigned int port_index)
140 {
141         struct devlink_port *devlink_port;
142
143         list_for_each_entry(devlink_port, &devlink->port_list, list) {
144                 if (devlink_port->index == port_index)
145                         return devlink_port;
146         }
147         return NULL;
148 }
149
150 static bool devlink_port_index_exists(struct devlink *devlink,
151                                       unsigned int port_index)
152 {
153         return devlink_port_get_by_index(devlink, port_index);
154 }
155
156 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
157                                                         struct nlattr **attrs)
158 {
159         if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
160                 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
161                 struct devlink_port *devlink_port;
162
163                 devlink_port = devlink_port_get_by_index(devlink, port_index);
164                 if (!devlink_port)
165                         return ERR_PTR(-ENODEV);
166                 return devlink_port;
167         }
168         return ERR_PTR(-EINVAL);
169 }
170
171 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
172                                                        struct genl_info *info)
173 {
174         return devlink_port_get_from_attrs(devlink, info->attrs);
175 }
176
177 struct devlink_sb {
178         struct list_head list;
179         unsigned int index;
180         u32 size;
181         u16 ingress_pools_count;
182         u16 egress_pools_count;
183         u16 ingress_tc_count;
184         u16 egress_tc_count;
185 };
186
187 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
188 {
189         return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
190 }
191
192 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
193                                                   unsigned int sb_index)
194 {
195         struct devlink_sb *devlink_sb;
196
197         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
198                 if (devlink_sb->index == sb_index)
199                         return devlink_sb;
200         }
201         return NULL;
202 }
203
204 static bool devlink_sb_index_exists(struct devlink *devlink,
205                                     unsigned int sb_index)
206 {
207         return devlink_sb_get_by_index(devlink, sb_index);
208 }
209
210 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
211                                                     struct nlattr **attrs)
212 {
213         if (attrs[DEVLINK_ATTR_SB_INDEX]) {
214                 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
215                 struct devlink_sb *devlink_sb;
216
217                 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
218                 if (!devlink_sb)
219                         return ERR_PTR(-ENODEV);
220                 return devlink_sb;
221         }
222         return ERR_PTR(-EINVAL);
223 }
224
225 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
226                                                    struct genl_info *info)
227 {
228         return devlink_sb_get_from_attrs(devlink, info->attrs);
229 }
230
231 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
232                                                 struct nlattr **attrs,
233                                                 u16 *p_pool_index)
234 {
235         u16 val;
236
237         if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
238                 return -EINVAL;
239
240         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
241         if (val >= devlink_sb_pool_count(devlink_sb))
242                 return -EINVAL;
243         *p_pool_index = val;
244         return 0;
245 }
246
247 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
248                                                struct genl_info *info,
249                                                u16 *p_pool_index)
250 {
251         return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
252                                                     p_pool_index);
253 }
254
255 static int
256 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
257                                     enum devlink_sb_pool_type *p_pool_type)
258 {
259         u8 val;
260
261         if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
262                 return -EINVAL;
263
264         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
265         if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
266             val != DEVLINK_SB_POOL_TYPE_EGRESS)
267                 return -EINVAL;
268         *p_pool_type = val;
269         return 0;
270 }
271
272 static int
273 devlink_sb_pool_type_get_from_info(struct genl_info *info,
274                                    enum devlink_sb_pool_type *p_pool_type)
275 {
276         return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
277 }
278
279 static int
280 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
281                                   enum devlink_sb_threshold_type *p_th_type)
282 {
283         u8 val;
284
285         if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
286                 return -EINVAL;
287
288         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
289         if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
290             val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
291                 return -EINVAL;
292         *p_th_type = val;
293         return 0;
294 }
295
296 static int
297 devlink_sb_th_type_get_from_info(struct genl_info *info,
298                                  enum devlink_sb_threshold_type *p_th_type)
299 {
300         return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
301 }
302
303 static int
304 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
305                                    struct nlattr **attrs,
306                                    enum devlink_sb_pool_type pool_type,
307                                    u16 *p_tc_index)
308 {
309         u16 val;
310
311         if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
312                 return -EINVAL;
313
314         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
315         if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
316             val >= devlink_sb->ingress_tc_count)
317                 return -EINVAL;
318         if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
319             val >= devlink_sb->egress_tc_count)
320                 return -EINVAL;
321         *p_tc_index = val;
322         return 0;
323 }
324
325 static int
326 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
327                                   struct genl_info *info,
328                                   enum devlink_sb_pool_type pool_type,
329                                   u16 *p_tc_index)
330 {
331         return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
332                                                   pool_type, p_tc_index);
333 }
334
335 struct devlink_region {
336         struct devlink *devlink;
337         struct list_head list;
338         const char *name;
339         struct list_head snapshot_list;
340         u32 max_snapshots;
341         u32 cur_snapshots;
342         u64 size;
343 };
344
345 struct devlink_snapshot {
346         struct list_head list;
347         struct devlink_region *region;
348         devlink_snapshot_data_dest_t *data_destructor;
349         u8 *data;
350         u32 id;
351 };
352
353 static struct devlink_region *
354 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
355 {
356         struct devlink_region *region;
357
358         list_for_each_entry(region, &devlink->region_list, list)
359                 if (!strcmp(region->name, region_name))
360                         return region;
361
362         return NULL;
363 }
364
365 static struct devlink_snapshot *
366 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
367 {
368         struct devlink_snapshot *snapshot;
369
370         list_for_each_entry(snapshot, &region->snapshot_list, list)
371                 if (snapshot->id == id)
372                         return snapshot;
373
374         return NULL;
375 }
376
377 #define DEVLINK_NL_FLAG_NEED_DEVLINK    BIT(0)
378 #define DEVLINK_NL_FLAG_NEED_PORT       BIT(1)
379 #define DEVLINK_NL_FLAG_NEED_SB         BIT(2)
380
381 /* The per devlink instance lock is taken by default in the pre-doit
382  * operation, yet several commands do not require this. The global
383  * devlink lock is taken and protects from disruption by user-calls.
384  */
385 #define DEVLINK_NL_FLAG_NO_LOCK         BIT(3)
386
387 static int devlink_nl_pre_doit(const struct genl_ops *ops,
388                                struct sk_buff *skb, struct genl_info *info)
389 {
390         struct devlink *devlink;
391         int err;
392
393         mutex_lock(&devlink_mutex);
394         devlink = devlink_get_from_info(info);
395         if (IS_ERR(devlink)) {
396                 mutex_unlock(&devlink_mutex);
397                 return PTR_ERR(devlink);
398         }
399         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
400                 mutex_lock(&devlink->lock);
401         if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
402                 info->user_ptr[0] = devlink;
403         } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
404                 struct devlink_port *devlink_port;
405
406                 devlink_port = devlink_port_get_from_info(devlink, info);
407                 if (IS_ERR(devlink_port)) {
408                         err = PTR_ERR(devlink_port);
409                         goto unlock;
410                 }
411                 info->user_ptr[0] = devlink_port;
412         }
413         if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
414                 struct devlink_sb *devlink_sb;
415
416                 devlink_sb = devlink_sb_get_from_info(devlink, info);
417                 if (IS_ERR(devlink_sb)) {
418                         err = PTR_ERR(devlink_sb);
419                         goto unlock;
420                 }
421                 info->user_ptr[1] = devlink_sb;
422         }
423         return 0;
424
425 unlock:
426         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
427                 mutex_unlock(&devlink->lock);
428         mutex_unlock(&devlink_mutex);
429         return err;
430 }
431
432 static void devlink_nl_post_doit(const struct genl_ops *ops,
433                                  struct sk_buff *skb, struct genl_info *info)
434 {
435         struct devlink *devlink;
436
437         devlink = devlink_get_from_info(info);
438         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
439                 mutex_unlock(&devlink->lock);
440         mutex_unlock(&devlink_mutex);
441 }
442
443 static struct genl_family devlink_nl_family;
444
445 enum devlink_multicast_groups {
446         DEVLINK_MCGRP_CONFIG,
447 };
448
449 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
450         [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
451 };
452
453 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
454 {
455         if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
456                 return -EMSGSIZE;
457         if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
458                 return -EMSGSIZE;
459         return 0;
460 }
461
462 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
463                            enum devlink_command cmd, u32 portid,
464                            u32 seq, int flags)
465 {
466         void *hdr;
467
468         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
469         if (!hdr)
470                 return -EMSGSIZE;
471
472         if (devlink_nl_put_handle(msg, devlink))
473                 goto nla_put_failure;
474         if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
475                 goto nla_put_failure;
476
477         genlmsg_end(msg, hdr);
478         return 0;
479
480 nla_put_failure:
481         genlmsg_cancel(msg, hdr);
482         return -EMSGSIZE;
483 }
484
485 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
486 {
487         struct sk_buff *msg;
488         int err;
489
490         WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
491
492         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
493         if (!msg)
494                 return;
495
496         err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
497         if (err) {
498                 nlmsg_free(msg);
499                 return;
500         }
501
502         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
503                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
504 }
505
506 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
507                                      struct devlink_port *devlink_port)
508 {
509         struct devlink_port_attrs *attrs = &devlink_port->attrs;
510
511         if (!attrs->set)
512                 return 0;
513         if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
514                 return -EMSGSIZE;
515         switch (devlink_port->attrs.flavour) {
516         case DEVLINK_PORT_FLAVOUR_PCI_PF:
517                 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
518                                 attrs->pci_pf.pf))
519                         return -EMSGSIZE;
520                 break;
521         case DEVLINK_PORT_FLAVOUR_PCI_VF:
522                 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
523                                 attrs->pci_vf.pf) ||
524                     nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
525                                 attrs->pci_vf.vf))
526                         return -EMSGSIZE;
527                 break;
528         case DEVLINK_PORT_FLAVOUR_PHYSICAL:
529         case DEVLINK_PORT_FLAVOUR_CPU:
530         case DEVLINK_PORT_FLAVOUR_DSA:
531                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
532                                 attrs->phys.port_number))
533                         return -EMSGSIZE;
534                 if (!attrs->split)
535                         return 0;
536                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
537                                 attrs->phys.port_number))
538                         return -EMSGSIZE;
539                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
540                                 attrs->phys.split_subport_number))
541                         return -EMSGSIZE;
542                 break;
543         default:
544                 break;
545         }
546         return 0;
547 }
548
549 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
550                                 struct devlink_port *devlink_port,
551                                 enum devlink_command cmd, u32 portid,
552                                 u32 seq, int flags)
553 {
554         void *hdr;
555
556         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
557         if (!hdr)
558                 return -EMSGSIZE;
559
560         if (devlink_nl_put_handle(msg, devlink))
561                 goto nla_put_failure;
562         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
563                 goto nla_put_failure;
564
565         /* Hold rtnl lock while accessing port's netdev attributes. */
566         rtnl_lock();
567         spin_lock_bh(&devlink_port->type_lock);
568         if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
569                 goto nla_put_failure_type_locked;
570         if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
571             nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
572                         devlink_port->desired_type))
573                 goto nla_put_failure_type_locked;
574         if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
575                 struct net_device *netdev = devlink_port->type_dev;
576
577                 if (netdev &&
578                     (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
579                                  netdev->ifindex) ||
580                      nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
581                                     netdev->name)))
582                         goto nla_put_failure_type_locked;
583         }
584         if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
585                 struct ib_device *ibdev = devlink_port->type_dev;
586
587                 if (ibdev &&
588                     nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
589                                    ibdev->name))
590                         goto nla_put_failure_type_locked;
591         }
592         spin_unlock_bh(&devlink_port->type_lock);
593         rtnl_unlock();
594         if (devlink_nl_port_attrs_put(msg, devlink_port))
595                 goto nla_put_failure;
596
597         genlmsg_end(msg, hdr);
598         return 0;
599
600 nla_put_failure_type_locked:
601         spin_unlock_bh(&devlink_port->type_lock);
602         rtnl_unlock();
603 nla_put_failure:
604         genlmsg_cancel(msg, hdr);
605         return -EMSGSIZE;
606 }
607
608 static void devlink_port_notify(struct devlink_port *devlink_port,
609                                 enum devlink_command cmd)
610 {
611         struct devlink *devlink = devlink_port->devlink;
612         struct sk_buff *msg;
613         int err;
614
615         if (!devlink_port->registered)
616                 return;
617
618         WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
619
620         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
621         if (!msg)
622                 return;
623
624         err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
625         if (err) {
626                 nlmsg_free(msg);
627                 return;
628         }
629
630         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
631                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
632 }
633
634 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
635 {
636         struct devlink *devlink = info->user_ptr[0];
637         struct sk_buff *msg;
638         int err;
639
640         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
641         if (!msg)
642                 return -ENOMEM;
643
644         err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
645                               info->snd_portid, info->snd_seq, 0);
646         if (err) {
647                 nlmsg_free(msg);
648                 return err;
649         }
650
651         return genlmsg_reply(msg, info);
652 }
653
654 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
655                                      struct netlink_callback *cb)
656 {
657         struct devlink *devlink;
658         int start = cb->args[0];
659         int idx = 0;
660         int err;
661
662         mutex_lock(&devlink_mutex);
663         list_for_each_entry(devlink, &devlink_list, list) {
664                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
665                         continue;
666                 if (idx < start) {
667                         idx++;
668                         continue;
669                 }
670                 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
671                                       NETLINK_CB(cb->skb).portid,
672                                       cb->nlh->nlmsg_seq, NLM_F_MULTI);
673                 if (err)
674                         goto out;
675                 idx++;
676         }
677 out:
678         mutex_unlock(&devlink_mutex);
679
680         cb->args[0] = idx;
681         return msg->len;
682 }
683
684 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
685                                         struct genl_info *info)
686 {
687         struct devlink_port *devlink_port = info->user_ptr[0];
688         struct devlink *devlink = devlink_port->devlink;
689         struct sk_buff *msg;
690         int err;
691
692         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
693         if (!msg)
694                 return -ENOMEM;
695
696         err = devlink_nl_port_fill(msg, devlink, devlink_port,
697                                    DEVLINK_CMD_PORT_NEW,
698                                    info->snd_portid, info->snd_seq, 0);
699         if (err) {
700                 nlmsg_free(msg);
701                 return err;
702         }
703
704         return genlmsg_reply(msg, info);
705 }
706
707 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
708                                           struct netlink_callback *cb)
709 {
710         struct devlink *devlink;
711         struct devlink_port *devlink_port;
712         int start = cb->args[0];
713         int idx = 0;
714         int err;
715
716         mutex_lock(&devlink_mutex);
717         list_for_each_entry(devlink, &devlink_list, list) {
718                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
719                         continue;
720                 mutex_lock(&devlink->lock);
721                 list_for_each_entry(devlink_port, &devlink->port_list, list) {
722                         if (idx < start) {
723                                 idx++;
724                                 continue;
725                         }
726                         err = devlink_nl_port_fill(msg, devlink, devlink_port,
727                                                    DEVLINK_CMD_NEW,
728                                                    NETLINK_CB(cb->skb).portid,
729                                                    cb->nlh->nlmsg_seq,
730                                                    NLM_F_MULTI);
731                         if (err) {
732                                 mutex_unlock(&devlink->lock);
733                                 goto out;
734                         }
735                         idx++;
736                 }
737                 mutex_unlock(&devlink->lock);
738         }
739 out:
740         mutex_unlock(&devlink_mutex);
741
742         cb->args[0] = idx;
743         return msg->len;
744 }
745
746 static int devlink_port_type_set(struct devlink *devlink,
747                                  struct devlink_port *devlink_port,
748                                  enum devlink_port_type port_type)
749
750 {
751         int err;
752
753         if (devlink->ops->port_type_set) {
754                 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
755                         return -EINVAL;
756                 if (port_type == devlink_port->type)
757                         return 0;
758                 err = devlink->ops->port_type_set(devlink_port, port_type);
759                 if (err)
760                         return err;
761                 devlink_port->desired_type = port_type;
762                 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
763                 return 0;
764         }
765         return -EOPNOTSUPP;
766 }
767
768 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
769                                         struct genl_info *info)
770 {
771         struct devlink_port *devlink_port = info->user_ptr[0];
772         struct devlink *devlink = devlink_port->devlink;
773         int err;
774
775         if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
776                 enum devlink_port_type port_type;
777
778                 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
779                 err = devlink_port_type_set(devlink, devlink_port, port_type);
780                 if (err)
781                         return err;
782         }
783         return 0;
784 }
785
786 static int devlink_port_split(struct devlink *devlink, u32 port_index,
787                               u32 count, struct netlink_ext_ack *extack)
788
789 {
790         if (devlink->ops->port_split)
791                 return devlink->ops->port_split(devlink, port_index, count,
792                                                 extack);
793         return -EOPNOTSUPP;
794 }
795
796 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
797                                           struct genl_info *info)
798 {
799         struct devlink *devlink = info->user_ptr[0];
800         u32 port_index;
801         u32 count;
802
803         if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
804             !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
805                 return -EINVAL;
806
807         port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
808         count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
809         return devlink_port_split(devlink, port_index, count, info->extack);
810 }
811
812 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
813                                 struct netlink_ext_ack *extack)
814
815 {
816         if (devlink->ops->port_unsplit)
817                 return devlink->ops->port_unsplit(devlink, port_index, extack);
818         return -EOPNOTSUPP;
819 }
820
821 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
822                                             struct genl_info *info)
823 {
824         struct devlink *devlink = info->user_ptr[0];
825         u32 port_index;
826
827         if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
828                 return -EINVAL;
829
830         port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
831         return devlink_port_unsplit(devlink, port_index, info->extack);
832 }
833
834 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
835                               struct devlink_sb *devlink_sb,
836                               enum devlink_command cmd, u32 portid,
837                               u32 seq, int flags)
838 {
839         void *hdr;
840
841         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
842         if (!hdr)
843                 return -EMSGSIZE;
844
845         if (devlink_nl_put_handle(msg, devlink))
846                 goto nla_put_failure;
847         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
848                 goto nla_put_failure;
849         if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
850                 goto nla_put_failure;
851         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
852                         devlink_sb->ingress_pools_count))
853                 goto nla_put_failure;
854         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
855                         devlink_sb->egress_pools_count))
856                 goto nla_put_failure;
857         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
858                         devlink_sb->ingress_tc_count))
859                 goto nla_put_failure;
860         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
861                         devlink_sb->egress_tc_count))
862                 goto nla_put_failure;
863
864         genlmsg_end(msg, hdr);
865         return 0;
866
867 nla_put_failure:
868         genlmsg_cancel(msg, hdr);
869         return -EMSGSIZE;
870 }
871
872 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
873                                       struct genl_info *info)
874 {
875         struct devlink *devlink = info->user_ptr[0];
876         struct devlink_sb *devlink_sb = info->user_ptr[1];
877         struct sk_buff *msg;
878         int err;
879
880         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
881         if (!msg)
882                 return -ENOMEM;
883
884         err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
885                                  DEVLINK_CMD_SB_NEW,
886                                  info->snd_portid, info->snd_seq, 0);
887         if (err) {
888                 nlmsg_free(msg);
889                 return err;
890         }
891
892         return genlmsg_reply(msg, info);
893 }
894
895 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
896                                         struct netlink_callback *cb)
897 {
898         struct devlink *devlink;
899         struct devlink_sb *devlink_sb;
900         int start = cb->args[0];
901         int idx = 0;
902         int err;
903
904         mutex_lock(&devlink_mutex);
905         list_for_each_entry(devlink, &devlink_list, list) {
906                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
907                         continue;
908                 mutex_lock(&devlink->lock);
909                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
910                         if (idx < start) {
911                                 idx++;
912                                 continue;
913                         }
914                         err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
915                                                  DEVLINK_CMD_SB_NEW,
916                                                  NETLINK_CB(cb->skb).portid,
917                                                  cb->nlh->nlmsg_seq,
918                                                  NLM_F_MULTI);
919                         if (err) {
920                                 mutex_unlock(&devlink->lock);
921                                 goto out;
922                         }
923                         idx++;
924                 }
925                 mutex_unlock(&devlink->lock);
926         }
927 out:
928         mutex_unlock(&devlink_mutex);
929
930         cb->args[0] = idx;
931         return msg->len;
932 }
933
934 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
935                                    struct devlink_sb *devlink_sb,
936                                    u16 pool_index, enum devlink_command cmd,
937                                    u32 portid, u32 seq, int flags)
938 {
939         struct devlink_sb_pool_info pool_info;
940         void *hdr;
941         int err;
942
943         err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
944                                         pool_index, &pool_info);
945         if (err)
946                 return err;
947
948         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
949         if (!hdr)
950                 return -EMSGSIZE;
951
952         if (devlink_nl_put_handle(msg, devlink))
953                 goto nla_put_failure;
954         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
955                 goto nla_put_failure;
956         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
957                 goto nla_put_failure;
958         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
959                 goto nla_put_failure;
960         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
961                 goto nla_put_failure;
962         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
963                        pool_info.threshold_type))
964                 goto nla_put_failure;
965         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
966                         pool_info.cell_size))
967                 goto nla_put_failure;
968
969         genlmsg_end(msg, hdr);
970         return 0;
971
972 nla_put_failure:
973         genlmsg_cancel(msg, hdr);
974         return -EMSGSIZE;
975 }
976
977 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
978                                            struct genl_info *info)
979 {
980         struct devlink *devlink = info->user_ptr[0];
981         struct devlink_sb *devlink_sb = info->user_ptr[1];
982         struct sk_buff *msg;
983         u16 pool_index;
984         int err;
985
986         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
987                                                   &pool_index);
988         if (err)
989                 return err;
990
991         if (!devlink->ops->sb_pool_get)
992                 return -EOPNOTSUPP;
993
994         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
995         if (!msg)
996                 return -ENOMEM;
997
998         err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
999                                       DEVLINK_CMD_SB_POOL_NEW,
1000                                       info->snd_portid, info->snd_seq, 0);
1001         if (err) {
1002                 nlmsg_free(msg);
1003                 return err;
1004         }
1005
1006         return genlmsg_reply(msg, info);
1007 }
1008
1009 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1010                                 struct devlink *devlink,
1011                                 struct devlink_sb *devlink_sb,
1012                                 u32 portid, u32 seq)
1013 {
1014         u16 pool_count = devlink_sb_pool_count(devlink_sb);
1015         u16 pool_index;
1016         int err;
1017
1018         for (pool_index = 0; pool_index < pool_count; pool_index++) {
1019                 if (*p_idx < start) {
1020                         (*p_idx)++;
1021                         continue;
1022                 }
1023                 err = devlink_nl_sb_pool_fill(msg, devlink,
1024                                               devlink_sb,
1025                                               pool_index,
1026                                               DEVLINK_CMD_SB_POOL_NEW,
1027                                               portid, seq, NLM_F_MULTI);
1028                 if (err)
1029                         return err;
1030                 (*p_idx)++;
1031         }
1032         return 0;
1033 }
1034
1035 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1036                                              struct netlink_callback *cb)
1037 {
1038         struct devlink *devlink;
1039         struct devlink_sb *devlink_sb;
1040         int start = cb->args[0];
1041         int idx = 0;
1042         int err;
1043
1044         mutex_lock(&devlink_mutex);
1045         list_for_each_entry(devlink, &devlink_list, list) {
1046                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1047                     !devlink->ops->sb_pool_get)
1048                         continue;
1049                 mutex_lock(&devlink->lock);
1050                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1051                         err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1052                                                    devlink_sb,
1053                                                    NETLINK_CB(cb->skb).portid,
1054                                                    cb->nlh->nlmsg_seq);
1055                         if (err && err != -EOPNOTSUPP) {
1056                                 mutex_unlock(&devlink->lock);
1057                                 goto out;
1058                         }
1059                 }
1060                 mutex_unlock(&devlink->lock);
1061         }
1062 out:
1063         mutex_unlock(&devlink_mutex);
1064
1065         cb->args[0] = idx;
1066         return msg->len;
1067 }
1068
1069 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1070                                u16 pool_index, u32 size,
1071                                enum devlink_sb_threshold_type threshold_type,
1072                                struct netlink_ext_ack *extack)
1073
1074 {
1075         const struct devlink_ops *ops = devlink->ops;
1076
1077         if (ops->sb_pool_set)
1078                 return ops->sb_pool_set(devlink, sb_index, pool_index,
1079                                         size, threshold_type, extack);
1080         return -EOPNOTSUPP;
1081 }
1082
1083 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1084                                            struct genl_info *info)
1085 {
1086         struct devlink *devlink = info->user_ptr[0];
1087         struct devlink_sb *devlink_sb = info->user_ptr[1];
1088         enum devlink_sb_threshold_type threshold_type;
1089         u16 pool_index;
1090         u32 size;
1091         int err;
1092
1093         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1094                                                   &pool_index);
1095         if (err)
1096                 return err;
1097
1098         err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1099         if (err)
1100                 return err;
1101
1102         if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1103                 return -EINVAL;
1104
1105         size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1106         return devlink_sb_pool_set(devlink, devlink_sb->index,
1107                                    pool_index, size, threshold_type,
1108                                    info->extack);
1109 }
1110
1111 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1112                                         struct devlink *devlink,
1113                                         struct devlink_port *devlink_port,
1114                                         struct devlink_sb *devlink_sb,
1115                                         u16 pool_index,
1116                                         enum devlink_command cmd,
1117                                         u32 portid, u32 seq, int flags)
1118 {
1119         const struct devlink_ops *ops = devlink->ops;
1120         u32 threshold;
1121         void *hdr;
1122         int err;
1123
1124         err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1125                                     pool_index, &threshold);
1126         if (err)
1127                 return err;
1128
1129         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1130         if (!hdr)
1131                 return -EMSGSIZE;
1132
1133         if (devlink_nl_put_handle(msg, devlink))
1134                 goto nla_put_failure;
1135         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1136                 goto nla_put_failure;
1137         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1138                 goto nla_put_failure;
1139         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1140                 goto nla_put_failure;
1141         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1142                 goto nla_put_failure;
1143
1144         if (ops->sb_occ_port_pool_get) {
1145                 u32 cur;
1146                 u32 max;
1147
1148                 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1149                                                 pool_index, &cur, &max);
1150                 if (err && err != -EOPNOTSUPP)
1151                         goto sb_occ_get_failure;
1152                 if (!err) {
1153                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1154                                 goto nla_put_failure;
1155                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1156                                 goto nla_put_failure;
1157                 }
1158         }
1159
1160         genlmsg_end(msg, hdr);
1161         return 0;
1162
1163 nla_put_failure:
1164         err = -EMSGSIZE;
1165 sb_occ_get_failure:
1166         genlmsg_cancel(msg, hdr);
1167         return err;
1168 }
1169
1170 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1171                                                 struct genl_info *info)
1172 {
1173         struct devlink_port *devlink_port = info->user_ptr[0];
1174         struct devlink *devlink = devlink_port->devlink;
1175         struct devlink_sb *devlink_sb = info->user_ptr[1];
1176         struct sk_buff *msg;
1177         u16 pool_index;
1178         int err;
1179
1180         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1181                                                   &pool_index);
1182         if (err)
1183                 return err;
1184
1185         if (!devlink->ops->sb_port_pool_get)
1186                 return -EOPNOTSUPP;
1187
1188         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1189         if (!msg)
1190                 return -ENOMEM;
1191
1192         err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1193                                            devlink_sb, pool_index,
1194                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
1195                                            info->snd_portid, info->snd_seq, 0);
1196         if (err) {
1197                 nlmsg_free(msg);
1198                 return err;
1199         }
1200
1201         return genlmsg_reply(msg, info);
1202 }
1203
1204 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1205                                      struct devlink *devlink,
1206                                      struct devlink_sb *devlink_sb,
1207                                      u32 portid, u32 seq)
1208 {
1209         struct devlink_port *devlink_port;
1210         u16 pool_count = devlink_sb_pool_count(devlink_sb);
1211         u16 pool_index;
1212         int err;
1213
1214         list_for_each_entry(devlink_port, &devlink->port_list, list) {
1215                 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1216                         if (*p_idx < start) {
1217                                 (*p_idx)++;
1218                                 continue;
1219                         }
1220                         err = devlink_nl_sb_port_pool_fill(msg, devlink,
1221                                                            devlink_port,
1222                                                            devlink_sb,
1223                                                            pool_index,
1224                                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
1225                                                            portid, seq,
1226                                                            NLM_F_MULTI);
1227                         if (err)
1228                                 return err;
1229                         (*p_idx)++;
1230                 }
1231         }
1232         return 0;
1233 }
1234
1235 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1236                                                   struct netlink_callback *cb)
1237 {
1238         struct devlink *devlink;
1239         struct devlink_sb *devlink_sb;
1240         int start = cb->args[0];
1241         int idx = 0;
1242         int err;
1243
1244         mutex_lock(&devlink_mutex);
1245         list_for_each_entry(devlink, &devlink_list, list) {
1246                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1247                     !devlink->ops->sb_port_pool_get)
1248                         continue;
1249                 mutex_lock(&devlink->lock);
1250                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1251                         err = __sb_port_pool_get_dumpit(msg, start, &idx,
1252                                                         devlink, devlink_sb,
1253                                                         NETLINK_CB(cb->skb).portid,
1254                                                         cb->nlh->nlmsg_seq);
1255                         if (err && err != -EOPNOTSUPP) {
1256                                 mutex_unlock(&devlink->lock);
1257                                 goto out;
1258                         }
1259                 }
1260                 mutex_unlock(&devlink->lock);
1261         }
1262 out:
1263         mutex_unlock(&devlink_mutex);
1264
1265         cb->args[0] = idx;
1266         return msg->len;
1267 }
1268
1269 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1270                                     unsigned int sb_index, u16 pool_index,
1271                                     u32 threshold,
1272                                     struct netlink_ext_ack *extack)
1273
1274 {
1275         const struct devlink_ops *ops = devlink_port->devlink->ops;
1276
1277         if (ops->sb_port_pool_set)
1278                 return ops->sb_port_pool_set(devlink_port, sb_index,
1279                                              pool_index, threshold, extack);
1280         return -EOPNOTSUPP;
1281 }
1282
1283 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1284                                                 struct genl_info *info)
1285 {
1286         struct devlink_port *devlink_port = info->user_ptr[0];
1287         struct devlink_sb *devlink_sb = info->user_ptr[1];
1288         u16 pool_index;
1289         u32 threshold;
1290         int err;
1291
1292         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1293                                                   &pool_index);
1294         if (err)
1295                 return err;
1296
1297         if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1298                 return -EINVAL;
1299
1300         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1301         return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1302                                         pool_index, threshold, info->extack);
1303 }
1304
1305 static int
1306 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1307                                 struct devlink_port *devlink_port,
1308                                 struct devlink_sb *devlink_sb, u16 tc_index,
1309                                 enum devlink_sb_pool_type pool_type,
1310                                 enum devlink_command cmd,
1311                                 u32 portid, u32 seq, int flags)
1312 {
1313         const struct devlink_ops *ops = devlink->ops;
1314         u16 pool_index;
1315         u32 threshold;
1316         void *hdr;
1317         int err;
1318
1319         err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1320                                        tc_index, pool_type,
1321                                        &pool_index, &threshold);
1322         if (err)
1323                 return err;
1324
1325         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1326         if (!hdr)
1327                 return -EMSGSIZE;
1328
1329         if (devlink_nl_put_handle(msg, devlink))
1330                 goto nla_put_failure;
1331         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1332                 goto nla_put_failure;
1333         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1334                 goto nla_put_failure;
1335         if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1336                 goto nla_put_failure;
1337         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1338                 goto nla_put_failure;
1339         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1340                 goto nla_put_failure;
1341         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1342                 goto nla_put_failure;
1343
1344         if (ops->sb_occ_tc_port_bind_get) {
1345                 u32 cur;
1346                 u32 max;
1347
1348                 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1349                                                    devlink_sb->index,
1350                                                    tc_index, pool_type,
1351                                                    &cur, &max);
1352                 if (err && err != -EOPNOTSUPP)
1353                         return err;
1354                 if (!err) {
1355                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1356                                 goto nla_put_failure;
1357                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1358                                 goto nla_put_failure;
1359                 }
1360         }
1361
1362         genlmsg_end(msg, hdr);
1363         return 0;
1364
1365 nla_put_failure:
1366         genlmsg_cancel(msg, hdr);
1367         return -EMSGSIZE;
1368 }
1369
1370 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1371                                                    struct genl_info *info)
1372 {
1373         struct devlink_port *devlink_port = info->user_ptr[0];
1374         struct devlink *devlink = devlink_port->devlink;
1375         struct devlink_sb *devlink_sb = info->user_ptr[1];
1376         struct sk_buff *msg;
1377         enum devlink_sb_pool_type pool_type;
1378         u16 tc_index;
1379         int err;
1380
1381         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1382         if (err)
1383                 return err;
1384
1385         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1386                                                 pool_type, &tc_index);
1387         if (err)
1388                 return err;
1389
1390         if (!devlink->ops->sb_tc_pool_bind_get)
1391                 return -EOPNOTSUPP;
1392
1393         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1394         if (!msg)
1395                 return -ENOMEM;
1396
1397         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1398                                               devlink_sb, tc_index, pool_type,
1399                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1400                                               info->snd_portid,
1401                                               info->snd_seq, 0);
1402         if (err) {
1403                 nlmsg_free(msg);
1404                 return err;
1405         }
1406
1407         return genlmsg_reply(msg, info);
1408 }
1409
1410 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1411                                         int start, int *p_idx,
1412                                         struct devlink *devlink,
1413                                         struct devlink_sb *devlink_sb,
1414                                         u32 portid, u32 seq)
1415 {
1416         struct devlink_port *devlink_port;
1417         u16 tc_index;
1418         int err;
1419
1420         list_for_each_entry(devlink_port, &devlink->port_list, list) {
1421                 for (tc_index = 0;
1422                      tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1423                         if (*p_idx < start) {
1424                                 (*p_idx)++;
1425                                 continue;
1426                         }
1427                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1428                                                               devlink_port,
1429                                                               devlink_sb,
1430                                                               tc_index,
1431                                                               DEVLINK_SB_POOL_TYPE_INGRESS,
1432                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1433                                                               portid, seq,
1434                                                               NLM_F_MULTI);
1435                         if (err)
1436                                 return err;
1437                         (*p_idx)++;
1438                 }
1439                 for (tc_index = 0;
1440                      tc_index < devlink_sb->egress_tc_count; tc_index++) {
1441                         if (*p_idx < start) {
1442                                 (*p_idx)++;
1443                                 continue;
1444                         }
1445                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1446                                                               devlink_port,
1447                                                               devlink_sb,
1448                                                               tc_index,
1449                                                               DEVLINK_SB_POOL_TYPE_EGRESS,
1450                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1451                                                               portid, seq,
1452                                                               NLM_F_MULTI);
1453                         if (err)
1454                                 return err;
1455                         (*p_idx)++;
1456                 }
1457         }
1458         return 0;
1459 }
1460
1461 static int
1462 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1463                                           struct netlink_callback *cb)
1464 {
1465         struct devlink *devlink;
1466         struct devlink_sb *devlink_sb;
1467         int start = cb->args[0];
1468         int idx = 0;
1469         int err;
1470
1471         mutex_lock(&devlink_mutex);
1472         list_for_each_entry(devlink, &devlink_list, list) {
1473                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1474                     !devlink->ops->sb_tc_pool_bind_get)
1475                         continue;
1476
1477                 mutex_lock(&devlink->lock);
1478                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1479                         err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1480                                                            devlink,
1481                                                            devlink_sb,
1482                                                            NETLINK_CB(cb->skb).portid,
1483                                                            cb->nlh->nlmsg_seq);
1484                         if (err && err != -EOPNOTSUPP) {
1485                                 mutex_unlock(&devlink->lock);
1486                                 goto out;
1487                         }
1488                 }
1489                 mutex_unlock(&devlink->lock);
1490         }
1491 out:
1492         mutex_unlock(&devlink_mutex);
1493
1494         cb->args[0] = idx;
1495         return msg->len;
1496 }
1497
1498 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1499                                        unsigned int sb_index, u16 tc_index,
1500                                        enum devlink_sb_pool_type pool_type,
1501                                        u16 pool_index, u32 threshold,
1502                                        struct netlink_ext_ack *extack)
1503
1504 {
1505         const struct devlink_ops *ops = devlink_port->devlink->ops;
1506
1507         if (ops->sb_tc_pool_bind_set)
1508                 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1509                                                 tc_index, pool_type,
1510                                                 pool_index, threshold, extack);
1511         return -EOPNOTSUPP;
1512 }
1513
1514 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1515                                                    struct genl_info *info)
1516 {
1517         struct devlink_port *devlink_port = info->user_ptr[0];
1518         struct devlink_sb *devlink_sb = info->user_ptr[1];
1519         enum devlink_sb_pool_type pool_type;
1520         u16 tc_index;
1521         u16 pool_index;
1522         u32 threshold;
1523         int err;
1524
1525         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1526         if (err)
1527                 return err;
1528
1529         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1530                                                 pool_type, &tc_index);
1531         if (err)
1532                 return err;
1533
1534         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1535                                                   &pool_index);
1536         if (err)
1537                 return err;
1538
1539         if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1540                 return -EINVAL;
1541
1542         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1543         return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1544                                            tc_index, pool_type,
1545                                            pool_index, threshold, info->extack);
1546 }
1547
1548 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1549                                                struct genl_info *info)
1550 {
1551         struct devlink *devlink = info->user_ptr[0];
1552         struct devlink_sb *devlink_sb = info->user_ptr[1];
1553         const struct devlink_ops *ops = devlink->ops;
1554
1555         if (ops->sb_occ_snapshot)
1556                 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1557         return -EOPNOTSUPP;
1558 }
1559
1560 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1561                                                 struct genl_info *info)
1562 {
1563         struct devlink *devlink = info->user_ptr[0];
1564         struct devlink_sb *devlink_sb = info->user_ptr[1];
1565         const struct devlink_ops *ops = devlink->ops;
1566
1567         if (ops->sb_occ_max_clear)
1568                 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1569         return -EOPNOTSUPP;
1570 }
1571
1572 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1573                                    enum devlink_command cmd, u32 portid,
1574                                    u32 seq, int flags)
1575 {
1576         const struct devlink_ops *ops = devlink->ops;
1577         enum devlink_eswitch_encap_mode encap_mode;
1578         u8 inline_mode;
1579         void *hdr;
1580         int err = 0;
1581         u16 mode;
1582
1583         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1584         if (!hdr)
1585                 return -EMSGSIZE;
1586
1587         err = devlink_nl_put_handle(msg, devlink);
1588         if (err)
1589                 goto nla_put_failure;
1590
1591         if (ops->eswitch_mode_get) {
1592                 err = ops->eswitch_mode_get(devlink, &mode);
1593                 if (err)
1594                         goto nla_put_failure;
1595                 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1596                 if (err)
1597                         goto nla_put_failure;
1598         }
1599
1600         if (ops->eswitch_inline_mode_get) {
1601                 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1602                 if (err)
1603                         goto nla_put_failure;
1604                 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1605                                  inline_mode);
1606                 if (err)
1607                         goto nla_put_failure;
1608         }
1609
1610         if (ops->eswitch_encap_mode_get) {
1611                 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1612                 if (err)
1613                         goto nla_put_failure;
1614                 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1615                 if (err)
1616                         goto nla_put_failure;
1617         }
1618
1619         genlmsg_end(msg, hdr);
1620         return 0;
1621
1622 nla_put_failure:
1623         genlmsg_cancel(msg, hdr);
1624         return err;
1625 }
1626
1627 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1628                                            struct genl_info *info)
1629 {
1630         struct devlink *devlink = info->user_ptr[0];
1631         struct sk_buff *msg;
1632         int err;
1633
1634         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1635         if (!msg)
1636                 return -ENOMEM;
1637
1638         err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1639                                       info->snd_portid, info->snd_seq, 0);
1640
1641         if (err) {
1642                 nlmsg_free(msg);
1643                 return err;
1644         }
1645
1646         return genlmsg_reply(msg, info);
1647 }
1648
1649 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1650                                            struct genl_info *info)
1651 {
1652         struct devlink *devlink = info->user_ptr[0];
1653         const struct devlink_ops *ops = devlink->ops;
1654         enum devlink_eswitch_encap_mode encap_mode;
1655         u8 inline_mode;
1656         int err = 0;
1657         u16 mode;
1658
1659         if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1660                 if (!ops->eswitch_mode_set)
1661                         return -EOPNOTSUPP;
1662                 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1663                 err = ops->eswitch_mode_set(devlink, mode, info->extack);
1664                 if (err)
1665                         return err;
1666         }
1667
1668         if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1669                 if (!ops->eswitch_inline_mode_set)
1670                         return -EOPNOTSUPP;
1671                 inline_mode = nla_get_u8(
1672                                 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1673                 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1674                                                    info->extack);
1675                 if (err)
1676                         return err;
1677         }
1678
1679         if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1680                 if (!ops->eswitch_encap_mode_set)
1681                         return -EOPNOTSUPP;
1682                 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1683                 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1684                                                   info->extack);
1685                 if (err)
1686                         return err;
1687         }
1688
1689         return 0;
1690 }
1691
1692 int devlink_dpipe_match_put(struct sk_buff *skb,
1693                             struct devlink_dpipe_match *match)
1694 {
1695         struct devlink_dpipe_header *header = match->header;
1696         struct devlink_dpipe_field *field = &header->fields[match->field_id];
1697         struct nlattr *match_attr;
1698
1699         match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1700         if (!match_attr)
1701                 return -EMSGSIZE;
1702
1703         if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1704             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1705             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1706             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1707             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1708                 goto nla_put_failure;
1709
1710         nla_nest_end(skb, match_attr);
1711         return 0;
1712
1713 nla_put_failure:
1714         nla_nest_cancel(skb, match_attr);
1715         return -EMSGSIZE;
1716 }
1717 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1718
1719 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1720                                      struct sk_buff *skb)
1721 {
1722         struct nlattr *matches_attr;
1723
1724         matches_attr = nla_nest_start_noflag(skb,
1725                                              DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1726         if (!matches_attr)
1727                 return -EMSGSIZE;
1728
1729         if (table->table_ops->matches_dump(table->priv, skb))
1730                 goto nla_put_failure;
1731
1732         nla_nest_end(skb, matches_attr);
1733         return 0;
1734
1735 nla_put_failure:
1736         nla_nest_cancel(skb, matches_attr);
1737         return -EMSGSIZE;
1738 }
1739
1740 int devlink_dpipe_action_put(struct sk_buff *skb,
1741                              struct devlink_dpipe_action *action)
1742 {
1743         struct devlink_dpipe_header *header = action->header;
1744         struct devlink_dpipe_field *field = &header->fields[action->field_id];
1745         struct nlattr *action_attr;
1746
1747         action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1748         if (!action_attr)
1749                 return -EMSGSIZE;
1750
1751         if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1752             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1753             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1754             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1755             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1756                 goto nla_put_failure;
1757
1758         nla_nest_end(skb, action_attr);
1759         return 0;
1760
1761 nla_put_failure:
1762         nla_nest_cancel(skb, action_attr);
1763         return -EMSGSIZE;
1764 }
1765 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1766
1767 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1768                                      struct sk_buff *skb)
1769 {
1770         struct nlattr *actions_attr;
1771
1772         actions_attr = nla_nest_start_noflag(skb,
1773                                              DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1774         if (!actions_attr)
1775                 return -EMSGSIZE;
1776
1777         if (table->table_ops->actions_dump(table->priv, skb))
1778                 goto nla_put_failure;
1779
1780         nla_nest_end(skb, actions_attr);
1781         return 0;
1782
1783 nla_put_failure:
1784         nla_nest_cancel(skb, actions_attr);
1785         return -EMSGSIZE;
1786 }
1787
1788 static int devlink_dpipe_table_put(struct sk_buff *skb,
1789                                    struct devlink_dpipe_table *table)
1790 {
1791         struct nlattr *table_attr;
1792         u64 table_size;
1793
1794         table_size = table->table_ops->size_get(table->priv);
1795         table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1796         if (!table_attr)
1797                 return -EMSGSIZE;
1798
1799         if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1800             nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1801                               DEVLINK_ATTR_PAD))
1802                 goto nla_put_failure;
1803         if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1804                        table->counters_enabled))
1805                 goto nla_put_failure;
1806
1807         if (table->resource_valid) {
1808                 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1809                                       table->resource_id, DEVLINK_ATTR_PAD) ||
1810                     nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1811                                       table->resource_units, DEVLINK_ATTR_PAD))
1812                         goto nla_put_failure;
1813         }
1814         if (devlink_dpipe_matches_put(table, skb))
1815                 goto nla_put_failure;
1816
1817         if (devlink_dpipe_actions_put(table, skb))
1818                 goto nla_put_failure;
1819
1820         nla_nest_end(skb, table_attr);
1821         return 0;
1822
1823 nla_put_failure:
1824         nla_nest_cancel(skb, table_attr);
1825         return -EMSGSIZE;
1826 }
1827
1828 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1829                                             struct genl_info *info)
1830 {
1831         int err;
1832
1833         if (*pskb) {
1834                 err = genlmsg_reply(*pskb, info);
1835                 if (err)
1836                         return err;
1837         }
1838         *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1839         if (!*pskb)
1840                 return -ENOMEM;
1841         return 0;
1842 }
1843
1844 static int devlink_dpipe_tables_fill(struct genl_info *info,
1845                                      enum devlink_command cmd, int flags,
1846                                      struct list_head *dpipe_tables,
1847                                      const char *table_name)
1848 {
1849         struct devlink *devlink = info->user_ptr[0];
1850         struct devlink_dpipe_table *table;
1851         struct nlattr *tables_attr;
1852         struct sk_buff *skb = NULL;
1853         struct nlmsghdr *nlh;
1854         bool incomplete;
1855         void *hdr;
1856         int i;
1857         int err;
1858
1859         table = list_first_entry(dpipe_tables,
1860                                  struct devlink_dpipe_table, list);
1861 start_again:
1862         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1863         if (err)
1864                 return err;
1865
1866         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1867                           &devlink_nl_family, NLM_F_MULTI, cmd);
1868         if (!hdr) {
1869                 nlmsg_free(skb);
1870                 return -EMSGSIZE;
1871         }
1872
1873         if (devlink_nl_put_handle(skb, devlink))
1874                 goto nla_put_failure;
1875         tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1876         if (!tables_attr)
1877                 goto nla_put_failure;
1878
1879         i = 0;
1880         incomplete = false;
1881         list_for_each_entry_from(table, dpipe_tables, list) {
1882                 if (!table_name) {
1883                         err = devlink_dpipe_table_put(skb, table);
1884                         if (err) {
1885                                 if (!i)
1886                                         goto err_table_put;
1887                                 incomplete = true;
1888                                 break;
1889                         }
1890                 } else {
1891                         if (!strcmp(table->name, table_name)) {
1892                                 err = devlink_dpipe_table_put(skb, table);
1893                                 if (err)
1894                                         break;
1895                         }
1896                 }
1897                 i++;
1898         }
1899
1900         nla_nest_end(skb, tables_attr);
1901         genlmsg_end(skb, hdr);
1902         if (incomplete)
1903                 goto start_again;
1904
1905 send_done:
1906         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1907                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
1908         if (!nlh) {
1909                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1910                 if (err)
1911                         return err;
1912                 goto send_done;
1913         }
1914
1915         return genlmsg_reply(skb, info);
1916
1917 nla_put_failure:
1918         err = -EMSGSIZE;
1919 err_table_put:
1920         nlmsg_free(skb);
1921         return err;
1922 }
1923
1924 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1925                                           struct genl_info *info)
1926 {
1927         struct devlink *devlink = info->user_ptr[0];
1928         const char *table_name =  NULL;
1929
1930         if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1931                 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1932
1933         return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1934                                          &devlink->dpipe_table_list,
1935                                          table_name);
1936 }
1937
1938 static int devlink_dpipe_value_put(struct sk_buff *skb,
1939                                    struct devlink_dpipe_value *value)
1940 {
1941         if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1942                     value->value_size, value->value))
1943                 return -EMSGSIZE;
1944         if (value->mask)
1945                 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1946                             value->value_size, value->mask))
1947                         return -EMSGSIZE;
1948         if (value->mapping_valid)
1949                 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1950                                 value->mapping_value))
1951                         return -EMSGSIZE;
1952         return 0;
1953 }
1954
1955 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1956                                           struct devlink_dpipe_value *value)
1957 {
1958         if (!value->action)
1959                 return -EINVAL;
1960         if (devlink_dpipe_action_put(skb, value->action))
1961                 return -EMSGSIZE;
1962         if (devlink_dpipe_value_put(skb, value))
1963                 return -EMSGSIZE;
1964         return 0;
1965 }
1966
1967 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1968                                            struct devlink_dpipe_value *values,
1969                                            unsigned int values_count)
1970 {
1971         struct nlattr *action_attr;
1972         int i;
1973         int err;
1974
1975         for (i = 0; i < values_count; i++) {
1976                 action_attr = nla_nest_start_noflag(skb,
1977                                                     DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1978                 if (!action_attr)
1979                         return -EMSGSIZE;
1980                 err = devlink_dpipe_action_value_put(skb, &values[i]);
1981                 if (err)
1982                         goto err_action_value_put;
1983                 nla_nest_end(skb, action_attr);
1984         }
1985         return 0;
1986
1987 err_action_value_put:
1988         nla_nest_cancel(skb, action_attr);
1989         return err;
1990 }
1991
1992 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1993                                          struct devlink_dpipe_value *value)
1994 {
1995         if (!value->match)
1996                 return -EINVAL;
1997         if (devlink_dpipe_match_put(skb, value->match))
1998                 return -EMSGSIZE;
1999         if (devlink_dpipe_value_put(skb, value))
2000                 return -EMSGSIZE;
2001         return 0;
2002 }
2003
2004 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
2005                                           struct devlink_dpipe_value *values,
2006                                           unsigned int values_count)
2007 {
2008         struct nlattr *match_attr;
2009         int i;
2010         int err;
2011
2012         for (i = 0; i < values_count; i++) {
2013                 match_attr = nla_nest_start_noflag(skb,
2014                                                    DEVLINK_ATTR_DPIPE_MATCH_VALUE);
2015                 if (!match_attr)
2016                         return -EMSGSIZE;
2017                 err = devlink_dpipe_match_value_put(skb, &values[i]);
2018                 if (err)
2019                         goto err_match_value_put;
2020                 nla_nest_end(skb, match_attr);
2021         }
2022         return 0;
2023
2024 err_match_value_put:
2025         nla_nest_cancel(skb, match_attr);
2026         return err;
2027 }
2028
2029 static int devlink_dpipe_entry_put(struct sk_buff *skb,
2030                                    struct devlink_dpipe_entry *entry)
2031 {
2032         struct nlattr *entry_attr, *matches_attr, *actions_attr;
2033         int err;
2034
2035         entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2036         if (!entry_attr)
2037                 return  -EMSGSIZE;
2038
2039         if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2040                               DEVLINK_ATTR_PAD))
2041                 goto nla_put_failure;
2042         if (entry->counter_valid)
2043                 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2044                                       entry->counter, DEVLINK_ATTR_PAD))
2045                         goto nla_put_failure;
2046
2047         matches_attr = nla_nest_start_noflag(skb,
2048                                              DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2049         if (!matches_attr)
2050                 goto nla_put_failure;
2051
2052         err = devlink_dpipe_match_values_put(skb, entry->match_values,
2053                                              entry->match_values_count);
2054         if (err) {
2055                 nla_nest_cancel(skb, matches_attr);
2056                 goto err_match_values_put;
2057         }
2058         nla_nest_end(skb, matches_attr);
2059
2060         actions_attr = nla_nest_start_noflag(skb,
2061                                              DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2062         if (!actions_attr)
2063                 goto nla_put_failure;
2064
2065         err = devlink_dpipe_action_values_put(skb, entry->action_values,
2066                                               entry->action_values_count);
2067         if (err) {
2068                 nla_nest_cancel(skb, actions_attr);
2069                 goto err_action_values_put;
2070         }
2071         nla_nest_end(skb, actions_attr);
2072
2073         nla_nest_end(skb, entry_attr);
2074         return 0;
2075
2076 nla_put_failure:
2077         err = -EMSGSIZE;
2078 err_match_values_put:
2079 err_action_values_put:
2080         nla_nest_cancel(skb, entry_attr);
2081         return err;
2082 }
2083
2084 static struct devlink_dpipe_table *
2085 devlink_dpipe_table_find(struct list_head *dpipe_tables,
2086                          const char *table_name)
2087 {
2088         struct devlink_dpipe_table *table;
2089
2090         list_for_each_entry_rcu(table, dpipe_tables, list) {
2091                 if (!strcmp(table->name, table_name))
2092                         return table;
2093         }
2094         return NULL;
2095 }
2096
2097 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2098 {
2099         struct devlink *devlink;
2100         int err;
2101
2102         err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2103                                                dump_ctx->info);
2104         if (err)
2105                 return err;
2106
2107         dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2108                                     dump_ctx->info->snd_portid,
2109                                     dump_ctx->info->snd_seq,
2110                                     &devlink_nl_family, NLM_F_MULTI,
2111                                     dump_ctx->cmd);
2112         if (!dump_ctx->hdr)
2113                 goto nla_put_failure;
2114
2115         devlink = dump_ctx->info->user_ptr[0];
2116         if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2117                 goto nla_put_failure;
2118         dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2119                                                DEVLINK_ATTR_DPIPE_ENTRIES);
2120         if (!dump_ctx->nest)
2121                 goto nla_put_failure;
2122         return 0;
2123
2124 nla_put_failure:
2125         nlmsg_free(dump_ctx->skb);
2126         return -EMSGSIZE;
2127 }
2128 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2129
2130 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2131                                    struct devlink_dpipe_entry *entry)
2132 {
2133         return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2134 }
2135 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2136
2137 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2138 {
2139         nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2140         genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2141         return 0;
2142 }
2143 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2144
2145 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2146
2147 {
2148         unsigned int value_count, value_index;
2149         struct devlink_dpipe_value *value;
2150
2151         value = entry->action_values;
2152         value_count = entry->action_values_count;
2153         for (value_index = 0; value_index < value_count; value_index++) {
2154                 kfree(value[value_index].value);
2155                 kfree(value[value_index].mask);
2156         }
2157
2158         value = entry->match_values;
2159         value_count = entry->match_values_count;
2160         for (value_index = 0; value_index < value_count; value_index++) {
2161                 kfree(value[value_index].value);
2162                 kfree(value[value_index].mask);
2163         }
2164 }
2165 EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2166
2167 static int devlink_dpipe_entries_fill(struct genl_info *info,
2168                                       enum devlink_command cmd, int flags,
2169                                       struct devlink_dpipe_table *table)
2170 {
2171         struct devlink_dpipe_dump_ctx dump_ctx;
2172         struct nlmsghdr *nlh;
2173         int err;
2174
2175         dump_ctx.skb = NULL;
2176         dump_ctx.cmd = cmd;
2177         dump_ctx.info = info;
2178
2179         err = table->table_ops->entries_dump(table->priv,
2180                                              table->counters_enabled,
2181                                              &dump_ctx);
2182         if (err)
2183                 return err;
2184
2185 send_done:
2186         nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2187                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2188         if (!nlh) {
2189                 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2190                 if (err)
2191                         return err;
2192                 goto send_done;
2193         }
2194         return genlmsg_reply(dump_ctx.skb, info);
2195 }
2196
2197 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2198                                             struct genl_info *info)
2199 {
2200         struct devlink *devlink = info->user_ptr[0];
2201         struct devlink_dpipe_table *table;
2202         const char *table_name;
2203
2204         if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2205                 return -EINVAL;
2206
2207         table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2208         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2209                                          table_name);
2210         if (!table)
2211                 return -EINVAL;
2212
2213         if (!table->table_ops->entries_dump)
2214                 return -EINVAL;
2215
2216         return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2217                                           0, table);
2218 }
2219
2220 static int devlink_dpipe_fields_put(struct sk_buff *skb,
2221                                     const struct devlink_dpipe_header *header)
2222 {
2223         struct devlink_dpipe_field *field;
2224         struct nlattr *field_attr;
2225         int i;
2226
2227         for (i = 0; i < header->fields_count; i++) {
2228                 field = &header->fields[i];
2229                 field_attr = nla_nest_start_noflag(skb,
2230                                                    DEVLINK_ATTR_DPIPE_FIELD);
2231                 if (!field_attr)
2232                         return -EMSGSIZE;
2233                 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2234                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2235                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2236                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2237                         goto nla_put_failure;
2238                 nla_nest_end(skb, field_attr);
2239         }
2240         return 0;
2241
2242 nla_put_failure:
2243         nla_nest_cancel(skb, field_attr);
2244         return -EMSGSIZE;
2245 }
2246
2247 static int devlink_dpipe_header_put(struct sk_buff *skb,
2248                                     struct devlink_dpipe_header *header)
2249 {
2250         struct nlattr *fields_attr, *header_attr;
2251         int err;
2252
2253         header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2254         if (!header_attr)
2255                 return -EMSGSIZE;
2256
2257         if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2258             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2259             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2260                 goto nla_put_failure;
2261
2262         fields_attr = nla_nest_start_noflag(skb,
2263                                             DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2264         if (!fields_attr)
2265                 goto nla_put_failure;
2266
2267         err = devlink_dpipe_fields_put(skb, header);
2268         if (err) {
2269                 nla_nest_cancel(skb, fields_attr);
2270                 goto nla_put_failure;
2271         }
2272         nla_nest_end(skb, fields_attr);
2273         nla_nest_end(skb, header_attr);
2274         return 0;
2275
2276 nla_put_failure:
2277         err = -EMSGSIZE;
2278         nla_nest_cancel(skb, header_attr);
2279         return err;
2280 }
2281
2282 static int devlink_dpipe_headers_fill(struct genl_info *info,
2283                                       enum devlink_command cmd, int flags,
2284                                       struct devlink_dpipe_headers *
2285                                       dpipe_headers)
2286 {
2287         struct devlink *devlink = info->user_ptr[0];
2288         struct nlattr *headers_attr;
2289         struct sk_buff *skb = NULL;
2290         struct nlmsghdr *nlh;
2291         void *hdr;
2292         int i, j;
2293         int err;
2294
2295         i = 0;
2296 start_again:
2297         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2298         if (err)
2299                 return err;
2300
2301         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2302                           &devlink_nl_family, NLM_F_MULTI, cmd);
2303         if (!hdr) {
2304                 nlmsg_free(skb);
2305                 return -EMSGSIZE;
2306         }
2307
2308         if (devlink_nl_put_handle(skb, devlink))
2309                 goto nla_put_failure;
2310         headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2311         if (!headers_attr)
2312                 goto nla_put_failure;
2313
2314         j = 0;
2315         for (; i < dpipe_headers->headers_count; i++) {
2316                 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2317                 if (err) {
2318                         if (!j)
2319                                 goto err_table_put;
2320                         break;
2321                 }
2322                 j++;
2323         }
2324         nla_nest_end(skb, headers_attr);
2325         genlmsg_end(skb, hdr);
2326         if (i != dpipe_headers->headers_count)
2327                 goto start_again;
2328
2329 send_done:
2330         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2331                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2332         if (!nlh) {
2333                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2334                 if (err)
2335                         return err;
2336                 goto send_done;
2337         }
2338         return genlmsg_reply(skb, info);
2339
2340 nla_put_failure:
2341         err = -EMSGSIZE;
2342 err_table_put:
2343         nlmsg_free(skb);
2344         return err;
2345 }
2346
2347 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2348                                             struct genl_info *info)
2349 {
2350         struct devlink *devlink = info->user_ptr[0];
2351
2352         if (!devlink->dpipe_headers)
2353                 return -EOPNOTSUPP;
2354         return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2355                                           0, devlink->dpipe_headers);
2356 }
2357
2358 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2359                                             const char *table_name,
2360                                             bool enable)
2361 {
2362         struct devlink_dpipe_table *table;
2363
2364         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2365                                          table_name);
2366         if (!table)
2367                 return -EINVAL;
2368
2369         if (table->counter_control_extern)
2370                 return -EOPNOTSUPP;
2371
2372         if (!(table->counters_enabled ^ enable))
2373                 return 0;
2374
2375         table->counters_enabled = enable;
2376         if (table->table_ops->counters_set_update)
2377                 table->table_ops->counters_set_update(table->priv, enable);
2378         return 0;
2379 }
2380
2381 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2382                                                    struct genl_info *info)
2383 {
2384         struct devlink *devlink = info->user_ptr[0];
2385         const char *table_name;
2386         bool counters_enable;
2387
2388         if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2389             !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2390                 return -EINVAL;
2391
2392         table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2393         counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2394
2395         return devlink_dpipe_table_counters_set(devlink, table_name,
2396                                                 counters_enable);
2397 }
2398
2399 static struct devlink_resource *
2400 devlink_resource_find(struct devlink *devlink,
2401                       struct devlink_resource *resource, u64 resource_id)
2402 {
2403         struct list_head *resource_list;
2404
2405         if (resource)
2406                 resource_list = &resource->resource_list;
2407         else
2408                 resource_list = &devlink->resource_list;
2409
2410         list_for_each_entry(resource, resource_list, list) {
2411                 struct devlink_resource *child_resource;
2412
2413                 if (resource->id == resource_id)
2414                         return resource;
2415
2416                 child_resource = devlink_resource_find(devlink, resource,
2417                                                        resource_id);
2418                 if (child_resource)
2419                         return child_resource;
2420         }
2421         return NULL;
2422 }
2423
2424 static void
2425 devlink_resource_validate_children(struct devlink_resource *resource)
2426 {
2427         struct devlink_resource *child_resource;
2428         bool size_valid = true;
2429         u64 parts_size = 0;
2430
2431         if (list_empty(&resource->resource_list))
2432                 goto out;
2433
2434         list_for_each_entry(child_resource, &resource->resource_list, list)
2435                 parts_size += child_resource->size_new;
2436
2437         if (parts_size > resource->size_new)
2438                 size_valid = false;
2439 out:
2440         resource->size_valid = size_valid;
2441 }
2442
2443 static int
2444 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2445                                struct netlink_ext_ack *extack)
2446 {
2447         u64 reminder;
2448         int err = 0;
2449
2450         if (size > resource->size_params.size_max) {
2451                 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2452                 err = -EINVAL;
2453         }
2454
2455         if (size < resource->size_params.size_min) {
2456                 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2457                 err = -EINVAL;
2458         }
2459
2460         div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2461         if (reminder) {
2462                 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2463                 err = -EINVAL;
2464         }
2465
2466         return err;
2467 }
2468
2469 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2470                                        struct genl_info *info)
2471 {
2472         struct devlink *devlink = info->user_ptr[0];
2473         struct devlink_resource *resource;
2474         u64 resource_id;
2475         u64 size;
2476         int err;
2477
2478         if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2479             !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2480                 return -EINVAL;
2481         resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2482
2483         resource = devlink_resource_find(devlink, NULL, resource_id);
2484         if (!resource)
2485                 return -EINVAL;
2486
2487         size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2488         err = devlink_resource_validate_size(resource, size, info->extack);
2489         if (err)
2490                 return err;
2491
2492         resource->size_new = size;
2493         devlink_resource_validate_children(resource);
2494         if (resource->parent)
2495                 devlink_resource_validate_children(resource->parent);
2496         return 0;
2497 }
2498
2499 static int
2500 devlink_resource_size_params_put(struct devlink_resource *resource,
2501                                  struct sk_buff *skb)
2502 {
2503         struct devlink_resource_size_params *size_params;
2504
2505         size_params = &resource->size_params;
2506         if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2507                               size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2508             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2509                               size_params->size_max, DEVLINK_ATTR_PAD) ||
2510             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2511                               size_params->size_min, DEVLINK_ATTR_PAD) ||
2512             nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2513                 return -EMSGSIZE;
2514         return 0;
2515 }
2516
2517 static int devlink_resource_occ_put(struct devlink_resource *resource,
2518                                     struct sk_buff *skb)
2519 {
2520         if (!resource->occ_get)
2521                 return 0;
2522         return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2523                                  resource->occ_get(resource->occ_get_priv),
2524                                  DEVLINK_ATTR_PAD);
2525 }
2526
2527 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2528                                 struct devlink_resource *resource)
2529 {
2530         struct devlink_resource *child_resource;
2531         struct nlattr *child_resource_attr;
2532         struct nlattr *resource_attr;
2533
2534         resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2535         if (!resource_attr)
2536                 return -EMSGSIZE;
2537
2538         if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2539             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2540                               DEVLINK_ATTR_PAD) ||
2541             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2542                               DEVLINK_ATTR_PAD))
2543                 goto nla_put_failure;
2544         if (resource->size != resource->size_new)
2545                 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2546                                   resource->size_new, DEVLINK_ATTR_PAD);
2547         if (devlink_resource_occ_put(resource, skb))
2548                 goto nla_put_failure;
2549         if (devlink_resource_size_params_put(resource, skb))
2550                 goto nla_put_failure;
2551         if (list_empty(&resource->resource_list))
2552                 goto out;
2553
2554         if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2555                        resource->size_valid))
2556                 goto nla_put_failure;
2557
2558         child_resource_attr = nla_nest_start_noflag(skb,
2559                                                     DEVLINK_ATTR_RESOURCE_LIST);
2560         if (!child_resource_attr)
2561                 goto nla_put_failure;
2562
2563         list_for_each_entry(child_resource, &resource->resource_list, list) {
2564                 if (devlink_resource_put(devlink, skb, child_resource))
2565                         goto resource_put_failure;
2566         }
2567
2568         nla_nest_end(skb, child_resource_attr);
2569 out:
2570         nla_nest_end(skb, resource_attr);
2571         return 0;
2572
2573 resource_put_failure:
2574         nla_nest_cancel(skb, child_resource_attr);
2575 nla_put_failure:
2576         nla_nest_cancel(skb, resource_attr);
2577         return -EMSGSIZE;
2578 }
2579
2580 static int devlink_resource_fill(struct genl_info *info,
2581                                  enum devlink_command cmd, int flags)
2582 {
2583         struct devlink *devlink = info->user_ptr[0];
2584         struct devlink_resource *resource;
2585         struct nlattr *resources_attr;
2586         struct sk_buff *skb = NULL;
2587         struct nlmsghdr *nlh;
2588         bool incomplete;
2589         void *hdr;
2590         int i;
2591         int err;
2592
2593         resource = list_first_entry(&devlink->resource_list,
2594                                     struct devlink_resource, list);
2595 start_again:
2596         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2597         if (err)
2598                 return err;
2599
2600         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2601                           &devlink_nl_family, NLM_F_MULTI, cmd);
2602         if (!hdr) {
2603                 nlmsg_free(skb);
2604                 return -EMSGSIZE;
2605         }
2606
2607         if (devlink_nl_put_handle(skb, devlink))
2608                 goto nla_put_failure;
2609
2610         resources_attr = nla_nest_start_noflag(skb,
2611                                                DEVLINK_ATTR_RESOURCE_LIST);
2612         if (!resources_attr)
2613                 goto nla_put_failure;
2614
2615         incomplete = false;
2616         i = 0;
2617         list_for_each_entry_from(resource, &devlink->resource_list, list) {
2618                 err = devlink_resource_put(devlink, skb, resource);
2619                 if (err) {
2620                         if (!i)
2621                                 goto err_resource_put;
2622                         incomplete = true;
2623                         break;
2624                 }
2625                 i++;
2626         }
2627         nla_nest_end(skb, resources_attr);
2628         genlmsg_end(skb, hdr);
2629         if (incomplete)
2630                 goto start_again;
2631 send_done:
2632         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2633                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2634         if (!nlh) {
2635                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2636                 if (err)
2637                         return err;
2638                 goto send_done;
2639         }
2640         return genlmsg_reply(skb, info);
2641
2642 nla_put_failure:
2643         err = -EMSGSIZE;
2644 err_resource_put:
2645         nlmsg_free(skb);
2646         return err;
2647 }
2648
2649 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2650                                         struct genl_info *info)
2651 {
2652         struct devlink *devlink = info->user_ptr[0];
2653
2654         if (list_empty(&devlink->resource_list))
2655                 return -EOPNOTSUPP;
2656
2657         return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2658 }
2659
2660 static int
2661 devlink_resources_validate(struct devlink *devlink,
2662                            struct devlink_resource *resource,
2663                            struct genl_info *info)
2664 {
2665         struct list_head *resource_list;
2666         int err = 0;
2667
2668         if (resource)
2669                 resource_list = &resource->resource_list;
2670         else
2671                 resource_list = &devlink->resource_list;
2672
2673         list_for_each_entry(resource, resource_list, list) {
2674                 if (!resource->size_valid)
2675                         return -EINVAL;
2676                 err = devlink_resources_validate(devlink, resource, info);
2677                 if (err)
2678                         return err;
2679         }
2680         return err;
2681 }
2682
2683 static bool devlink_reload_supported(struct devlink *devlink)
2684 {
2685         return devlink->ops->reload_down && devlink->ops->reload_up;
2686 }
2687
2688 static void devlink_reload_failed_set(struct devlink *devlink,
2689                                       bool reload_failed)
2690 {
2691         if (devlink->reload_failed == reload_failed)
2692                 return;
2693         devlink->reload_failed = reload_failed;
2694         devlink_notify(devlink, DEVLINK_CMD_NEW);
2695 }
2696
2697 bool devlink_is_reload_failed(const struct devlink *devlink)
2698 {
2699         return devlink->reload_failed;
2700 }
2701 EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
2702
2703 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2704 {
2705         struct devlink *devlink = info->user_ptr[0];
2706         int err;
2707
2708         if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
2709                 return -EOPNOTSUPP;
2710
2711         err = devlink_resources_validate(devlink, NULL, info);
2712         if (err) {
2713                 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2714                 return err;
2715         }
2716         err = devlink->ops->reload_down(devlink, info->extack);
2717         if (err)
2718                 return err;
2719         err = devlink->ops->reload_up(devlink, info->extack);
2720         devlink_reload_failed_set(devlink, !!err);
2721         return err;
2722 }
2723
2724 static int devlink_nl_flash_update_fill(struct sk_buff *msg,
2725                                         struct devlink *devlink,
2726                                         enum devlink_command cmd,
2727                                         const char *status_msg,
2728                                         const char *component,
2729                                         unsigned long done, unsigned long total)
2730 {
2731         void *hdr;
2732
2733         hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
2734         if (!hdr)
2735                 return -EMSGSIZE;
2736
2737         if (devlink_nl_put_handle(msg, devlink))
2738                 goto nla_put_failure;
2739
2740         if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
2741                 goto out;
2742
2743         if (status_msg &&
2744             nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
2745                            status_msg))
2746                 goto nla_put_failure;
2747         if (component &&
2748             nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
2749                            component))
2750                 goto nla_put_failure;
2751         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
2752                               done, DEVLINK_ATTR_PAD))
2753                 goto nla_put_failure;
2754         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
2755                               total, DEVLINK_ATTR_PAD))
2756                 goto nla_put_failure;
2757
2758 out:
2759         genlmsg_end(msg, hdr);
2760         return 0;
2761
2762 nla_put_failure:
2763         genlmsg_cancel(msg, hdr);
2764         return -EMSGSIZE;
2765 }
2766
2767 static void __devlink_flash_update_notify(struct devlink *devlink,
2768                                           enum devlink_command cmd,
2769                                           const char *status_msg,
2770                                           const char *component,
2771                                           unsigned long done,
2772                                           unsigned long total)
2773 {
2774         struct sk_buff *msg;
2775         int err;
2776
2777         WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
2778                 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
2779                 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
2780
2781         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2782         if (!msg)
2783                 return;
2784
2785         err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
2786                                            component, done, total);
2787         if (err)
2788                 goto out_free_msg;
2789
2790         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2791                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2792         return;
2793
2794 out_free_msg:
2795         nlmsg_free(msg);
2796 }
2797
2798 void devlink_flash_update_begin_notify(struct devlink *devlink)
2799 {
2800         __devlink_flash_update_notify(devlink,
2801                                       DEVLINK_CMD_FLASH_UPDATE,
2802                                       NULL, NULL, 0, 0);
2803 }
2804 EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);
2805
2806 void devlink_flash_update_end_notify(struct devlink *devlink)
2807 {
2808         __devlink_flash_update_notify(devlink,
2809                                       DEVLINK_CMD_FLASH_UPDATE_END,
2810                                       NULL, NULL, 0, 0);
2811 }
2812 EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);
2813
2814 void devlink_flash_update_status_notify(struct devlink *devlink,
2815                                         const char *status_msg,
2816                                         const char *component,
2817                                         unsigned long done,
2818                                         unsigned long total)
2819 {
2820         __devlink_flash_update_notify(devlink,
2821                                       DEVLINK_CMD_FLASH_UPDATE_STATUS,
2822                                       status_msg, component, done, total);
2823 }
2824 EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
2825
2826 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2827                                        struct genl_info *info)
2828 {
2829         struct devlink *devlink = info->user_ptr[0];
2830         const char *file_name, *component;
2831         struct nlattr *nla_component;
2832
2833         if (!devlink->ops->flash_update)
2834                 return -EOPNOTSUPP;
2835
2836         if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2837                 return -EINVAL;
2838         file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2839
2840         nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2841         component = nla_component ? nla_data(nla_component) : NULL;
2842
2843         return devlink->ops->flash_update(devlink, file_name, component,
2844                                           info->extack);
2845 }
2846
2847 static const struct devlink_param devlink_param_generic[] = {
2848         {
2849                 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2850                 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2851                 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2852         },
2853         {
2854                 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2855                 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2856                 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2857         },
2858         {
2859                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2860                 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2861                 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2862         },
2863         {
2864                 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2865                 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2866                 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2867         },
2868         {
2869                 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2870                 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2871                 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2872         },
2873         {
2874                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2875                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2876                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2877         },
2878         {
2879                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
2880                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
2881                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
2882         },
2883         {
2884                 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
2885                 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
2886                 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
2887         },
2888         {
2889                 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
2890                 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
2891                 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
2892         },
2893 };
2894
2895 static int devlink_param_generic_verify(const struct devlink_param *param)
2896 {
2897         /* verify it match generic parameter by id and name */
2898         if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2899                 return -EINVAL;
2900         if (strcmp(param->name, devlink_param_generic[param->id].name))
2901                 return -ENOENT;
2902
2903         WARN_ON(param->type != devlink_param_generic[param->id].type);
2904
2905         return 0;
2906 }
2907
2908 static int devlink_param_driver_verify(const struct devlink_param *param)
2909 {
2910         int i;
2911
2912         if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2913                 return -EINVAL;
2914         /* verify no such name in generic params */
2915         for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2916                 if (!strcmp(param->name, devlink_param_generic[i].name))
2917                         return -EEXIST;
2918
2919         return 0;
2920 }
2921
2922 static struct devlink_param_item *
2923 devlink_param_find_by_name(struct list_head *param_list,
2924                            const char *param_name)
2925 {
2926         struct devlink_param_item *param_item;
2927
2928         list_for_each_entry(param_item, param_list, list)
2929                 if (!strcmp(param_item->param->name, param_name))
2930                         return param_item;
2931         return NULL;
2932 }
2933
2934 static struct devlink_param_item *
2935 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2936 {
2937         struct devlink_param_item *param_item;
2938
2939         list_for_each_entry(param_item, param_list, list)
2940                 if (param_item->param->id == param_id)
2941                         return param_item;
2942         return NULL;
2943 }
2944
2945 static bool
2946 devlink_param_cmode_is_supported(const struct devlink_param *param,
2947                                  enum devlink_param_cmode cmode)
2948 {
2949         return test_bit(cmode, &param->supported_cmodes);
2950 }
2951
2952 static int devlink_param_get(struct devlink *devlink,
2953                              const struct devlink_param *param,
2954                              struct devlink_param_gset_ctx *ctx)
2955 {
2956         if (!param->get)
2957                 return -EOPNOTSUPP;
2958         return param->get(devlink, param->id, ctx);
2959 }
2960
2961 static int devlink_param_set(struct devlink *devlink,
2962                              const struct devlink_param *param,
2963                              struct devlink_param_gset_ctx *ctx)
2964 {
2965         if (!param->set)
2966                 return -EOPNOTSUPP;
2967         return param->set(devlink, param->id, ctx);
2968 }
2969
2970 static int
2971 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2972 {
2973         switch (param_type) {
2974         case DEVLINK_PARAM_TYPE_U8:
2975                 return NLA_U8;
2976         case DEVLINK_PARAM_TYPE_U16:
2977                 return NLA_U16;
2978         case DEVLINK_PARAM_TYPE_U32:
2979                 return NLA_U32;
2980         case DEVLINK_PARAM_TYPE_STRING:
2981                 return NLA_STRING;
2982         case DEVLINK_PARAM_TYPE_BOOL:
2983                 return NLA_FLAG;
2984         default:
2985                 return -EINVAL;
2986         }
2987 }
2988
2989 static int
2990 devlink_nl_param_value_fill_one(struct sk_buff *msg,
2991                                 enum devlink_param_type type,
2992                                 enum devlink_param_cmode cmode,
2993                                 union devlink_param_value val)
2994 {
2995         struct nlattr *param_value_attr;
2996
2997         param_value_attr = nla_nest_start_noflag(msg,
2998                                                  DEVLINK_ATTR_PARAM_VALUE);
2999         if (!param_value_attr)
3000                 goto nla_put_failure;
3001
3002         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
3003                 goto value_nest_cancel;
3004
3005         switch (type) {
3006         case DEVLINK_PARAM_TYPE_U8:
3007                 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
3008                         goto value_nest_cancel;
3009                 break;
3010         case DEVLINK_PARAM_TYPE_U16:
3011                 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
3012                         goto value_nest_cancel;
3013                 break;
3014         case DEVLINK_PARAM_TYPE_U32:
3015                 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
3016                         goto value_nest_cancel;
3017                 break;
3018         case DEVLINK_PARAM_TYPE_STRING:
3019                 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
3020                                    val.vstr))
3021                         goto value_nest_cancel;
3022                 break;
3023         case DEVLINK_PARAM_TYPE_BOOL:
3024                 if (val.vbool &&
3025                     nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
3026                         goto value_nest_cancel;
3027                 break;
3028         }
3029
3030         nla_nest_end(msg, param_value_attr);
3031         return 0;
3032
3033 value_nest_cancel:
3034         nla_nest_cancel(msg, param_value_attr);
3035 nla_put_failure:
3036         return -EMSGSIZE;
3037 }
3038
3039 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
3040                                  unsigned int port_index,
3041                                  struct devlink_param_item *param_item,
3042                                  enum devlink_command cmd,
3043                                  u32 portid, u32 seq, int flags)
3044 {
3045         union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
3046         bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
3047         const struct devlink_param *param = param_item->param;
3048         struct devlink_param_gset_ctx ctx;
3049         struct nlattr *param_values_list;
3050         struct nlattr *param_attr;
3051         int nla_type;
3052         void *hdr;
3053         int err;
3054         int i;
3055
3056         /* Get value from driver part to driverinit configuration mode */
3057         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3058                 if (!devlink_param_cmode_is_supported(param, i))
3059                         continue;
3060                 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3061                         if (!param_item->driverinit_value_valid)
3062                                 return -EOPNOTSUPP;
3063                         param_value[i] = param_item->driverinit_value;
3064                 } else {
3065                         if (!param_item->published)
3066                                 continue;
3067                         ctx.cmode = i;
3068                         err = devlink_param_get(devlink, param, &ctx);
3069                         if (err)
3070                                 return err;
3071                         param_value[i] = ctx.val;
3072                 }
3073                 param_value_set[i] = true;
3074         }
3075
3076         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3077         if (!hdr)
3078                 return -EMSGSIZE;
3079
3080         if (devlink_nl_put_handle(msg, devlink))
3081                 goto genlmsg_cancel;
3082
3083         if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3084             cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3085             cmd == DEVLINK_CMD_PORT_PARAM_DEL)
3086                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3087                         goto genlmsg_cancel;
3088
3089         param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
3090         if (!param_attr)
3091                 goto genlmsg_cancel;
3092         if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3093                 goto param_nest_cancel;
3094         if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3095                 goto param_nest_cancel;
3096
3097         nla_type = devlink_param_type_to_nla_type(param->type);
3098         if (nla_type < 0)
3099                 goto param_nest_cancel;
3100         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3101                 goto param_nest_cancel;
3102
3103         param_values_list = nla_nest_start_noflag(msg,
3104                                                   DEVLINK_ATTR_PARAM_VALUES_LIST);
3105         if (!param_values_list)
3106                 goto param_nest_cancel;
3107
3108         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3109                 if (!param_value_set[i])
3110                         continue;
3111                 err = devlink_nl_param_value_fill_one(msg, param->type,
3112                                                       i, param_value[i]);
3113                 if (err)
3114                         goto values_list_nest_cancel;
3115         }
3116
3117         nla_nest_end(msg, param_values_list);
3118         nla_nest_end(msg, param_attr);
3119         genlmsg_end(msg, hdr);
3120         return 0;
3121
3122 values_list_nest_cancel:
3123         nla_nest_end(msg, param_values_list);
3124 param_nest_cancel:
3125         nla_nest_cancel(msg, param_attr);
3126 genlmsg_cancel:
3127         genlmsg_cancel(msg, hdr);
3128         return -EMSGSIZE;
3129 }
3130
3131 static void devlink_param_notify(struct devlink *devlink,
3132                                  unsigned int port_index,
3133                                  struct devlink_param_item *param_item,
3134                                  enum devlink_command cmd)
3135 {
3136         struct sk_buff *msg;
3137         int err;
3138
3139         WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3140                 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3141                 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
3142
3143         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3144         if (!msg)
3145                 return;
3146         err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3147                                     0, 0, 0);
3148         if (err) {
3149                 nlmsg_free(msg);
3150                 return;
3151         }
3152
3153         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3154                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3155 }
3156
3157 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3158                                            struct netlink_callback *cb)
3159 {
3160         struct devlink_param_item *param_item;
3161         struct devlink *devlink;
3162         int start = cb->args[0];
3163         int idx = 0;
3164         int err;
3165
3166         mutex_lock(&devlink_mutex);
3167         list_for_each_entry(devlink, &devlink_list, list) {
3168                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3169                         continue;
3170                 mutex_lock(&devlink->lock);
3171                 list_for_each_entry(param_item, &devlink->param_list, list) {
3172                         if (idx < start) {
3173                                 idx++;
3174                                 continue;
3175                         }
3176                         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3177                                                     DEVLINK_CMD_PARAM_GET,
3178                                                     NETLINK_CB(cb->skb).portid,
3179                                                     cb->nlh->nlmsg_seq,
3180                                                     NLM_F_MULTI);
3181                         if (err && err != -EOPNOTSUPP) {
3182                                 mutex_unlock(&devlink->lock);
3183                                 goto out;
3184                         }
3185                         idx++;
3186                 }
3187                 mutex_unlock(&devlink->lock);
3188         }
3189 out:
3190         mutex_unlock(&devlink_mutex);
3191
3192         cb->args[0] = idx;
3193         return msg->len;
3194 }
3195
3196 static int
3197 devlink_param_type_get_from_info(struct genl_info *info,
3198                                  enum devlink_param_type *param_type)
3199 {
3200         if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3201                 return -EINVAL;
3202
3203         switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3204         case NLA_U8:
3205                 *param_type = DEVLINK_PARAM_TYPE_U8;
3206                 break;
3207         case NLA_U16:
3208                 *param_type = DEVLINK_PARAM_TYPE_U16;
3209                 break;
3210         case NLA_U32:
3211                 *param_type = DEVLINK_PARAM_TYPE_U32;
3212                 break;
3213         case NLA_STRING:
3214                 *param_type = DEVLINK_PARAM_TYPE_STRING;
3215                 break;
3216         case NLA_FLAG:
3217                 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3218                 break;
3219         default:
3220                 return -EINVAL;
3221         }
3222
3223         return 0;
3224 }
3225
3226 static int
3227 devlink_param_value_get_from_info(const struct devlink_param *param,
3228                                   struct genl_info *info,
3229                                   union devlink_param_value *value)
3230 {
3231         struct nlattr *param_data;
3232         int len;
3233
3234         param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
3235
3236         if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
3237                 return -EINVAL;
3238
3239         switch (param->type) {
3240         case DEVLINK_PARAM_TYPE_U8:
3241                 if (nla_len(param_data) != sizeof(u8))
3242                         return -EINVAL;
3243                 value->vu8 = nla_get_u8(param_data);
3244                 break;
3245         case DEVLINK_PARAM_TYPE_U16:
3246                 if (nla_len(param_data) != sizeof(u16))
3247                         return -EINVAL;
3248                 value->vu16 = nla_get_u16(param_data);
3249                 break;
3250         case DEVLINK_PARAM_TYPE_U32:
3251                 if (nla_len(param_data) != sizeof(u32))
3252                         return -EINVAL;
3253                 value->vu32 = nla_get_u32(param_data);
3254                 break;
3255         case DEVLINK_PARAM_TYPE_STRING:
3256                 len = strnlen(nla_data(param_data), nla_len(param_data));
3257                 if (len == nla_len(param_data) ||
3258                     len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3259                         return -EINVAL;
3260                 strcpy(value->vstr, nla_data(param_data));
3261                 break;
3262         case DEVLINK_PARAM_TYPE_BOOL:
3263                 if (param_data && nla_len(param_data))
3264                         return -EINVAL;
3265                 value->vbool = nla_get_flag(param_data);
3266                 break;
3267         }
3268         return 0;
3269 }
3270
3271 static struct devlink_param_item *
3272 devlink_param_get_from_info(struct list_head *param_list,
3273                             struct genl_info *info)
3274 {
3275         char *param_name;
3276
3277         if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3278                 return NULL;
3279
3280         param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3281         return devlink_param_find_by_name(param_list, param_name);
3282 }
3283
3284 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3285                                          struct genl_info *info)
3286 {
3287         struct devlink *devlink = info->user_ptr[0];
3288         struct devlink_param_item *param_item;
3289         struct sk_buff *msg;
3290         int err;
3291
3292         param_item = devlink_param_get_from_info(&devlink->param_list, info);
3293         if (!param_item)
3294                 return -EINVAL;
3295
3296         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3297         if (!msg)
3298                 return -ENOMEM;
3299
3300         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3301                                     DEVLINK_CMD_PARAM_GET,
3302                                     info->snd_portid, info->snd_seq, 0);
3303         if (err) {
3304                 nlmsg_free(msg);
3305                 return err;
3306         }
3307
3308         return genlmsg_reply(msg, info);
3309 }
3310
3311 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3312                                            unsigned int port_index,
3313                                            struct list_head *param_list,
3314                                            struct genl_info *info,
3315                                            enum devlink_command cmd)
3316 {
3317         enum devlink_param_type param_type;
3318         struct devlink_param_gset_ctx ctx;
3319         enum devlink_param_cmode cmode;
3320         struct devlink_param_item *param_item;
3321         const struct devlink_param *param;
3322         union devlink_param_value value;
3323         int err = 0;
3324
3325         param_item = devlink_param_get_from_info(param_list, info);
3326         if (!param_item)
3327                 return -EINVAL;
3328         param = param_item->param;
3329         err = devlink_param_type_get_from_info(info, &param_type);
3330         if (err)
3331                 return err;
3332         if (param_type != param->type)
3333                 return -EINVAL;
3334         err = devlink_param_value_get_from_info(param, info, &value);
3335         if (err)
3336                 return err;
3337         if (param->validate) {
3338                 err = param->validate(devlink, param->id, value, info->extack);
3339                 if (err)
3340                         return err;
3341         }
3342
3343         if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3344                 return -EINVAL;
3345         cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3346         if (!devlink_param_cmode_is_supported(param, cmode))
3347                 return -EOPNOTSUPP;
3348
3349         if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3350                 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3351                         strcpy(param_item->driverinit_value.vstr, value.vstr);
3352                 else
3353                         param_item->driverinit_value = value;
3354                 param_item->driverinit_value_valid = true;
3355         } else {
3356                 if (!param->set)
3357                         return -EOPNOTSUPP;
3358                 ctx.val = value;
3359                 ctx.cmode = cmode;
3360                 err = devlink_param_set(devlink, param, &ctx);
3361                 if (err)
3362                         return err;
3363         }
3364
3365         devlink_param_notify(devlink, port_index, param_item, cmd);
3366         return 0;
3367 }
3368
3369 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3370                                          struct genl_info *info)
3371 {
3372         struct devlink *devlink = info->user_ptr[0];
3373
3374         return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3375                                                info, DEVLINK_CMD_PARAM_NEW);
3376 }
3377
3378 static int devlink_param_register_one(struct devlink *devlink,
3379                                       unsigned int port_index,
3380                                       struct list_head *param_list,
3381                                       const struct devlink_param *param,
3382                                       enum devlink_command cmd)
3383 {
3384         struct devlink_param_item *param_item;
3385
3386         if (devlink_param_find_by_name(param_list, param->name))
3387                 return -EEXIST;
3388
3389         if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3390                 WARN_ON(param->get || param->set);
3391         else
3392                 WARN_ON(!param->get || !param->set);
3393
3394         param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3395         if (!param_item)
3396                 return -ENOMEM;
3397         param_item->param = param;
3398
3399         list_add_tail(&param_item->list, param_list);
3400         devlink_param_notify(devlink, port_index, param_item, cmd);
3401         return 0;
3402 }
3403
3404 static void devlink_param_unregister_one(struct devlink *devlink,
3405                                          unsigned int port_index,
3406                                          struct list_head *param_list,
3407                                          const struct devlink_param *param,
3408                                          enum devlink_command cmd)
3409 {
3410         struct devlink_param_item *param_item;
3411
3412         param_item = devlink_param_find_by_name(param_list, param->name);
3413         WARN_ON(!param_item);
3414         devlink_param_notify(devlink, port_index, param_item, cmd);
3415         list_del(&param_item->list);
3416         kfree(param_item);
3417 }
3418
3419 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3420                                                 struct netlink_callback *cb)
3421 {
3422         struct devlink_param_item *param_item;
3423         struct devlink_port *devlink_port;
3424         struct devlink *devlink;
3425         int start = cb->args[0];
3426         int idx = 0;
3427         int err;
3428
3429         mutex_lock(&devlink_mutex);
3430         list_for_each_entry(devlink, &devlink_list, list) {
3431                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3432                         continue;
3433                 mutex_lock(&devlink->lock);
3434                 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3435                         list_for_each_entry(param_item,
3436                                             &devlink_port->param_list, list) {
3437                                 if (idx < start) {
3438                                         idx++;
3439                                         continue;
3440                                 }
3441                                 err = devlink_nl_param_fill(msg,
3442                                                 devlink_port->devlink,
3443                                                 devlink_port->index, param_item,
3444                                                 DEVLINK_CMD_PORT_PARAM_GET,
3445                                                 NETLINK_CB(cb->skb).portid,
3446                                                 cb->nlh->nlmsg_seq,
3447                                                 NLM_F_MULTI);
3448                                 if (err && err != -EOPNOTSUPP) {
3449                                         mutex_unlock(&devlink->lock);
3450                                         goto out;
3451                                 }
3452                                 idx++;
3453                         }
3454                 }
3455                 mutex_unlock(&devlink->lock);
3456         }
3457 out:
3458         mutex_unlock(&devlink_mutex);
3459
3460         cb->args[0] = idx;
3461         return msg->len;
3462 }
3463
3464 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3465                                               struct genl_info *info)
3466 {
3467         struct devlink_port *devlink_port = info->user_ptr[0];
3468         struct devlink_param_item *param_item;
3469         struct sk_buff *msg;
3470         int err;
3471
3472         param_item = devlink_param_get_from_info(&devlink_port->param_list,
3473                                                  info);
3474         if (!param_item)
3475                 return -EINVAL;
3476
3477         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3478         if (!msg)
3479                 return -ENOMEM;
3480
3481         err = devlink_nl_param_fill(msg, devlink_port->devlink,
3482                                     devlink_port->index, param_item,
3483                                     DEVLINK_CMD_PORT_PARAM_GET,
3484                                     info->snd_portid, info->snd_seq, 0);
3485         if (err) {
3486                 nlmsg_free(msg);
3487                 return err;
3488         }
3489
3490         return genlmsg_reply(msg, info);
3491 }
3492
3493 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3494                                               struct genl_info *info)
3495 {
3496         struct devlink_port *devlink_port = info->user_ptr[0];
3497
3498         return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3499                                                devlink_port->index,
3500                                                &devlink_port->param_list, info,
3501                                                DEVLINK_CMD_PORT_PARAM_NEW);
3502 }
3503
3504 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3505                                              struct devlink *devlink,
3506                                              struct devlink_snapshot *snapshot)
3507 {
3508         struct nlattr *snap_attr;
3509         int err;
3510
3511         snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3512         if (!snap_attr)
3513                 return -EINVAL;
3514
3515         err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3516         if (err)
3517                 goto nla_put_failure;
3518
3519         nla_nest_end(msg, snap_attr);
3520         return 0;
3521
3522 nla_put_failure:
3523         nla_nest_cancel(msg, snap_attr);
3524         return err;
3525 }
3526
3527 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3528                                               struct devlink *devlink,
3529                                               struct devlink_region *region)
3530 {
3531         struct devlink_snapshot *snapshot;
3532         struct nlattr *snapshots_attr;
3533         int err;
3534
3535         snapshots_attr = nla_nest_start_noflag(msg,
3536                                                DEVLINK_ATTR_REGION_SNAPSHOTS);
3537         if (!snapshots_attr)
3538                 return -EINVAL;
3539
3540         list_for_each_entry(snapshot, &region->snapshot_list, list) {
3541                 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3542                 if (err)
3543                         goto nla_put_failure;
3544         }
3545
3546         nla_nest_end(msg, snapshots_attr);
3547         return 0;
3548
3549 nla_put_failure:
3550         nla_nest_cancel(msg, snapshots_attr);
3551         return err;
3552 }
3553
3554 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3555                                   enum devlink_command cmd, u32 portid,
3556                                   u32 seq, int flags,
3557                                   struct devlink_region *region)
3558 {
3559         void *hdr;
3560         int err;
3561
3562         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3563         if (!hdr)
3564                 return -EMSGSIZE;
3565
3566         err = devlink_nl_put_handle(msg, devlink);
3567         if (err)
3568                 goto nla_put_failure;
3569
3570         err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3571         if (err)
3572                 goto nla_put_failure;
3573
3574         err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3575                                 region->size,
3576                                 DEVLINK_ATTR_PAD);
3577         if (err)
3578                 goto nla_put_failure;
3579
3580         err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3581         if (err)
3582                 goto nla_put_failure;
3583
3584         genlmsg_end(msg, hdr);
3585         return 0;
3586
3587 nla_put_failure:
3588         genlmsg_cancel(msg, hdr);
3589         return err;
3590 }
3591
3592 static void devlink_nl_region_notify(struct devlink_region *region,
3593                                      struct devlink_snapshot *snapshot,
3594                                      enum devlink_command cmd)
3595 {
3596         struct devlink *devlink = region->devlink;
3597         struct sk_buff *msg;
3598         void *hdr;
3599         int err;
3600
3601         WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3602
3603         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3604         if (!msg)
3605                 return;
3606
3607         hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3608         if (!hdr)
3609                 goto out_free_msg;
3610
3611         err = devlink_nl_put_handle(msg, devlink);
3612         if (err)
3613                 goto out_cancel_msg;
3614
3615         err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3616                              region->name);
3617         if (err)
3618                 goto out_cancel_msg;
3619
3620         if (snapshot) {
3621                 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3622                                   snapshot->id);
3623                 if (err)
3624                         goto out_cancel_msg;
3625         } else {
3626                 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3627                                         region->size, DEVLINK_ATTR_PAD);
3628                 if (err)
3629                         goto out_cancel_msg;
3630         }
3631         genlmsg_end(msg, hdr);
3632
3633         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3634                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3635
3636         return;
3637
3638 out_cancel_msg:
3639         genlmsg_cancel(msg, hdr);
3640 out_free_msg:
3641         nlmsg_free(msg);
3642 }
3643
3644 static void devlink_region_snapshot_del(struct devlink_region *region,
3645                                         struct devlink_snapshot *snapshot)
3646 {
3647         devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3648         region->cur_snapshots--;
3649         list_del(&snapshot->list);
3650         (*snapshot->data_destructor)(snapshot->data);
3651         kfree(snapshot);
3652 }
3653
3654 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3655                                           struct genl_info *info)
3656 {
3657         struct devlink *devlink = info->user_ptr[0];
3658         struct devlink_region *region;
3659         const char *region_name;
3660         struct sk_buff *msg;
3661         int err;
3662
3663         if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3664                 return -EINVAL;
3665
3666         region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3667         region = devlink_region_get_by_name(devlink, region_name);
3668         if (!region)
3669                 return -EINVAL;
3670
3671         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3672         if (!msg)
3673                 return -ENOMEM;
3674
3675         err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3676                                      info->snd_portid, info->snd_seq, 0,
3677                                      region);
3678         if (err) {
3679                 nlmsg_free(msg);
3680                 return err;
3681         }
3682
3683         return genlmsg_reply(msg, info);
3684 }
3685
3686 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3687                                             struct netlink_callback *cb)
3688 {
3689         struct devlink_region *region;
3690         struct devlink *devlink;
3691         int start = cb->args[0];
3692         int idx = 0;
3693         int err;
3694
3695         mutex_lock(&devlink_mutex);
3696         list_for_each_entry(devlink, &devlink_list, list) {
3697                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3698                         continue;
3699
3700                 mutex_lock(&devlink->lock);
3701                 list_for_each_entry(region, &devlink->region_list, list) {
3702                         if (idx < start) {
3703                                 idx++;
3704                                 continue;
3705                         }
3706                         err = devlink_nl_region_fill(msg, devlink,
3707                                                      DEVLINK_CMD_REGION_GET,
3708                                                      NETLINK_CB(cb->skb).portid,
3709                                                      cb->nlh->nlmsg_seq,
3710                                                      NLM_F_MULTI, region);
3711                         if (err) {
3712                                 mutex_unlock(&devlink->lock);
3713                                 goto out;
3714                         }
3715                         idx++;
3716                 }
3717                 mutex_unlock(&devlink->lock);
3718         }
3719 out:
3720         mutex_unlock(&devlink_mutex);
3721         cb->args[0] = idx;
3722         return msg->len;
3723 }
3724
3725 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3726                                      struct genl_info *info)
3727 {
3728         struct devlink *devlink = info->user_ptr[0];
3729         struct devlink_snapshot *snapshot;
3730         struct devlink_region *region;
3731         const char *region_name;
3732         u32 snapshot_id;
3733
3734         if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3735             !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3736                 return -EINVAL;
3737
3738         region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3739         snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3740
3741         region = devlink_region_get_by_name(devlink, region_name);
3742         if (!region)
3743                 return -EINVAL;
3744
3745         snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3746         if (!snapshot)
3747                 return -EINVAL;
3748
3749         devlink_region_snapshot_del(region, snapshot);
3750         return 0;
3751 }
3752
3753 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3754                                                  struct devlink *devlink,
3755                                                  u8 *chunk, u32 chunk_size,
3756                                                  u64 addr)
3757 {
3758         struct nlattr *chunk_attr;
3759         int err;
3760
3761         chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
3762         if (!chunk_attr)
3763                 return -EINVAL;
3764
3765         err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3766         if (err)
3767                 goto nla_put_failure;
3768
3769         err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3770                                 DEVLINK_ATTR_PAD);
3771         if (err)
3772                 goto nla_put_failure;
3773
3774         nla_nest_end(msg, chunk_attr);
3775         return 0;
3776
3777 nla_put_failure:
3778         nla_nest_cancel(msg, chunk_attr);
3779         return err;
3780 }
3781
3782 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
3783
3784 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3785                                                 struct devlink *devlink,
3786                                                 struct devlink_region *region,
3787                                                 struct nlattr **attrs,
3788                                                 u64 start_offset,
3789                                                 u64 end_offset,
3790                                                 bool dump,
3791                                                 u64 *new_offset)
3792 {
3793         struct devlink_snapshot *snapshot;
3794         u64 curr_offset = start_offset;
3795         u32 snapshot_id;
3796         int err = 0;
3797
3798         *new_offset = start_offset;
3799
3800         snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3801         snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3802         if (!snapshot)
3803                 return -EINVAL;
3804
3805         if (end_offset > region->size || dump)
3806                 end_offset = region->size;
3807
3808         while (curr_offset < end_offset) {
3809                 u32 data_size;
3810                 u8 *data;
3811
3812                 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3813                         data_size = end_offset - curr_offset;
3814                 else
3815                         data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3816
3817                 data = &snapshot->data[curr_offset];
3818                 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3819                                                             data, data_size,
3820                                                             curr_offset);
3821                 if (err)
3822                         break;
3823
3824                 curr_offset += data_size;
3825         }
3826         *new_offset = curr_offset;
3827
3828         return err;
3829 }
3830
3831 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3832                                              struct netlink_callback *cb)
3833 {
3834         u64 ret_offset, start_offset, end_offset = 0;
3835         struct devlink_region *region;
3836         struct nlattr *chunks_attr;
3837         const char *region_name;
3838         struct devlink *devlink;
3839         struct nlattr **attrs;
3840         bool dump = true;
3841         void *hdr;
3842         int err;
3843
3844         start_offset = *((u64 *)&cb->args[0]);
3845
3846         attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
3847         if (!attrs)
3848                 return -ENOMEM;
3849
3850         err = nlmsg_parse_deprecated(cb->nlh,
3851                                      GENL_HDRLEN + devlink_nl_family.hdrsize,
3852                                      attrs, DEVLINK_ATTR_MAX,
3853                                      devlink_nl_family.policy, cb->extack);
3854         if (err)
3855                 goto out_free;
3856
3857         mutex_lock(&devlink_mutex);
3858         devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3859         if (IS_ERR(devlink)) {
3860                 err = PTR_ERR(devlink);
3861                 goto out_dev;
3862         }
3863
3864         mutex_lock(&devlink->lock);
3865
3866         if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3867             !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
3868                 err = -EINVAL;
3869                 goto out_unlock;
3870         }
3871
3872         region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3873         region = devlink_region_get_by_name(devlink, region_name);
3874         if (!region) {
3875                 err = -EINVAL;
3876                 goto out_unlock;
3877         }
3878
3879         /* return 0 if there is no further data to read */
3880         if (start_offset >= region->size) {
3881                 err = 0;
3882                 goto out_unlock;
3883         }
3884
3885         hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3886                           &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3887                           DEVLINK_CMD_REGION_READ);
3888         if (!hdr) {
3889                 err = -EMSGSIZE;
3890                 goto out_unlock;
3891         }
3892
3893         err = devlink_nl_put_handle(skb, devlink);
3894         if (err)
3895                 goto nla_put_failure;
3896
3897         err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3898         if (err)
3899                 goto nla_put_failure;
3900
3901         chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
3902         if (!chunks_attr) {
3903                 err = -EMSGSIZE;
3904                 goto nla_put_failure;
3905         }
3906
3907         if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3908             attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3909                 if (!start_offset)
3910                         start_offset =
3911                                 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3912
3913                 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3914                 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3915                 dump = false;
3916
3917                 if (start_offset == end_offset) {
3918                         err = 0;
3919                         goto nla_put_failure;
3920                 }
3921         }
3922
3923         err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3924                                                    region, attrs,
3925                                                    start_offset,
3926                                                    end_offset, dump,
3927                                                    &ret_offset);
3928
3929         if (err && err != -EMSGSIZE)
3930                 goto nla_put_failure;
3931
3932         /* Check if there was any progress done to prevent infinite loop */
3933         if (ret_offset == start_offset) {
3934                 err = -EINVAL;
3935                 goto nla_put_failure;
3936         }
3937
3938         *((u64 *)&cb->args[0]) = ret_offset;
3939
3940         nla_nest_end(skb, chunks_attr);
3941         genlmsg_end(skb, hdr);
3942         mutex_unlock(&devlink->lock);
3943         mutex_unlock(&devlink_mutex);
3944         kfree(attrs);
3945
3946         return skb->len;
3947
3948 nla_put_failure:
3949         genlmsg_cancel(skb, hdr);
3950 out_unlock:
3951         mutex_unlock(&devlink->lock);
3952 out_dev:
3953         mutex_unlock(&devlink_mutex);
3954 out_free:
3955         kfree(attrs);
3956         return err;
3957 }
3958
3959 struct devlink_info_req {
3960         struct sk_buff *msg;
3961 };
3962
3963 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3964 {
3965         return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3966 }
3967 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3968
3969 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3970 {
3971         return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3972 }
3973 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3974
3975 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
3976                                     const char *version_name,
3977                                     const char *version_value)
3978 {
3979         struct nlattr *nest;
3980         int err;
3981
3982         nest = nla_nest_start_noflag(req->msg, attr);
3983         if (!nest)
3984                 return -EMSGSIZE;
3985
3986         err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
3987                              version_name);
3988         if (err)
3989                 goto nla_put_failure;
3990
3991         err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
3992                              version_value);
3993         if (err)
3994                 goto nla_put_failure;
3995
3996         nla_nest_end(req->msg, nest);
3997
3998         return 0;
3999
4000 nla_put_failure:
4001         nla_nest_cancel(req->msg, nest);
4002         return err;
4003 }
4004
4005 int devlink_info_version_fixed_put(struct devlink_info_req *req,
4006                                    const char *version_name,
4007                                    const char *version_value)
4008 {
4009         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
4010                                         version_name, version_value);
4011 }
4012 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
4013
4014 int devlink_info_version_stored_put(struct devlink_info_req *req,
4015                                     const char *version_name,
4016                                     const char *version_value)
4017 {
4018         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
4019                                         version_name, version_value);
4020 }
4021 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
4022
4023 int devlink_info_version_running_put(struct devlink_info_req *req,
4024                                      const char *version_name,
4025                                      const char *version_value)
4026 {
4027         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
4028                                         version_name, version_value);
4029 }
4030 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
4031
4032 static int
4033 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
4034                      enum devlink_command cmd, u32 portid,
4035                      u32 seq, int flags, struct netlink_ext_ack *extack)
4036 {
4037         struct devlink_info_req req;
4038         void *hdr;
4039         int err;
4040
4041         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4042         if (!hdr)
4043                 return -EMSGSIZE;
4044
4045         err = -EMSGSIZE;
4046         if (devlink_nl_put_handle(msg, devlink))
4047                 goto err_cancel_msg;
4048
4049         req.msg = msg;
4050         err = devlink->ops->info_get(devlink, &req, extack);
4051         if (err)
4052                 goto err_cancel_msg;
4053
4054         genlmsg_end(msg, hdr);
4055         return 0;
4056
4057 err_cancel_msg:
4058         genlmsg_cancel(msg, hdr);
4059         return err;
4060 }
4061
4062 static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
4063                                         struct genl_info *info)
4064 {
4065         struct devlink *devlink = info->user_ptr[0];
4066         struct sk_buff *msg;
4067         int err;
4068
4069         if (!devlink->ops->info_get)
4070                 return -EOPNOTSUPP;
4071
4072         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4073         if (!msg)
4074                 return -ENOMEM;
4075
4076         err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4077                                    info->snd_portid, info->snd_seq, 0,
4078                                    info->extack);
4079         if (err) {
4080                 nlmsg_free(msg);
4081                 return err;
4082         }
4083
4084         return genlmsg_reply(msg, info);
4085 }
4086
4087 static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
4088                                           struct netlink_callback *cb)
4089 {
4090         struct devlink *devlink;
4091         int start = cb->args[0];
4092         int idx = 0;
4093         int err;
4094
4095         mutex_lock(&devlink_mutex);
4096         list_for_each_entry(devlink, &devlink_list, list) {
4097                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4098                         continue;
4099                 if (idx < start) {
4100                         idx++;
4101                         continue;
4102                 }
4103
4104                 if (!devlink->ops->info_get) {
4105                         idx++;
4106                         continue;
4107                 }
4108
4109                 mutex_lock(&devlink->lock);
4110                 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4111                                            NETLINK_CB(cb->skb).portid,
4112                                            cb->nlh->nlmsg_seq, NLM_F_MULTI,
4113                                            cb->extack);
4114                 mutex_unlock(&devlink->lock);
4115                 if (err && err != -EOPNOTSUPP)
4116                         break;
4117                 idx++;
4118         }
4119         mutex_unlock(&devlink_mutex);
4120
4121         cb->args[0] = idx;
4122         return msg->len;
4123 }
4124
4125 struct devlink_fmsg_item {
4126         struct list_head list;
4127         int attrtype;
4128         u8 nla_type;
4129         u16 len;
4130         int value[0];
4131 };
4132
4133 struct devlink_fmsg {
4134         struct list_head item_list;
4135 };
4136
4137 static struct devlink_fmsg *devlink_fmsg_alloc(void)
4138 {
4139         struct devlink_fmsg *fmsg;
4140
4141         fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
4142         if (!fmsg)
4143                 return NULL;
4144
4145         INIT_LIST_HEAD(&fmsg->item_list);
4146
4147         return fmsg;
4148 }
4149
4150 static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
4151 {
4152         struct devlink_fmsg_item *item, *tmp;
4153
4154         list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
4155                 list_del(&item->list);
4156                 kfree(item);
4157         }
4158         kfree(fmsg);
4159 }
4160
4161 static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
4162                                     int attrtype)
4163 {
4164         struct devlink_fmsg_item *item;
4165
4166         item = kzalloc(sizeof(*item), GFP_KERNEL);
4167         if (!item)
4168                 return -ENOMEM;
4169
4170         item->attrtype = attrtype;
4171         list_add_tail(&item->list, &fmsg->item_list);
4172
4173         return 0;
4174 }
4175
4176 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
4177 {
4178         return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
4179 }
4180 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
4181
4182 static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4183 {
4184         return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4185 }
4186
4187 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4188 {
4189         return devlink_fmsg_nest_end(fmsg);
4190 }
4191 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4192
4193 #define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4194
4195 static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4196 {
4197         struct devlink_fmsg_item *item;
4198
4199         if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4200                 return -EMSGSIZE;
4201
4202         item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4203         if (!item)
4204                 return -ENOMEM;
4205
4206         item->nla_type = NLA_NUL_STRING;
4207         item->len = strlen(name) + 1;
4208         item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4209         memcpy(&item->value, name, item->len);
4210         list_add_tail(&item->list, &fmsg->item_list);
4211
4212         return 0;
4213 }
4214
4215 int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4216 {
4217         int err;
4218
4219         err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4220         if (err)
4221                 return err;
4222
4223         err = devlink_fmsg_put_name(fmsg, name);
4224         if (err)
4225                 return err;
4226
4227         return 0;
4228 }
4229 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4230
4231 int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4232 {
4233         return devlink_fmsg_nest_end(fmsg);
4234 }
4235 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4236
4237 int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4238                                      const char *name)
4239 {
4240         int err;
4241
4242         err = devlink_fmsg_pair_nest_start(fmsg, name);
4243         if (err)
4244                 return err;
4245
4246         err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4247         if (err)
4248                 return err;
4249
4250         return 0;
4251 }
4252 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4253
4254 int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4255 {
4256         int err;
4257
4258         err = devlink_fmsg_nest_end(fmsg);
4259         if (err)
4260                 return err;
4261
4262         err = devlink_fmsg_nest_end(fmsg);
4263         if (err)
4264                 return err;
4265
4266         return 0;
4267 }
4268 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4269
4270 static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4271                                   const void *value, u16 value_len,
4272                                   u8 value_nla_type)
4273 {
4274         struct devlink_fmsg_item *item;
4275
4276         if (value_len > DEVLINK_FMSG_MAX_SIZE)
4277                 return -EMSGSIZE;
4278
4279         item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4280         if (!item)
4281                 return -ENOMEM;
4282
4283         item->nla_type = value_nla_type;
4284         item->len = value_len;
4285         item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4286         memcpy(&item->value, value, item->len);
4287         list_add_tail(&item->list, &fmsg->item_list);
4288
4289         return 0;
4290 }
4291
4292 int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4293 {
4294         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4295 }
4296 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4297
4298 int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4299 {
4300         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4301 }
4302 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4303
4304 int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4305 {
4306         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4307 }
4308 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4309
4310 int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4311 {
4312         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4313 }
4314 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4315
4316 int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4317 {
4318         return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4319                                       NLA_NUL_STRING);
4320 }
4321 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4322
4323 int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4324                             u16 value_len)
4325 {
4326         return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4327 }
4328 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4329
4330 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4331                                bool value)
4332 {
4333         int err;
4334
4335         err = devlink_fmsg_pair_nest_start(fmsg, name);
4336         if (err)
4337                 return err;
4338
4339         err = devlink_fmsg_bool_put(fmsg, value);
4340         if (err)
4341                 return err;
4342
4343         err = devlink_fmsg_pair_nest_end(fmsg);
4344         if (err)
4345                 return err;
4346
4347         return 0;
4348 }
4349 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4350
4351 int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4352                              u8 value)
4353 {
4354         int err;
4355
4356         err = devlink_fmsg_pair_nest_start(fmsg, name);
4357         if (err)
4358                 return err;
4359
4360         err = devlink_fmsg_u8_put(fmsg, value);
4361         if (err)
4362                 return err;
4363
4364         err = devlink_fmsg_pair_nest_end(fmsg);
4365         if (err)
4366                 return err;
4367
4368         return 0;
4369 }
4370 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4371
4372 int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4373                               u32 value)
4374 {
4375         int err;
4376
4377         err = devlink_fmsg_pair_nest_start(fmsg, name);
4378         if (err)
4379                 return err;
4380
4381         err = devlink_fmsg_u32_put(fmsg, value);
4382         if (err)
4383                 return err;
4384
4385         err = devlink_fmsg_pair_nest_end(fmsg);
4386         if (err)
4387                 return err;
4388
4389         return 0;
4390 }
4391 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4392
4393 int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4394                               u64 value)
4395 {
4396         int err;
4397
4398         err = devlink_fmsg_pair_nest_start(fmsg, name);
4399         if (err)
4400                 return err;
4401
4402         err = devlink_fmsg_u64_put(fmsg, value);
4403         if (err)
4404                 return err;
4405
4406         err = devlink_fmsg_pair_nest_end(fmsg);
4407         if (err)
4408                 return err;
4409
4410         return 0;
4411 }
4412 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4413
4414 int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4415                                  const char *value)
4416 {
4417         int err;
4418
4419         err = devlink_fmsg_pair_nest_start(fmsg, name);
4420         if (err)
4421                 return err;
4422
4423         err = devlink_fmsg_string_put(fmsg, value);
4424         if (err)
4425                 return err;
4426
4427         err = devlink_fmsg_pair_nest_end(fmsg);
4428         if (err)
4429                 return err;
4430
4431         return 0;
4432 }
4433 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4434
4435 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4436                                  const void *value, u16 value_len)
4437 {
4438         int err;
4439
4440         err = devlink_fmsg_pair_nest_start(fmsg, name);
4441         if (err)
4442                 return err;
4443
4444         err = devlink_fmsg_binary_put(fmsg, value, value_len);
4445         if (err)
4446                 return err;
4447
4448         err = devlink_fmsg_pair_nest_end(fmsg);
4449         if (err)
4450                 return err;
4451
4452         return 0;
4453 }
4454 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4455
4456 static int
4457 devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4458 {
4459         switch (msg->nla_type) {
4460         case NLA_FLAG:
4461         case NLA_U8:
4462         case NLA_U32:
4463         case NLA_U64:
4464         case NLA_NUL_STRING:
4465         case NLA_BINARY:
4466                 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4467                                   msg->nla_type);
4468         default:
4469                 return -EINVAL;
4470         }
4471 }
4472
4473 static int
4474 devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4475 {
4476         int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4477         u8 tmp;
4478
4479         switch (msg->nla_type) {
4480         case NLA_FLAG:
4481                 /* Always provide flag data, regardless of its value */
4482                 tmp = *(bool *) msg->value;
4483
4484                 return nla_put_u8(skb, attrtype, tmp);
4485         case NLA_U8:
4486                 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4487         case NLA_U32:
4488                 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4489         case NLA_U64:
4490                 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4491                                          DEVLINK_ATTR_PAD);
4492         case NLA_NUL_STRING:
4493                 return nla_put_string(skb, attrtype, (char *) &msg->value);
4494         case NLA_BINARY:
4495                 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
4496         default:
4497                 return -EINVAL;
4498         }
4499 }
4500
4501 static int
4502 devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4503                          int *start)
4504 {
4505         struct devlink_fmsg_item *item;
4506         struct nlattr *fmsg_nlattr;
4507         int i = 0;
4508         int err;
4509
4510         fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
4511         if (!fmsg_nlattr)
4512                 return -EMSGSIZE;
4513
4514         list_for_each_entry(item, &fmsg->item_list, list) {
4515                 if (i < *start) {
4516                         i++;
4517                         continue;
4518                 }
4519
4520                 switch (item->attrtype) {
4521                 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
4522                 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
4523                 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
4524                 case DEVLINK_ATTR_FMSG_NEST_END:
4525                         err = nla_put_flag(skb, item->attrtype);
4526                         break;
4527                 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
4528                         err = devlink_fmsg_item_fill_type(item, skb);
4529                         if (err)
4530                                 break;
4531                         err = devlink_fmsg_item_fill_data(item, skb);
4532                         break;
4533                 case DEVLINK_ATTR_FMSG_OBJ_NAME:
4534                         err = nla_put_string(skb, item->attrtype,
4535                                              (char *) &item->value);
4536                         break;
4537                 default:
4538                         err = -EINVAL;
4539                         break;
4540                 }
4541                 if (!err)
4542                         *start = ++i;
4543                 else
4544                         break;
4545         }
4546
4547         nla_nest_end(skb, fmsg_nlattr);
4548         return err;
4549 }
4550
4551 static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
4552                             struct genl_info *info,
4553                             enum devlink_command cmd, int flags)
4554 {
4555         struct nlmsghdr *nlh;
4556         struct sk_buff *skb;
4557         bool last = false;
4558         int index = 0;
4559         void *hdr;
4560         int err;
4561
4562         while (!last) {
4563                 int tmp_index = index;
4564
4565                 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4566                 if (!skb)
4567                         return -ENOMEM;
4568
4569                 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4570                                   &devlink_nl_family, flags | NLM_F_MULTI, cmd);
4571                 if (!hdr) {
4572                         err = -EMSGSIZE;
4573                         goto nla_put_failure;
4574                 }
4575
4576                 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4577                 if (!err)
4578                         last = true;
4579                 else if (err != -EMSGSIZE || tmp_index == index)
4580                         goto nla_put_failure;
4581
4582                 genlmsg_end(skb, hdr);
4583                 err = genlmsg_reply(skb, info);
4584                 if (err)
4585                         return err;
4586         }
4587
4588         skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4589         if (!skb)
4590                 return -ENOMEM;
4591         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4592                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
4593         if (!nlh) {
4594                 err = -EMSGSIZE;
4595                 goto nla_put_failure;
4596         }
4597
4598         return genlmsg_reply(skb, info);
4599
4600 nla_put_failure:
4601         nlmsg_free(skb);
4602         return err;
4603 }
4604
4605 static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4606                                struct netlink_callback *cb,
4607                                enum devlink_command cmd)
4608 {
4609         int index = cb->args[0];
4610         int tmp_index = index;
4611         void *hdr;
4612         int err;
4613
4614         hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4615                           &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
4616         if (!hdr) {
4617                 err = -EMSGSIZE;
4618                 goto nla_put_failure;
4619         }
4620
4621         err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4622         if ((err && err != -EMSGSIZE) || tmp_index == index)
4623                 goto nla_put_failure;
4624
4625         cb->args[0] = index;
4626         genlmsg_end(skb, hdr);
4627         return skb->len;
4628
4629 nla_put_failure:
4630         genlmsg_cancel(skb, hdr);
4631         return err;
4632 }
4633
4634 struct devlink_health_reporter {
4635         struct list_head list;
4636         void *priv;
4637         const struct devlink_health_reporter_ops *ops;
4638         struct devlink *devlink;
4639         struct devlink_fmsg *dump_fmsg;
4640         struct mutex dump_lock; /* lock parallel read/write from dump buffers */
4641         u64 graceful_period;
4642         bool auto_recover;
4643         u8 health_state;
4644         u64 dump_ts;
4645         u64 dump_real_ts;
4646         u64 error_count;
4647         u64 recovery_count;
4648         u64 last_recovery_ts;
4649         refcount_t refcount;
4650 };
4651
4652 void *
4653 devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
4654 {
4655         return reporter->priv;
4656 }
4657 EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
4658
4659 static struct devlink_health_reporter *
4660 devlink_health_reporter_find_by_name(struct devlink *devlink,
4661                                      const char *reporter_name)
4662 {
4663         struct devlink_health_reporter *reporter;
4664
4665         lockdep_assert_held(&devlink->reporters_lock);
4666         list_for_each_entry(reporter, &devlink->reporter_list, list)
4667                 if (!strcmp(reporter->ops->name, reporter_name))
4668                         return reporter;
4669         return NULL;
4670 }
4671
4672 /**
4673  *      devlink_health_reporter_create - create devlink health reporter
4674  *
4675  *      @devlink: devlink
4676  *      @ops: ops
4677  *      @graceful_period: to avoid recovery loops, in msecs
4678  *      @auto_recover: auto recover when error occurs
4679  *      @priv: priv
4680  */
4681 struct devlink_health_reporter *
4682 devlink_health_reporter_create(struct devlink *devlink,
4683                                const struct devlink_health_reporter_ops *ops,
4684                                u64 graceful_period, bool auto_recover,
4685                                void *priv)
4686 {
4687         struct devlink_health_reporter *reporter;
4688
4689         mutex_lock(&devlink->reporters_lock);
4690         if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
4691                 reporter = ERR_PTR(-EEXIST);
4692                 goto unlock;
4693         }
4694
4695         if (WARN_ON(auto_recover && !ops->recover) ||
4696             WARN_ON(graceful_period && !ops->recover)) {
4697                 reporter = ERR_PTR(-EINVAL);
4698                 goto unlock;
4699         }
4700
4701         reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
4702         if (!reporter) {
4703                 reporter = ERR_PTR(-ENOMEM);
4704                 goto unlock;
4705         }
4706
4707         reporter->priv = priv;
4708         reporter->ops = ops;
4709         reporter->devlink = devlink;
4710         reporter->graceful_period = graceful_period;
4711         reporter->auto_recover = auto_recover;
4712         mutex_init(&reporter->dump_lock);
4713         refcount_set(&reporter->refcount, 1);
4714         list_add_tail(&reporter->list, &devlink->reporter_list);
4715 unlock:
4716         mutex_unlock(&devlink->reporters_lock);
4717         return reporter;
4718 }
4719 EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
4720
4721 /**
4722  *      devlink_health_reporter_destroy - destroy devlink health reporter
4723  *
4724  *      @reporter: devlink health reporter to destroy
4725  */
4726 void
4727 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
4728 {
4729         mutex_lock(&reporter->devlink->reporters_lock);
4730         list_del(&reporter->list);
4731         mutex_unlock(&reporter->devlink->reporters_lock);
4732         while (refcount_read(&reporter->refcount) > 1)
4733                 msleep(100);
4734         mutex_destroy(&reporter->dump_lock);
4735         if (reporter->dump_fmsg)
4736                 devlink_fmsg_free(reporter->dump_fmsg);
4737         kfree(reporter);
4738 }
4739 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
4740
4741 void
4742 devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
4743                                      enum devlink_health_reporter_state state)
4744 {
4745         if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
4746                     state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
4747                 return;
4748
4749         if (reporter->health_state == state)
4750                 return;
4751
4752         reporter->health_state = state;
4753         trace_devlink_health_reporter_state_update(reporter->devlink,
4754                                                    reporter->ops->name, state);
4755 }
4756 EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
4757
4758 static int
4759 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
4760                                 void *priv_ctx)
4761 {
4762         int err;
4763
4764         if (!reporter->ops->recover)
4765                 return -EOPNOTSUPP;
4766
4767         err = reporter->ops->recover(reporter, priv_ctx);
4768         if (err)
4769                 return err;
4770
4771         reporter->recovery_count++;
4772         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
4773         reporter->last_recovery_ts = jiffies;
4774
4775         return 0;
4776 }
4777
4778 static void
4779 devlink_health_dump_clear(struct devlink_health_reporter *reporter)
4780 {
4781         if (!reporter->dump_fmsg)
4782                 return;
4783         devlink_fmsg_free(reporter->dump_fmsg);
4784         reporter->dump_fmsg = NULL;
4785 }
4786
4787 static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
4788                                   void *priv_ctx)
4789 {
4790         int err;
4791
4792         if (!reporter->ops->dump)
4793                 return 0;
4794
4795         if (reporter->dump_fmsg)
4796                 return 0;
4797
4798         reporter->dump_fmsg = devlink_fmsg_alloc();
4799         if (!reporter->dump_fmsg) {
4800                 err = -ENOMEM;
4801                 return err;
4802         }
4803
4804         err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
4805         if (err)
4806                 goto dump_err;
4807
4808         err = reporter->ops->dump(reporter, reporter->dump_fmsg,
4809                                   priv_ctx);
4810         if (err)
4811                 goto dump_err;
4812
4813         err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
4814         if (err)
4815                 goto dump_err;
4816
4817         reporter->dump_ts = jiffies;
4818         reporter->dump_real_ts = ktime_get_real_ns();
4819
4820         return 0;
4821
4822 dump_err:
4823         devlink_health_dump_clear(reporter);
4824         return err;
4825 }
4826
4827 int devlink_health_report(struct devlink_health_reporter *reporter,
4828                           const char *msg, void *priv_ctx)
4829 {
4830         enum devlink_health_reporter_state prev_health_state;
4831         struct devlink *devlink = reporter->devlink;
4832         unsigned long recover_ts_threshold;
4833
4834         /* write a log message of the current error */
4835         WARN_ON(!msg);
4836         trace_devlink_health_report(devlink, reporter->ops->name, msg);
4837         reporter->error_count++;
4838         prev_health_state = reporter->health_state;
4839         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4840
4841         /* abort if the previous error wasn't recovered */
4842         recover_ts_threshold = reporter->last_recovery_ts +
4843                                msecs_to_jiffies(reporter->graceful_period);
4844         if (reporter->auto_recover &&
4845             (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
4846              (reporter->last_recovery_ts && reporter->recovery_count &&
4847               time_is_after_jiffies(recover_ts_threshold)))) {
4848                 trace_devlink_health_recover_aborted(devlink,
4849                                                      reporter->ops->name,
4850                                                      reporter->health_state,
4851                                                      jiffies -
4852                                                      reporter->last_recovery_ts);
4853                 return -ECANCELED;
4854         }
4855
4856         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4857
4858         mutex_lock(&reporter->dump_lock);
4859         /* store current dump of current error, for later analysis */
4860         devlink_health_do_dump(reporter, priv_ctx);
4861         mutex_unlock(&reporter->dump_lock);
4862
4863         if (reporter->auto_recover)
4864                 return devlink_health_reporter_recover(reporter, priv_ctx);
4865
4866         return 0;
4867 }
4868 EXPORT_SYMBOL_GPL(devlink_health_report);
4869
4870 static struct devlink_health_reporter *
4871 devlink_health_reporter_get_from_attrs(struct devlink *devlink,
4872                                        struct nlattr **attrs)
4873 {
4874         struct devlink_health_reporter *reporter;
4875         char *reporter_name;
4876
4877         if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
4878                 return NULL;
4879
4880         reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
4881         mutex_lock(&devlink->reporters_lock);
4882         reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
4883         if (reporter)
4884                 refcount_inc(&reporter->refcount);
4885         mutex_unlock(&devlink->reporters_lock);
4886         return reporter;
4887 }
4888
4889 static struct devlink_health_reporter *
4890 devlink_health_reporter_get_from_info(struct devlink *devlink,
4891                                       struct genl_info *info)
4892 {
4893         return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
4894 }
4895
4896 static struct devlink_health_reporter *
4897 devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
4898 {
4899         struct devlink_health_reporter *reporter;
4900         struct devlink *devlink;
4901         struct nlattr **attrs;
4902         int err;
4903
4904         attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
4905         if (!attrs)
4906                 return NULL;
4907
4908         err = nlmsg_parse_deprecated(cb->nlh,
4909                                      GENL_HDRLEN + devlink_nl_family.hdrsize,
4910                                      attrs, DEVLINK_ATTR_MAX,
4911                                      devlink_nl_family.policy, cb->extack);
4912         if (err)
4913                 goto free;
4914
4915         mutex_lock(&devlink_mutex);
4916         devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
4917         if (IS_ERR(devlink))
4918                 goto unlock;
4919
4920         reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
4921         mutex_unlock(&devlink_mutex);
4922         kfree(attrs);
4923         return reporter;
4924 unlock:
4925         mutex_unlock(&devlink_mutex);
4926 free:
4927         kfree(attrs);
4928         return NULL;
4929 }
4930
4931 static void
4932 devlink_health_reporter_put(struct devlink_health_reporter *reporter)
4933 {
4934         refcount_dec(&reporter->refcount);
4935 }
4936
4937 static int
4938 devlink_nl_health_reporter_fill(struct sk_buff *msg,
4939                                 struct devlink *devlink,
4940                                 struct devlink_health_reporter *reporter,
4941                                 enum devlink_command cmd, u32 portid,
4942                                 u32 seq, int flags)
4943 {
4944         struct nlattr *reporter_attr;
4945         void *hdr;
4946
4947         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4948         if (!hdr)
4949                 return -EMSGSIZE;
4950
4951         if (devlink_nl_put_handle(msg, devlink))
4952                 goto genlmsg_cancel;
4953
4954         reporter_attr = nla_nest_start_noflag(msg,
4955                                               DEVLINK_ATTR_HEALTH_REPORTER);
4956         if (!reporter_attr)
4957                 goto genlmsg_cancel;
4958         if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
4959                            reporter->ops->name))
4960                 goto reporter_nest_cancel;
4961         if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
4962                        reporter->health_state))
4963                 goto reporter_nest_cancel;
4964         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
4965                               reporter->error_count, DEVLINK_ATTR_PAD))
4966                 goto reporter_nest_cancel;
4967         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
4968                               reporter->recovery_count, DEVLINK_ATTR_PAD))
4969                 goto reporter_nest_cancel;
4970         if (reporter->ops->recover &&
4971             nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
4972                               reporter->graceful_period,
4973                               DEVLINK_ATTR_PAD))
4974                 goto reporter_nest_cancel;
4975         if (reporter->ops->recover &&
4976             nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
4977                        reporter->auto_recover))
4978                 goto reporter_nest_cancel;
4979         if (reporter->dump_fmsg &&
4980             nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
4981                               jiffies_to_msecs(reporter->dump_ts),
4982                               DEVLINK_ATTR_PAD))
4983                 goto reporter_nest_cancel;
4984         if (reporter->dump_fmsg &&
4985             nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
4986                               reporter->dump_real_ts, DEVLINK_ATTR_PAD))
4987                 goto reporter_nest_cancel;
4988
4989         nla_nest_end(msg, reporter_attr);
4990         genlmsg_end(msg, hdr);
4991         return 0;
4992
4993 reporter_nest_cancel:
4994         nla_nest_end(msg, reporter_attr);
4995 genlmsg_cancel:
4996         genlmsg_cancel(msg, hdr);
4997         return -EMSGSIZE;
4998 }
4999
5000 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
5001                                                    struct genl_info *info)
5002 {
5003         struct devlink *devlink = info->user_ptr[0];
5004         struct devlink_health_reporter *reporter;
5005         struct sk_buff *msg;
5006         int err;
5007
5008         reporter = devlink_health_reporter_get_from_info(devlink, info);
5009         if (!reporter)
5010                 return -EINVAL;
5011
5012         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5013         if (!msg) {
5014                 err = -ENOMEM;
5015                 goto out;
5016         }
5017
5018         err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
5019                                               DEVLINK_CMD_HEALTH_REPORTER_GET,
5020                                               info->snd_portid, info->snd_seq,
5021                                               0);
5022         if (err) {
5023                 nlmsg_free(msg);
5024                 goto out;
5025         }
5026
5027         err = genlmsg_reply(msg, info);
5028 out:
5029         devlink_health_reporter_put(reporter);
5030         return err;
5031 }
5032
5033 static int
5034 devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
5035                                           struct netlink_callback *cb)
5036 {
5037         struct devlink_health_reporter *reporter;
5038         struct devlink *devlink;
5039         int start = cb->args[0];
5040         int idx = 0;
5041         int err;
5042
5043         mutex_lock(&devlink_mutex);
5044         list_for_each_entry(devlink, &devlink_list, list) {
5045                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5046                         continue;
5047                 mutex_lock(&devlink->reporters_lock);
5048                 list_for_each_entry(reporter, &devlink->reporter_list,
5049                                     list) {
5050                         if (idx < start) {
5051                                 idx++;
5052                                 continue;
5053                         }
5054                         err = devlink_nl_health_reporter_fill(msg, devlink,
5055                                                               reporter,
5056                                                               DEVLINK_CMD_HEALTH_REPORTER_GET,
5057                                                               NETLINK_CB(cb->skb).portid,
5058                                                               cb->nlh->nlmsg_seq,
5059                                                               NLM_F_MULTI);
5060                         if (err) {
5061                                 mutex_unlock(&devlink->reporters_lock);
5062                                 goto out;
5063                         }
5064                         idx++;
5065                 }
5066                 mutex_unlock(&devlink->reporters_lock);
5067         }
5068 out:
5069         mutex_unlock(&devlink_mutex);
5070
5071         cb->args[0] = idx;
5072         return msg->len;
5073 }
5074
5075 static int
5076 devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
5077                                         struct genl_info *info)
5078 {
5079         struct devlink *devlink = info->user_ptr[0];
5080         struct devlink_health_reporter *reporter;
5081         int err;
5082
5083         reporter = devlink_health_reporter_get_from_info(devlink, info);
5084         if (!reporter)
5085                 return -EINVAL;
5086
5087         if (!reporter->ops->recover &&
5088             (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
5089              info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
5090                 err = -EOPNOTSUPP;
5091                 goto out;
5092         }
5093
5094         if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
5095                 reporter->graceful_period =
5096                         nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
5097
5098         if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
5099                 reporter->auto_recover =
5100                         nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
5101
5102         devlink_health_reporter_put(reporter);
5103         return 0;
5104 out:
5105         devlink_health_reporter_put(reporter);
5106         return err;
5107 }
5108
5109 static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
5110                                                        struct genl_info *info)
5111 {
5112         struct devlink *devlink = info->user_ptr[0];
5113         struct devlink_health_reporter *reporter;
5114         int err;
5115
5116         reporter = devlink_health_reporter_get_from_info(devlink, info);
5117         if (!reporter)
5118                 return -EINVAL;
5119
5120         err = devlink_health_reporter_recover(reporter, NULL);
5121
5122         devlink_health_reporter_put(reporter);
5123         return err;
5124 }
5125
5126 static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
5127                                                         struct genl_info *info)
5128 {
5129         struct devlink *devlink = info->user_ptr[0];
5130         struct devlink_health_reporter *reporter;
5131         struct devlink_fmsg *fmsg;
5132         int err;
5133
5134         reporter = devlink_health_reporter_get_from_info(devlink, info);
5135         if (!reporter)
5136                 return -EINVAL;
5137
5138         if (!reporter->ops->diagnose) {
5139                 devlink_health_reporter_put(reporter);
5140                 return -EOPNOTSUPP;
5141         }
5142
5143         fmsg = devlink_fmsg_alloc();
5144         if (!fmsg) {
5145                 devlink_health_reporter_put(reporter);
5146                 return -ENOMEM;
5147         }
5148
5149         err = devlink_fmsg_obj_nest_start(fmsg);
5150         if (err)
5151                 goto out;
5152
5153         err = reporter->ops->diagnose(reporter, fmsg);
5154         if (err)
5155                 goto out;
5156
5157         err = devlink_fmsg_obj_nest_end(fmsg);
5158         if (err)
5159                 goto out;
5160
5161         err = devlink_fmsg_snd(fmsg, info,
5162                                DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
5163
5164 out:
5165         devlink_fmsg_free(fmsg);
5166         devlink_health_reporter_put(reporter);
5167         return err;
5168 }
5169
5170 static int
5171 devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
5172                                                struct netlink_callback *cb)
5173 {
5174         struct devlink_health_reporter *reporter;
5175         u64 start = cb->args[0];
5176         int err;
5177
5178         reporter = devlink_health_reporter_get_from_cb(cb);
5179         if (!reporter)
5180                 return -EINVAL;
5181
5182         if (!reporter->ops->dump) {
5183                 err = -EOPNOTSUPP;
5184                 goto out;
5185         }
5186         mutex_lock(&reporter->dump_lock);
5187         if (!start) {
5188                 err = devlink_health_do_dump(reporter, NULL);
5189                 if (err)
5190                         goto unlock;
5191                 cb->args[1] = reporter->dump_ts;
5192         }
5193         if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
5194                 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
5195                 err = -EAGAIN;
5196                 goto unlock;
5197         }
5198
5199         err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
5200                                   DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
5201 unlock:
5202         mutex_unlock(&reporter->dump_lock);
5203 out:
5204         devlink_health_reporter_put(reporter);
5205         return err;
5206 }
5207
5208 static int
5209 devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
5210                                                struct genl_info *info)
5211 {
5212         struct devlink *devlink = info->user_ptr[0];
5213         struct devlink_health_reporter *reporter;
5214
5215         reporter = devlink_health_reporter_get_from_info(devlink, info);
5216         if (!reporter)
5217                 return -EINVAL;
5218
5219         if (!reporter->ops->dump) {
5220                 devlink_health_reporter_put(reporter);
5221                 return -EOPNOTSUPP;
5222         }
5223
5224         mutex_lock(&reporter->dump_lock);
5225         devlink_health_dump_clear(reporter);
5226         mutex_unlock(&reporter->dump_lock);
5227         devlink_health_reporter_put(reporter);
5228         return 0;
5229 }
5230
5231 struct devlink_stats {
5232         u64 rx_bytes;
5233         u64 rx_packets;
5234         struct u64_stats_sync syncp;
5235 };
5236
5237 /**
5238  * struct devlink_trap_group_item - Packet trap group attributes.
5239  * @group: Immutable packet trap group attributes.
5240  * @refcount: Number of trap items using the group.
5241  * @list: trap_group_list member.
5242  * @stats: Trap group statistics.
5243  *
5244  * Describes packet trap group attributes. Created by devlink during trap
5245  * registration.
5246  */
5247 struct devlink_trap_group_item {
5248         const struct devlink_trap_group *group;
5249         refcount_t refcount;
5250         struct list_head list;
5251         struct devlink_stats __percpu *stats;
5252 };
5253
5254 /**
5255  * struct devlink_trap_item - Packet trap attributes.
5256  * @trap: Immutable packet trap attributes.
5257  * @group_item: Associated group item.
5258  * @list: trap_list member.
5259  * @action: Trap action.
5260  * @stats: Trap statistics.
5261  * @priv: Driver private information.
5262  *
5263  * Describes both mutable and immutable packet trap attributes. Created by
5264  * devlink during trap registration and used for all trap related operations.
5265  */
5266 struct devlink_trap_item {
5267         const struct devlink_trap *trap;
5268         struct devlink_trap_group_item *group_item;
5269         struct list_head list;
5270         enum devlink_trap_action action;
5271         struct devlink_stats __percpu *stats;
5272         void *priv;
5273 };
5274
5275 static struct devlink_trap_item *
5276 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
5277 {
5278         struct devlink_trap_item *trap_item;
5279
5280         list_for_each_entry(trap_item, &devlink->trap_list, list) {
5281                 if (!strcmp(trap_item->trap->name, name))
5282                         return trap_item;
5283         }
5284
5285         return NULL;
5286 }
5287
5288 static struct devlink_trap_item *
5289 devlink_trap_item_get_from_info(struct devlink *devlink,
5290                                 struct genl_info *info)
5291 {
5292         struct nlattr *attr;
5293
5294         if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
5295                 return NULL;
5296         attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
5297
5298         return devlink_trap_item_lookup(devlink, nla_data(attr));
5299 }
5300
5301 static int
5302 devlink_trap_action_get_from_info(struct genl_info *info,
5303                                   enum devlink_trap_action *p_trap_action)
5304 {
5305         u8 val;
5306
5307         val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
5308         switch (val) {
5309         case DEVLINK_TRAP_ACTION_DROP: /* fall-through */
5310         case DEVLINK_TRAP_ACTION_TRAP:
5311                 *p_trap_action = val;
5312                 break;
5313         default:
5314                 return -EINVAL;
5315         }
5316
5317         return 0;
5318 }
5319
5320 static int devlink_trap_metadata_put(struct sk_buff *msg,
5321                                      const struct devlink_trap *trap)
5322 {
5323         struct nlattr *attr;
5324
5325         attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
5326         if (!attr)
5327                 return -EMSGSIZE;
5328
5329         if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
5330             nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
5331                 goto nla_put_failure;
5332
5333         nla_nest_end(msg, attr);
5334
5335         return 0;
5336
5337 nla_put_failure:
5338         nla_nest_cancel(msg, attr);
5339         return -EMSGSIZE;
5340 }
5341
5342 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
5343                                     struct devlink_stats *stats)
5344 {
5345         int i;
5346
5347         memset(stats, 0, sizeof(*stats));
5348         for_each_possible_cpu(i) {
5349                 struct devlink_stats *cpu_stats;
5350                 u64 rx_packets, rx_bytes;
5351                 unsigned int start;
5352
5353                 cpu_stats = per_cpu_ptr(trap_stats, i);
5354                 do {
5355                         start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
5356                         rx_packets = cpu_stats->rx_packets;
5357                         rx_bytes = cpu_stats->rx_bytes;
5358                 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
5359
5360                 stats->rx_packets += rx_packets;
5361                 stats->rx_bytes += rx_bytes;
5362         }
5363 }
5364
5365 static int devlink_trap_stats_put(struct sk_buff *msg,
5366                                   struct devlink_stats __percpu *trap_stats)
5367 {
5368         struct devlink_stats stats;
5369         struct nlattr *attr;
5370
5371         devlink_trap_stats_read(trap_stats, &stats);
5372
5373         attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
5374         if (!attr)
5375                 return -EMSGSIZE;
5376
5377         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
5378                               stats.rx_packets, DEVLINK_ATTR_PAD))
5379                 goto nla_put_failure;
5380
5381         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
5382                               stats.rx_bytes, DEVLINK_ATTR_PAD))
5383                 goto nla_put_failure;
5384
5385         nla_nest_end(msg, attr);
5386
5387         return 0;
5388
5389 nla_put_failure:
5390         nla_nest_cancel(msg, attr);
5391         return -EMSGSIZE;
5392 }
5393
5394 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
5395                                 const struct devlink_trap_item *trap_item,
5396                                 enum devlink_command cmd, u32 portid, u32 seq,
5397                                 int flags)
5398 {
5399         struct devlink_trap_group_item *group_item = trap_item->group_item;
5400         void *hdr;
5401         int err;
5402
5403         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5404         if (!hdr)
5405                 return -EMSGSIZE;
5406
5407         if (devlink_nl_put_handle(msg, devlink))
5408                 goto nla_put_failure;
5409
5410         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5411                            group_item->group->name))
5412                 goto nla_put_failure;
5413
5414         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
5415                 goto nla_put_failure;
5416
5417         if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
5418                 goto nla_put_failure;
5419
5420         if (trap_item->trap->generic &&
5421             nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5422                 goto nla_put_failure;
5423
5424         if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
5425                 goto nla_put_failure;
5426
5427         err = devlink_trap_metadata_put(msg, trap_item->trap);
5428         if (err)
5429                 goto nla_put_failure;
5430
5431         err = devlink_trap_stats_put(msg, trap_item->stats);
5432         if (err)
5433                 goto nla_put_failure;
5434
5435         genlmsg_end(msg, hdr);
5436
5437         return 0;
5438
5439 nla_put_failure:
5440         genlmsg_cancel(msg, hdr);
5441         return -EMSGSIZE;
5442 }
5443
5444 static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
5445                                         struct genl_info *info)
5446 {
5447         struct netlink_ext_ack *extack = info->extack;
5448         struct devlink *devlink = info->user_ptr[0];
5449         struct devlink_trap_item *trap_item;
5450         struct sk_buff *msg;
5451         int err;
5452
5453         if (list_empty(&devlink->trap_list))
5454                 return -EOPNOTSUPP;
5455
5456         trap_item = devlink_trap_item_get_from_info(devlink, info);
5457         if (!trap_item) {
5458                 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5459                 return -ENOENT;
5460         }
5461
5462         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5463         if (!msg)
5464                 return -ENOMEM;
5465
5466         err = devlink_nl_trap_fill(msg, devlink, trap_item,
5467                                    DEVLINK_CMD_TRAP_NEW, info->snd_portid,
5468                                    info->snd_seq, 0);
5469         if (err)
5470                 goto err_trap_fill;
5471
5472         return genlmsg_reply(msg, info);
5473
5474 err_trap_fill:
5475         nlmsg_free(msg);
5476         return err;
5477 }
5478
5479 static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
5480                                           struct netlink_callback *cb)
5481 {
5482         struct devlink_trap_item *trap_item;
5483         struct devlink *devlink;
5484         int start = cb->args[0];
5485         int idx = 0;
5486         int err;
5487
5488         mutex_lock(&devlink_mutex);
5489         list_for_each_entry(devlink, &devlink_list, list) {
5490                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5491                         continue;
5492                 mutex_lock(&devlink->lock);
5493                 list_for_each_entry(trap_item, &devlink->trap_list, list) {
5494                         if (idx < start) {
5495                                 idx++;
5496                                 continue;
5497                         }
5498                         err = devlink_nl_trap_fill(msg, devlink, trap_item,
5499                                                    DEVLINK_CMD_TRAP_NEW,
5500                                                    NETLINK_CB(cb->skb).portid,
5501                                                    cb->nlh->nlmsg_seq,
5502                                                    NLM_F_MULTI);
5503                         if (err) {
5504                                 mutex_unlock(&devlink->lock);
5505                                 goto out;
5506                         }
5507                         idx++;
5508                 }
5509                 mutex_unlock(&devlink->lock);
5510         }
5511 out:
5512         mutex_unlock(&devlink_mutex);
5513
5514         cb->args[0] = idx;
5515         return msg->len;
5516 }
5517
5518 static int __devlink_trap_action_set(struct devlink *devlink,
5519                                      struct devlink_trap_item *trap_item,
5520                                      enum devlink_trap_action trap_action,
5521                                      struct netlink_ext_ack *extack)
5522 {
5523         int err;
5524
5525         if (trap_item->action != trap_action &&
5526             trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
5527                 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
5528                 return 0;
5529         }
5530
5531         err = devlink->ops->trap_action_set(devlink, trap_item->trap,
5532                                             trap_action);
5533         if (err)
5534                 return err;
5535
5536         trap_item->action = trap_action;
5537
5538         return 0;
5539 }
5540
5541 static int devlink_trap_action_set(struct devlink *devlink,
5542                                    struct devlink_trap_item *trap_item,
5543                                    struct genl_info *info)
5544 {
5545         enum devlink_trap_action trap_action;
5546         int err;
5547
5548         if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5549                 return 0;
5550
5551         err = devlink_trap_action_get_from_info(info, &trap_action);
5552         if (err) {
5553                 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5554                 return -EINVAL;
5555         }
5556
5557         return __devlink_trap_action_set(devlink, trap_item, trap_action,
5558                                          info->extack);
5559 }
5560
5561 static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
5562                                         struct genl_info *info)
5563 {
5564         struct netlink_ext_ack *extack = info->extack;
5565         struct devlink *devlink = info->user_ptr[0];
5566         struct devlink_trap_item *trap_item;
5567         int err;
5568
5569         if (list_empty(&devlink->trap_list))
5570                 return -EOPNOTSUPP;
5571
5572         trap_item = devlink_trap_item_get_from_info(devlink, info);
5573         if (!trap_item) {
5574                 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5575                 return -ENOENT;
5576         }
5577
5578         err = devlink_trap_action_set(devlink, trap_item, info);
5579         if (err)
5580                 return err;
5581
5582         return 0;
5583 }
5584
5585 static struct devlink_trap_group_item *
5586 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
5587 {
5588         struct devlink_trap_group_item *group_item;
5589
5590         list_for_each_entry(group_item, &devlink->trap_group_list, list) {
5591                 if (!strcmp(group_item->group->name, name))
5592                         return group_item;
5593         }
5594
5595         return NULL;
5596 }
5597
5598 static struct devlink_trap_group_item *
5599 devlink_trap_group_item_get_from_info(struct devlink *devlink,
5600                                       struct genl_info *info)
5601 {
5602         char *name;
5603
5604         if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
5605                 return NULL;
5606         name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
5607
5608         return devlink_trap_group_item_lookup(devlink, name);
5609 }
5610
5611 static int
5612 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
5613                            const struct devlink_trap_group_item *group_item,
5614                            enum devlink_command cmd, u32 portid, u32 seq,
5615                            int flags)
5616 {
5617         void *hdr;
5618         int err;
5619
5620         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5621         if (!hdr)
5622                 return -EMSGSIZE;
5623
5624         if (devlink_nl_put_handle(msg, devlink))
5625                 goto nla_put_failure;
5626
5627         if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5628                            group_item->group->name))
5629                 goto nla_put_failure;
5630
5631         if (group_item->group->generic &&
5632             nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5633                 goto nla_put_failure;
5634
5635         err = devlink_trap_stats_put(msg, group_item->stats);
5636         if (err)
5637                 goto nla_put_failure;
5638
5639         genlmsg_end(msg, hdr);
5640
5641         return 0;
5642
5643 nla_put_failure:
5644         genlmsg_cancel(msg, hdr);
5645         return -EMSGSIZE;
5646 }
5647
5648 static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
5649                                               struct genl_info *info)
5650 {
5651         struct netlink_ext_ack *extack = info->extack;
5652         struct devlink *devlink = info->user_ptr[0];
5653         struct devlink_trap_group_item *group_item;
5654         struct sk_buff *msg;
5655         int err;
5656
5657         if (list_empty(&devlink->trap_group_list))
5658                 return -EOPNOTSUPP;
5659
5660         group_item = devlink_trap_group_item_get_from_info(devlink, info);
5661         if (!group_item) {
5662                 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5663                 return -ENOENT;
5664         }
5665
5666         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5667         if (!msg)
5668                 return -ENOMEM;
5669
5670         err = devlink_nl_trap_group_fill(msg, devlink, group_item,
5671                                          DEVLINK_CMD_TRAP_GROUP_NEW,
5672                                          info->snd_portid, info->snd_seq, 0);
5673         if (err)
5674                 goto err_trap_group_fill;
5675
5676         return genlmsg_reply(msg, info);
5677
5678 err_trap_group_fill:
5679         nlmsg_free(msg);
5680         return err;
5681 }
5682
5683 static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
5684                                                 struct netlink_callback *cb)
5685 {
5686         enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
5687         struct devlink_trap_group_item *group_item;
5688         u32 portid = NETLINK_CB(cb->skb).portid;
5689         struct devlink *devlink;
5690         int start = cb->args[0];
5691         int idx = 0;
5692         int err;
5693
5694         mutex_lock(&devlink_mutex);
5695         list_for_each_entry(devlink, &devlink_list, list) {
5696                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5697                         continue;
5698                 mutex_lock(&devlink->lock);
5699                 list_for_each_entry(group_item, &devlink->trap_group_list,
5700                                     list) {
5701                         if (idx < start) {
5702                                 idx++;
5703                                 continue;
5704                         }
5705                         err = devlink_nl_trap_group_fill(msg, devlink,
5706                                                          group_item, cmd,
5707                                                          portid,
5708                                                          cb->nlh->nlmsg_seq,
5709                                                          NLM_F_MULTI);
5710                         if (err) {
5711                                 mutex_unlock(&devlink->lock);
5712                                 goto out;
5713                         }
5714                         idx++;
5715                 }
5716                 mutex_unlock(&devlink->lock);
5717         }
5718 out:
5719         mutex_unlock(&devlink_mutex);
5720
5721         cb->args[0] = idx;
5722         return msg->len;
5723 }
5724
5725 static int
5726 __devlink_trap_group_action_set(struct devlink *devlink,
5727                                 struct devlink_trap_group_item *group_item,
5728                                 enum devlink_trap_action trap_action,
5729                                 struct netlink_ext_ack *extack)
5730 {
5731         const char *group_name = group_item->group->name;
5732         struct devlink_trap_item *trap_item;
5733         int err;
5734
5735         list_for_each_entry(trap_item, &devlink->trap_list, list) {
5736                 if (strcmp(trap_item->trap->group.name, group_name))
5737                         continue;
5738                 err = __devlink_trap_action_set(devlink, trap_item,
5739                                                 trap_action, extack);
5740                 if (err)
5741                         return err;
5742         }
5743
5744         return 0;
5745 }
5746
5747 static int
5748 devlink_trap_group_action_set(struct devlink *devlink,
5749                               struct devlink_trap_group_item *group_item,
5750                               struct genl_info *info)
5751 {
5752         enum devlink_trap_action trap_action;
5753         int err;
5754
5755         if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5756                 return 0;
5757
5758         err = devlink_trap_action_get_from_info(info, &trap_action);
5759         if (err) {
5760                 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5761                 return -EINVAL;
5762         }
5763
5764         err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
5765                                               info->extack);
5766         if (err)
5767                 return err;
5768
5769         return 0;
5770 }
5771
5772 static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
5773                                               struct genl_info *info)
5774 {
5775         struct netlink_ext_ack *extack = info->extack;
5776         struct devlink *devlink = info->user_ptr[0];
5777         struct devlink_trap_group_item *group_item;
5778         int err;
5779
5780         if (list_empty(&devlink->trap_group_list))
5781                 return -EOPNOTSUPP;
5782
5783         group_item = devlink_trap_group_item_get_from_info(devlink, info);
5784         if (!group_item) {
5785                 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5786                 return -ENOENT;
5787         }
5788
5789         err = devlink_trap_group_action_set(devlink, group_item, info);
5790         if (err)
5791                 return err;
5792
5793         return 0;
5794 }
5795
5796 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
5797         [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
5798         [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
5799         [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
5800         [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
5801         [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
5802         [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
5803         [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
5804         [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
5805         [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
5806         [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
5807         [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
5808         [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
5809         [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
5810         [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
5811         [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
5812         [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
5813         [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
5814         [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
5815         [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
5816         [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
5817         [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
5818         [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
5819         [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
5820         [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
5821         [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
5822         [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
5823         [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
5824         [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
5825         [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
5826         [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
5827         [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
5828         [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
5829         [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
5830         [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
5831 };
5832
5833 static const struct genl_ops devlink_nl_ops[] = {
5834         {
5835                 .cmd = DEVLINK_CMD_GET,
5836                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5837                 .doit = devlink_nl_cmd_get_doit,
5838                 .dumpit = devlink_nl_cmd_get_dumpit,
5839                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5840                 /* can be retrieved by unprivileged users */
5841         },
5842         {
5843                 .cmd = DEVLINK_CMD_PORT_GET,
5844                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5845                 .doit = devlink_nl_cmd_port_get_doit,
5846                 .dumpit = devlink_nl_cmd_port_get_dumpit,
5847                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5848                 /* can be retrieved by unprivileged users */
5849         },
5850         {
5851                 .cmd = DEVLINK_CMD_PORT_SET,
5852                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5853                 .doit = devlink_nl_cmd_port_set_doit,
5854                 .flags = GENL_ADMIN_PERM,
5855                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5856         },
5857         {
5858                 .cmd = DEVLINK_CMD_PORT_SPLIT,
5859                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5860                 .doit = devlink_nl_cmd_port_split_doit,
5861                 .flags = GENL_ADMIN_PERM,
5862                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5863                                   DEVLINK_NL_FLAG_NO_LOCK,
5864         },
5865         {
5866                 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
5867                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5868                 .doit = devlink_nl_cmd_port_unsplit_doit,
5869                 .flags = GENL_ADMIN_PERM,
5870                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5871                                   DEVLINK_NL_FLAG_NO_LOCK,
5872         },
5873         {
5874                 .cmd = DEVLINK_CMD_SB_GET,
5875                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5876                 .doit = devlink_nl_cmd_sb_get_doit,
5877                 .dumpit = devlink_nl_cmd_sb_get_dumpit,
5878                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5879                                   DEVLINK_NL_FLAG_NEED_SB,
5880                 /* can be retrieved by unprivileged users */
5881         },
5882         {
5883                 .cmd = DEVLINK_CMD_SB_POOL_GET,
5884                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5885                 .doit = devlink_nl_cmd_sb_pool_get_doit,
5886                 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
5887                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5888                                   DEVLINK_NL_FLAG_NEED_SB,
5889                 /* can be retrieved by unprivileged users */
5890         },
5891         {
5892                 .cmd = DEVLINK_CMD_SB_POOL_SET,
5893                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5894                 .doit = devlink_nl_cmd_sb_pool_set_doit,
5895                 .flags = GENL_ADMIN_PERM,
5896                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5897                                   DEVLINK_NL_FLAG_NEED_SB,
5898         },
5899         {
5900                 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
5901                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5902                 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
5903                 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
5904                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5905                                   DEVLINK_NL_FLAG_NEED_SB,
5906                 /* can be retrieved by unprivileged users */
5907         },
5908         {
5909                 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
5910                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5911                 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
5912                 .flags = GENL_ADMIN_PERM,
5913                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5914                                   DEVLINK_NL_FLAG_NEED_SB,
5915         },
5916         {
5917                 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
5918                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5919                 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5920                 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
5921                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5922                                   DEVLINK_NL_FLAG_NEED_SB,
5923                 /* can be retrieved by unprivileged users */
5924         },
5925         {
5926                 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
5927                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5928                 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
5929                 .flags = GENL_ADMIN_PERM,
5930                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5931                                   DEVLINK_NL_FLAG_NEED_SB,
5932         },
5933         {
5934                 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
5935                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5936                 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
5937                 .flags = GENL_ADMIN_PERM,
5938                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5939                                   DEVLINK_NL_FLAG_NEED_SB,
5940         },
5941         {
5942                 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
5943                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5944                 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
5945                 .flags = GENL_ADMIN_PERM,
5946                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5947                                   DEVLINK_NL_FLAG_NEED_SB,
5948         },
5949         {
5950                 .cmd = DEVLINK_CMD_ESWITCH_GET,
5951                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5952                 .doit = devlink_nl_cmd_eswitch_get_doit,
5953                 .flags = GENL_ADMIN_PERM,
5954                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5955         },
5956         {
5957                 .cmd = DEVLINK_CMD_ESWITCH_SET,
5958                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5959                 .doit = devlink_nl_cmd_eswitch_set_doit,
5960                 .flags = GENL_ADMIN_PERM,
5961                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5962                                   DEVLINK_NL_FLAG_NO_LOCK,
5963         },
5964         {
5965                 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
5966                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5967                 .doit = devlink_nl_cmd_dpipe_table_get,
5968                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5969                 /* can be retrieved by unprivileged users */
5970         },
5971         {
5972                 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
5973                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5974                 .doit = devlink_nl_cmd_dpipe_entries_get,
5975                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5976                 /* can be retrieved by unprivileged users */
5977         },
5978         {
5979                 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
5980                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5981                 .doit = devlink_nl_cmd_dpipe_headers_get,
5982                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5983                 /* can be retrieved by unprivileged users */
5984         },
5985         {
5986                 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
5987                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5988                 .doit = devlink_nl_cmd_dpipe_table_counters_set,
5989                 .flags = GENL_ADMIN_PERM,
5990                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5991         },
5992         {
5993                 .cmd = DEVLINK_CMD_RESOURCE_SET,
5994                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5995                 .doit = devlink_nl_cmd_resource_set,
5996                 .flags = GENL_ADMIN_PERM,
5997                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5998         },
5999         {
6000                 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
6001                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6002                 .doit = devlink_nl_cmd_resource_dump,
6003                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6004                 /* can be retrieved by unprivileged users */
6005         },
6006         {
6007                 .cmd = DEVLINK_CMD_RELOAD,
6008                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6009                 .doit = devlink_nl_cmd_reload,
6010                 .flags = GENL_ADMIN_PERM,
6011                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6012                                   DEVLINK_NL_FLAG_NO_LOCK,
6013         },
6014         {
6015                 .cmd = DEVLINK_CMD_PARAM_GET,
6016                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6017                 .doit = devlink_nl_cmd_param_get_doit,
6018                 .dumpit = devlink_nl_cmd_param_get_dumpit,
6019                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6020                 /* can be retrieved by unprivileged users */
6021         },
6022         {
6023                 .cmd = DEVLINK_CMD_PARAM_SET,
6024                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6025                 .doit = devlink_nl_cmd_param_set_doit,
6026                 .flags = GENL_ADMIN_PERM,
6027                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6028         },
6029         {
6030                 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
6031                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6032                 .doit = devlink_nl_cmd_port_param_get_doit,
6033                 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
6034                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6035                 /* can be retrieved by unprivileged users */
6036         },
6037         {
6038                 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
6039                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6040                 .doit = devlink_nl_cmd_port_param_set_doit,
6041                 .flags = GENL_ADMIN_PERM,
6042                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6043         },
6044         {
6045                 .cmd = DEVLINK_CMD_REGION_GET,
6046                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6047                 .doit = devlink_nl_cmd_region_get_doit,
6048                 .dumpit = devlink_nl_cmd_region_get_dumpit,
6049                 .flags = GENL_ADMIN_PERM,
6050                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6051         },
6052         {
6053                 .cmd = DEVLINK_CMD_REGION_DEL,
6054                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6055                 .doit = devlink_nl_cmd_region_del,
6056                 .flags = GENL_ADMIN_PERM,
6057                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6058         },
6059         {
6060                 .cmd = DEVLINK_CMD_REGION_READ,
6061                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6062                 .dumpit = devlink_nl_cmd_region_read_dumpit,
6063                 .flags = GENL_ADMIN_PERM,
6064                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6065         },
6066         {
6067                 .cmd = DEVLINK_CMD_INFO_GET,
6068                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6069                 .doit = devlink_nl_cmd_info_get_doit,
6070                 .dumpit = devlink_nl_cmd_info_get_dumpit,
6071                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6072                 /* can be retrieved by unprivileged users */
6073         },
6074         {
6075                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
6076                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6077                 .doit = devlink_nl_cmd_health_reporter_get_doit,
6078                 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
6079                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6080                                   DEVLINK_NL_FLAG_NO_LOCK,
6081                 /* can be retrieved by unprivileged users */
6082         },
6083         {
6084                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
6085                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6086                 .doit = devlink_nl_cmd_health_reporter_set_doit,
6087                 .flags = GENL_ADMIN_PERM,
6088                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6089                                   DEVLINK_NL_FLAG_NO_LOCK,
6090         },
6091         {
6092                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
6093                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6094                 .doit = devlink_nl_cmd_health_reporter_recover_doit,
6095                 .flags = GENL_ADMIN_PERM,
6096                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6097                                   DEVLINK_NL_FLAG_NO_LOCK,
6098         },
6099         {
6100                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
6101                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6102                 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
6103                 .flags = GENL_ADMIN_PERM,
6104                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6105                                   DEVLINK_NL_FLAG_NO_LOCK,
6106         },
6107         {
6108                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
6109                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6110                 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
6111                 .flags = GENL_ADMIN_PERM,
6112                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6113                                   DEVLINK_NL_FLAG_NO_LOCK,
6114         },
6115         {
6116                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
6117                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6118                 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
6119                 .flags = GENL_ADMIN_PERM,
6120                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6121                                   DEVLINK_NL_FLAG_NO_LOCK,
6122         },
6123         {
6124                 .cmd = DEVLINK_CMD_FLASH_UPDATE,
6125                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6126                 .doit = devlink_nl_cmd_flash_update,
6127                 .flags = GENL_ADMIN_PERM,
6128                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6129         },
6130         {
6131                 .cmd = DEVLINK_CMD_TRAP_GET,
6132                 .doit = devlink_nl_cmd_trap_get_doit,
6133                 .dumpit = devlink_nl_cmd_trap_get_dumpit,
6134                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6135                 /* can be retrieved by unprivileged users */
6136         },
6137         {
6138                 .cmd = DEVLINK_CMD_TRAP_SET,
6139                 .doit = devlink_nl_cmd_trap_set_doit,
6140                 .flags = GENL_ADMIN_PERM,
6141                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6142         },
6143         {
6144                 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
6145                 .doit = devlink_nl_cmd_trap_group_get_doit,
6146                 .dumpit = devlink_nl_cmd_trap_group_get_dumpit,
6147                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6148                 /* can be retrieved by unprivileged users */
6149         },
6150         {
6151                 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
6152                 .doit = devlink_nl_cmd_trap_group_set_doit,
6153                 .flags = GENL_ADMIN_PERM,
6154                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6155         },
6156 };
6157
6158 static struct genl_family devlink_nl_family __ro_after_init = {
6159         .name           = DEVLINK_GENL_NAME,
6160         .version        = DEVLINK_GENL_VERSION,
6161         .maxattr        = DEVLINK_ATTR_MAX,
6162         .policy = devlink_nl_policy,
6163         .netnsok        = true,
6164         .pre_doit       = devlink_nl_pre_doit,
6165         .post_doit      = devlink_nl_post_doit,
6166         .module         = THIS_MODULE,
6167         .ops            = devlink_nl_ops,
6168         .n_ops          = ARRAY_SIZE(devlink_nl_ops),
6169         .mcgrps         = devlink_nl_mcgrps,
6170         .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
6171 };
6172
6173 /**
6174  *      devlink_alloc - Allocate new devlink instance resources
6175  *
6176  *      @ops: ops
6177  *      @priv_size: size of user private data
6178  *
6179  *      Allocate new devlink instance resources, including devlink index
6180  *      and name.
6181  */
6182 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
6183 {
6184         struct devlink *devlink;
6185
6186         if (WARN_ON(!ops))
6187                 return NULL;
6188
6189         devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
6190         if (!devlink)
6191                 return NULL;
6192         devlink->ops = ops;
6193         devlink_net_set(devlink, &init_net);
6194         INIT_LIST_HEAD(&devlink->port_list);
6195         INIT_LIST_HEAD(&devlink->sb_list);
6196         INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
6197         INIT_LIST_HEAD(&devlink->resource_list);
6198         INIT_LIST_HEAD(&devlink->param_list);
6199         INIT_LIST_HEAD(&devlink->region_list);
6200         INIT_LIST_HEAD(&devlink->reporter_list);
6201         INIT_LIST_HEAD(&devlink->trap_list);
6202         INIT_LIST_HEAD(&devlink->trap_group_list);
6203         mutex_init(&devlink->lock);
6204         mutex_init(&devlink->reporters_lock);
6205         return devlink;
6206 }
6207 EXPORT_SYMBOL_GPL(devlink_alloc);
6208
6209 /**
6210  *      devlink_register - Register devlink instance
6211  *
6212  *      @devlink: devlink
6213  *      @dev: parent device
6214  */
6215 int devlink_register(struct devlink *devlink, struct device *dev)
6216 {
6217         mutex_lock(&devlink_mutex);
6218         devlink->dev = dev;
6219         list_add_tail(&devlink->list, &devlink_list);
6220         devlink_notify(devlink, DEVLINK_CMD_NEW);
6221         mutex_unlock(&devlink_mutex);
6222         return 0;
6223 }
6224 EXPORT_SYMBOL_GPL(devlink_register);
6225
6226 /**
6227  *      devlink_unregister - Unregister devlink instance
6228  *
6229  *      @devlink: devlink
6230  */
6231 void devlink_unregister(struct devlink *devlink)
6232 {
6233         mutex_lock(&devlink_mutex);
6234         WARN_ON(devlink_reload_supported(devlink) &&
6235                 devlink->reload_enabled);
6236         devlink_notify(devlink, DEVLINK_CMD_DEL);
6237         list_del(&devlink->list);
6238         mutex_unlock(&devlink_mutex);
6239 }
6240 EXPORT_SYMBOL_GPL(devlink_unregister);
6241
6242 /**
6243  *      devlink_reload_enable - Enable reload of devlink instance
6244  *
6245  *      @devlink: devlink
6246  *
6247  *      Should be called at end of device initialization
6248  *      process when reload operation is supported.
6249  */
6250 void devlink_reload_enable(struct devlink *devlink)
6251 {
6252         mutex_lock(&devlink_mutex);
6253         devlink->reload_enabled = true;
6254         mutex_unlock(&devlink_mutex);
6255 }
6256 EXPORT_SYMBOL_GPL(devlink_reload_enable);
6257
6258 /**
6259  *      devlink_reload_disable - Disable reload of devlink instance
6260  *
6261  *      @devlink: devlink
6262  *
6263  *      Should be called at the beginning of device cleanup
6264  *      process when reload operation is supported.
6265  */
6266 void devlink_reload_disable(struct devlink *devlink)
6267 {
6268         mutex_lock(&devlink_mutex);
6269         /* Mutex is taken which ensures that no reload operation is in
6270          * progress while setting up forbidded flag.
6271          */
6272         devlink->reload_enabled = false;
6273         mutex_unlock(&devlink_mutex);
6274 }
6275 EXPORT_SYMBOL_GPL(devlink_reload_disable);
6276
6277 /**
6278  *      devlink_free - Free devlink instance resources
6279  *
6280  *      @devlink: devlink
6281  */
6282 void devlink_free(struct devlink *devlink)
6283 {
6284         mutex_destroy(&devlink->reporters_lock);
6285         mutex_destroy(&devlink->lock);
6286         WARN_ON(!list_empty(&devlink->trap_group_list));
6287         WARN_ON(!list_empty(&devlink->trap_list));
6288         WARN_ON(!list_empty(&devlink->reporter_list));
6289         WARN_ON(!list_empty(&devlink->region_list));
6290         WARN_ON(!list_empty(&devlink->param_list));
6291         WARN_ON(!list_empty(&devlink->resource_list));
6292         WARN_ON(!list_empty(&devlink->dpipe_table_list));
6293         WARN_ON(!list_empty(&devlink->sb_list));
6294         WARN_ON(!list_empty(&devlink->port_list));
6295
6296         kfree(devlink);
6297 }
6298 EXPORT_SYMBOL_GPL(devlink_free);
6299
6300 static void devlink_port_type_warn(struct work_struct *work)
6301 {
6302         WARN(true, "Type was not set for devlink port.");
6303 }
6304
6305 static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
6306 {
6307         /* Ignore CPU and DSA flavours. */
6308         return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
6309                devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
6310 }
6311
6312 #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
6313
6314 static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
6315 {
6316         if (!devlink_port_type_should_warn(devlink_port))
6317                 return;
6318         /* Schedule a work to WARN in case driver does not set port
6319          * type within timeout.
6320          */
6321         schedule_delayed_work(&devlink_port->type_warn_dw,
6322                               DEVLINK_PORT_TYPE_WARN_TIMEOUT);
6323 }
6324
6325 static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
6326 {
6327         if (!devlink_port_type_should_warn(devlink_port))
6328                 return;
6329         cancel_delayed_work_sync(&devlink_port->type_warn_dw);
6330 }
6331
6332 /**
6333  *      devlink_port_register - Register devlink port
6334  *
6335  *      @devlink: devlink
6336  *      @devlink_port: devlink port
6337  *      @port_index: driver-specific numerical identifier of the port
6338  *
6339  *      Register devlink port with provided port index. User can use
6340  *      any indexing, even hw-related one. devlink_port structure
6341  *      is convenient to be embedded inside user driver private structure.
6342  *      Note that the caller should take care of zeroing the devlink_port
6343  *      structure.
6344  */
6345 int devlink_port_register(struct devlink *devlink,
6346                           struct devlink_port *devlink_port,
6347                           unsigned int port_index)
6348 {
6349         mutex_lock(&devlink->lock);
6350         if (devlink_port_index_exists(devlink, port_index)) {
6351                 mutex_unlock(&devlink->lock);
6352                 return -EEXIST;
6353         }
6354         devlink_port->devlink = devlink;
6355         devlink_port->index = port_index;
6356         devlink_port->registered = true;
6357         spin_lock_init(&devlink_port->type_lock);
6358         list_add_tail(&devlink_port->list, &devlink->port_list);
6359         INIT_LIST_HEAD(&devlink_port->param_list);
6360         mutex_unlock(&devlink->lock);
6361         INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
6362         devlink_port_type_warn_schedule(devlink_port);
6363         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6364         return 0;
6365 }
6366 EXPORT_SYMBOL_GPL(devlink_port_register);
6367
6368 /**
6369  *      devlink_port_unregister - Unregister devlink port
6370  *
6371  *      @devlink_port: devlink port
6372  */
6373 void devlink_port_unregister(struct devlink_port *devlink_port)
6374 {
6375         struct devlink *devlink = devlink_port->devlink;
6376
6377         devlink_port_type_warn_cancel(devlink_port);
6378         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
6379         mutex_lock(&devlink->lock);
6380         list_del(&devlink_port->list);
6381         mutex_unlock(&devlink->lock);
6382 }
6383 EXPORT_SYMBOL_GPL(devlink_port_unregister);
6384
6385 static void __devlink_port_type_set(struct devlink_port *devlink_port,
6386                                     enum devlink_port_type type,
6387                                     void *type_dev)
6388 {
6389         if (WARN_ON(!devlink_port->registered))
6390                 return;
6391         devlink_port_type_warn_cancel(devlink_port);
6392         spin_lock_bh(&devlink_port->type_lock);
6393         devlink_port->type = type;
6394         devlink_port->type_dev = type_dev;
6395         spin_unlock_bh(&devlink_port->type_lock);
6396         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6397 }
6398
6399 /**
6400  *      devlink_port_type_eth_set - Set port type to Ethernet
6401  *
6402  *      @devlink_port: devlink port
6403  *      @netdev: related netdevice
6404  */
6405 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
6406                                struct net_device *netdev)
6407 {
6408         const struct net_device_ops *ops = netdev->netdev_ops;
6409
6410         /* If driver registers devlink port, it should set devlink port
6411          * attributes accordingly so the compat functions are called
6412          * and the original ops are not used.
6413          */
6414         if (ops->ndo_get_phys_port_name) {
6415                 /* Some drivers use the same set of ndos for netdevs
6416                  * that have devlink_port registered and also for
6417                  * those who don't. Make sure that ndo_get_phys_port_name
6418                  * returns -EOPNOTSUPP here in case it is defined.
6419                  * Warn if not.
6420                  */
6421                 char name[IFNAMSIZ];
6422                 int err;
6423
6424                 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
6425                 WARN_ON(err != -EOPNOTSUPP);
6426         }
6427         if (ops->ndo_get_port_parent_id) {
6428                 /* Some drivers use the same set of ndos for netdevs
6429                  * that have devlink_port registered and also for
6430                  * those who don't. Make sure that ndo_get_port_parent_id
6431                  * returns -EOPNOTSUPP here in case it is defined.
6432                  * Warn if not.
6433                  */
6434                 struct netdev_phys_item_id ppid;
6435                 int err;
6436
6437                 err = ops->ndo_get_port_parent_id(netdev, &ppid);
6438                 WARN_ON(err != -EOPNOTSUPP);
6439         }
6440         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
6441 }
6442 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
6443
6444 /**
6445  *      devlink_port_type_ib_set - Set port type to InfiniBand
6446  *
6447  *      @devlink_port: devlink port
6448  *      @ibdev: related IB device
6449  */
6450 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
6451                               struct ib_device *ibdev)
6452 {
6453         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
6454 }
6455 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
6456
6457 /**
6458  *      devlink_port_type_clear - Clear port type
6459  *
6460  *      @devlink_port: devlink port
6461  */
6462 void devlink_port_type_clear(struct devlink_port *devlink_port)
6463 {
6464         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
6465         devlink_port_type_warn_schedule(devlink_port);
6466 }
6467 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
6468
6469 static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
6470                                     enum devlink_port_flavour flavour,
6471                                     const unsigned char *switch_id,
6472                                     unsigned char switch_id_len)
6473 {
6474         struct devlink_port_attrs *attrs = &devlink_port->attrs;
6475
6476         if (WARN_ON(devlink_port->registered))
6477                 return -EEXIST;
6478         attrs->set = true;
6479         attrs->flavour = flavour;
6480         if (switch_id) {
6481                 attrs->switch_port = true;
6482                 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
6483                         switch_id_len = MAX_PHYS_ITEM_ID_LEN;
6484                 memcpy(attrs->switch_id.id, switch_id, switch_id_len);
6485                 attrs->switch_id.id_len = switch_id_len;
6486         } else {
6487                 attrs->switch_port = false;
6488         }
6489         return 0;
6490 }
6491
6492 /**
6493  *      devlink_port_attrs_set - Set port attributes
6494  *
6495  *      @devlink_port: devlink port
6496  *      @flavour: flavour of the port
6497  *      @port_number: number of the port that is facing user, for example
6498  *                    the front panel port number
6499  *      @split: indicates if this is split port
6500  *      @split_subport_number: if the port is split, this is the number
6501  *                             of subport.
6502  *      @switch_id: if the port is part of switch, this is buffer with ID,
6503  *                  otwerwise this is NULL
6504  *      @switch_id_len: length of the switch_id buffer
6505  */
6506 void devlink_port_attrs_set(struct devlink_port *devlink_port,
6507                             enum devlink_port_flavour flavour,
6508                             u32 port_number, bool split,
6509                             u32 split_subport_number,
6510                             const unsigned char *switch_id,
6511                             unsigned char switch_id_len)
6512 {
6513         struct devlink_port_attrs *attrs = &devlink_port->attrs;
6514         int ret;
6515
6516         ret = __devlink_port_attrs_set(devlink_port, flavour,
6517                                        switch_id, switch_id_len);
6518         if (ret)
6519                 return;
6520         attrs->split = split;
6521         attrs->phys.port_number = port_number;
6522         attrs->phys.split_subport_number = split_subport_number;
6523 }
6524 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
6525
6526 /**
6527  *      devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
6528  *
6529  *      @devlink_port: devlink port
6530  *      @pf: associated PF for the devlink port instance
6531  *      @switch_id: if the port is part of switch, this is buffer with ID,
6532  *                  otherwise this is NULL
6533  *      @switch_id_len: length of the switch_id buffer
6534  */
6535 void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port,
6536                                    const unsigned char *switch_id,
6537                                    unsigned char switch_id_len, u16 pf)
6538 {
6539         struct devlink_port_attrs *attrs = &devlink_port->attrs;
6540         int ret;
6541
6542         ret = __devlink_port_attrs_set(devlink_port,
6543                                        DEVLINK_PORT_FLAVOUR_PCI_PF,
6544                                        switch_id, switch_id_len);
6545         if (ret)
6546                 return;
6547
6548         attrs->pci_pf.pf = pf;
6549 }
6550 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
6551
6552 /**
6553  *      devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
6554  *
6555  *      @devlink_port: devlink port
6556  *      @pf: associated PF for the devlink port instance
6557  *      @vf: associated VF of a PF for the devlink port instance
6558  *      @switch_id: if the port is part of switch, this is buffer with ID,
6559  *                  otherwise this is NULL
6560  *      @switch_id_len: length of the switch_id buffer
6561  */
6562 void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
6563                                    const unsigned char *switch_id,
6564                                    unsigned char switch_id_len,
6565                                    u16 pf, u16 vf)
6566 {
6567         struct devlink_port_attrs *attrs = &devlink_port->attrs;
6568         int ret;
6569
6570         ret = __devlink_port_attrs_set(devlink_port,
6571                                        DEVLINK_PORT_FLAVOUR_PCI_VF,
6572                                        switch_id, switch_id_len);
6573         if (ret)
6574                 return;
6575         attrs->pci_vf.pf = pf;
6576         attrs->pci_vf.vf = vf;
6577 }
6578 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
6579
6580 static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
6581                                              char *name, size_t len)
6582 {
6583         struct devlink_port_attrs *attrs = &devlink_port->attrs;
6584         int n = 0;
6585
6586         if (!attrs->set)
6587                 return -EOPNOTSUPP;
6588
6589         switch (attrs->flavour) {
6590         case DEVLINK_PORT_FLAVOUR_PHYSICAL:
6591                 if (!attrs->split)
6592                         n = snprintf(name, len, "p%u", attrs->phys.port_number);
6593                 else
6594                         n = snprintf(name, len, "p%us%u",
6595                                      attrs->phys.port_number,
6596                                      attrs->phys.split_subport_number);
6597                 break;
6598         case DEVLINK_PORT_FLAVOUR_CPU:
6599         case DEVLINK_PORT_FLAVOUR_DSA:
6600                 /* As CPU and DSA ports do not have a netdevice associated
6601                  * case should not ever happen.
6602                  */
6603                 WARN_ON(1);
6604                 return -EINVAL;
6605         case DEVLINK_PORT_FLAVOUR_PCI_PF:
6606                 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
6607                 break;
6608         case DEVLINK_PORT_FLAVOUR_PCI_VF:
6609                 n = snprintf(name, len, "pf%uvf%u",
6610                              attrs->pci_vf.pf, attrs->pci_vf.vf);
6611                 break;
6612         }
6613
6614         if (n >= len)
6615                 return -EINVAL;
6616
6617         return 0;
6618 }
6619
6620 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
6621                         u32 size, u16 ingress_pools_count,
6622                         u16 egress_pools_count, u16 ingress_tc_count,
6623                         u16 egress_tc_count)
6624 {
6625         struct devlink_sb *devlink_sb;
6626         int err = 0;
6627
6628         mutex_lock(&devlink->lock);
6629         if (devlink_sb_index_exists(devlink, sb_index)) {
6630                 err = -EEXIST;
6631                 goto unlock;
6632         }
6633
6634         devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
6635         if (!devlink_sb) {
6636                 err = -ENOMEM;
6637                 goto unlock;
6638         }
6639         devlink_sb->index = sb_index;
6640         devlink_sb->size = size;
6641         devlink_sb->ingress_pools_count = ingress_pools_count;
6642         devlink_sb->egress_pools_count = egress_pools_count;
6643         devlink_sb->ingress_tc_count = ingress_tc_count;
6644         devlink_sb->egress_tc_count = egress_tc_count;
6645         list_add_tail(&devlink_sb->list, &devlink->sb_list);
6646 unlock:
6647         mutex_unlock(&devlink->lock);
6648         return err;
6649 }
6650 EXPORT_SYMBOL_GPL(devlink_sb_register);
6651
6652 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
6653 {
6654         struct devlink_sb *devlink_sb;
6655
6656         mutex_lock(&devlink->lock);
6657         devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
6658         WARN_ON(!devlink_sb);
6659         list_del(&devlink_sb->list);
6660         mutex_unlock(&devlink->lock);
6661         kfree(devlink_sb);
6662 }
6663 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
6664
6665 /**
6666  *      devlink_dpipe_headers_register - register dpipe headers
6667  *
6668  *      @devlink: devlink
6669  *      @dpipe_headers: dpipe header array
6670  *
6671  *      Register the headers supported by hardware.
6672  */
6673 int devlink_dpipe_headers_register(struct devlink *devlink,
6674                                    struct devlink_dpipe_headers *dpipe_headers)
6675 {
6676         mutex_lock(&devlink->lock);
6677         devlink->dpipe_headers = dpipe_headers;
6678         mutex_unlock(&devlink->lock);
6679         return 0;
6680 }
6681 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
6682
6683 /**
6684  *      devlink_dpipe_headers_unregister - unregister dpipe headers
6685  *
6686  *      @devlink: devlink
6687  *
6688  *      Unregister the headers supported by hardware.
6689  */
6690 void devlink_dpipe_headers_unregister(struct devlink *devlink)
6691 {
6692         mutex_lock(&devlink->lock);
6693         devlink->dpipe_headers = NULL;
6694         mutex_unlock(&devlink->lock);
6695 }
6696 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
6697
6698 /**
6699  *      devlink_dpipe_table_counter_enabled - check if counter allocation
6700  *                                            required
6701  *      @devlink: devlink
6702  *      @table_name: tables name
6703  *
6704  *      Used by driver to check if counter allocation is required.
6705  *      After counter allocation is turned on the table entries
6706  *      are updated to include counter statistics.
6707  *
6708  *      After that point on the driver must respect the counter
6709  *      state so that each entry added to the table is added
6710  *      with a counter.
6711  */
6712 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
6713                                          const char *table_name)
6714 {
6715         struct devlink_dpipe_table *table;
6716         bool enabled;
6717
6718         rcu_read_lock();
6719         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6720                                          table_name);
6721         enabled = false;
6722         if (table)
6723                 enabled = table->counters_enabled;
6724         rcu_read_unlock();
6725         return enabled;
6726 }
6727 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
6728
6729 /**
6730  *      devlink_dpipe_table_register - register dpipe table
6731  *
6732  *      @devlink: devlink
6733  *      @table_name: table name
6734  *      @table_ops: table ops
6735  *      @priv: priv
6736  *      @counter_control_extern: external control for counters
6737  */
6738 int devlink_dpipe_table_register(struct devlink *devlink,
6739                                  const char *table_name,
6740                                  struct devlink_dpipe_table_ops *table_ops,
6741                                  void *priv, bool counter_control_extern)
6742 {
6743         struct devlink_dpipe_table *table;
6744
6745         if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
6746                 return -EEXIST;
6747
6748         if (WARN_ON(!table_ops->size_get))
6749                 return -EINVAL;
6750
6751         table = kzalloc(sizeof(*table), GFP_KERNEL);
6752         if (!table)
6753                 return -ENOMEM;
6754
6755         table->name = table_name;
6756         table->table_ops = table_ops;
6757         table->priv = priv;
6758         table->counter_control_extern = counter_control_extern;
6759
6760         mutex_lock(&devlink->lock);
6761         list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
6762         mutex_unlock(&devlink->lock);
6763         return 0;
6764 }
6765 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
6766
6767 /**
6768  *      devlink_dpipe_table_unregister - unregister dpipe table
6769  *
6770  *      @devlink: devlink
6771  *      @table_name: table name
6772  */
6773 void devlink_dpipe_table_unregister(struct devlink *devlink,
6774                                     const char *table_name)
6775 {
6776         struct devlink_dpipe_table *table;
6777
6778         mutex_lock(&devlink->lock);
6779         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6780                                          table_name);
6781         if (!table)
6782                 goto unlock;
6783         list_del_rcu(&table->list);
6784         mutex_unlock(&devlink->lock);
6785         kfree_rcu(table, rcu);
6786         return;
6787 unlock:
6788         mutex_unlock(&devlink->lock);
6789 }
6790 EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
6791
6792 /**
6793  *      devlink_resource_register - devlink resource register
6794  *
6795  *      @devlink: devlink
6796  *      @resource_name: resource's name
6797  *      @resource_size: resource's size
6798  *      @resource_id: resource's id
6799  *      @parent_resource_id: resource's parent id
6800  *      @size_params: size parameters
6801  */
6802 int devlink_resource_register(struct devlink *devlink,
6803                               const char *resource_name,
6804                               u64 resource_size,
6805                               u64 resource_id,
6806                               u64 parent_resource_id,
6807                               const struct devlink_resource_size_params *size_params)
6808 {
6809         struct devlink_resource *resource;
6810         struct list_head *resource_list;
6811         bool top_hierarchy;
6812         int err = 0;
6813
6814         top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
6815
6816         mutex_lock(&devlink->lock);
6817         resource = devlink_resource_find(devlink, NULL, resource_id);
6818         if (resource) {
6819                 err = -EINVAL;
6820                 goto out;
6821         }
6822
6823         resource = kzalloc(sizeof(*resource), GFP_KERNEL);
6824         if (!resource) {
6825                 err = -ENOMEM;
6826                 goto out;
6827         }
6828
6829         if (top_hierarchy) {
6830                 resource_list = &devlink->resource_list;
6831         } else {
6832                 struct devlink_resource *parent_resource;
6833
6834                 parent_resource = devlink_resource_find(devlink, NULL,
6835                                                         parent_resource_id);
6836                 if (parent_resource) {
6837                         resource_list = &parent_resource->resource_list;
6838                         resource->parent = parent_resource;
6839                 } else {
6840                         kfree(resource);
6841                         err = -EINVAL;
6842                         goto out;
6843                 }
6844         }
6845
6846         resource->name = resource_name;
6847         resource->size = resource_size;
6848         resource->size_new = resource_size;
6849         resource->id = resource_id;
6850         resource->size_valid = true;
6851         memcpy(&resource->size_params, size_params,
6852                sizeof(resource->size_params));
6853         INIT_LIST_HEAD(&resource->resource_list);
6854         list_add_tail(&resource->list, resource_list);
6855 out:
6856         mutex_unlock(&devlink->lock);
6857         return err;
6858 }
6859 EXPORT_SYMBOL_GPL(devlink_resource_register);
6860
6861 /**
6862  *      devlink_resources_unregister - free all resources
6863  *
6864  *      @devlink: devlink
6865  *      @resource: resource
6866  */
6867 void devlink_resources_unregister(struct devlink *devlink,
6868                                   struct devlink_resource *resource)
6869 {
6870         struct devlink_resource *tmp, *child_resource;
6871         struct list_head *resource_list;
6872
6873         if (resource)
6874                 resource_list = &resource->resource_list;
6875         else
6876                 resource_list = &devlink->resource_list;
6877
6878         if (!resource)
6879                 mutex_lock(&devlink->lock);
6880
6881         list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
6882                 devlink_resources_unregister(devlink, child_resource);
6883                 list_del(&child_resource->list);
6884                 kfree(child_resource);
6885         }
6886
6887         if (!resource)
6888                 mutex_unlock(&devlink->lock);
6889 }
6890 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
6891
6892 /**
6893  *      devlink_resource_size_get - get and update size
6894  *
6895  *      @devlink: devlink
6896  *      @resource_id: the requested resource id
6897  *      @p_resource_size: ptr to update
6898  */
6899 int devlink_resource_size_get(struct devlink *devlink,
6900                               u64 resource_id,
6901                               u64 *p_resource_size)
6902 {
6903         struct devlink_resource *resource;
6904         int err = 0;
6905
6906         mutex_lock(&devlink->lock);
6907         resource = devlink_resource_find(devlink, NULL, resource_id);
6908         if (!resource) {
6909                 err = -EINVAL;
6910                 goto out;
6911         }
6912         *p_resource_size = resource->size_new;
6913         resource->size = resource->size_new;
6914 out:
6915         mutex_unlock(&devlink->lock);
6916         return err;
6917 }
6918 EXPORT_SYMBOL_GPL(devlink_resource_size_get);
6919
6920 /**
6921  *      devlink_dpipe_table_resource_set - set the resource id
6922  *
6923  *      @devlink: devlink
6924  *      @table_name: table name
6925  *      @resource_id: resource id
6926  *      @resource_units: number of resource's units consumed per table's entry
6927  */
6928 int devlink_dpipe_table_resource_set(struct devlink *devlink,
6929                                      const char *table_name, u64 resource_id,
6930                                      u64 resource_units)
6931 {
6932         struct devlink_dpipe_table *table;
6933         int err = 0;
6934
6935         mutex_lock(&devlink->lock);
6936         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6937                                          table_name);
6938         if (!table) {
6939                 err = -EINVAL;
6940                 goto out;
6941         }
6942         table->resource_id = resource_id;
6943         table->resource_units = resource_units;
6944         table->resource_valid = true;
6945 out:
6946         mutex_unlock(&devlink->lock);
6947         return err;
6948 }
6949 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
6950
6951 /**
6952  *      devlink_resource_occ_get_register - register occupancy getter
6953  *
6954  *      @devlink: devlink
6955  *      @resource_id: resource id
6956  *      @occ_get: occupancy getter callback
6957  *      @occ_get_priv: occupancy getter callback priv
6958  */
6959 void devlink_resource_occ_get_register(struct devlink *devlink,
6960                                        u64 resource_id,
6961                                        devlink_resource_occ_get_t *occ_get,
6962                                        void *occ_get_priv)
6963 {
6964         struct devlink_resource *resource;
6965
6966         mutex_lock(&devlink->lock);
6967         resource = devlink_resource_find(devlink, NULL, resource_id);
6968         if (WARN_ON(!resource))
6969                 goto out;
6970         WARN_ON(resource->occ_get);
6971
6972         resource->occ_get = occ_get;
6973         resource->occ_get_priv = occ_get_priv;
6974 out:
6975         mutex_unlock(&devlink->lock);
6976 }
6977 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
6978
6979 /**
6980  *      devlink_resource_occ_get_unregister - unregister occupancy getter
6981  *
6982  *      @devlink: devlink
6983  *      @resource_id: resource id
6984  */
6985 void devlink_resource_occ_get_unregister(struct devlink *devlink,
6986                                          u64 resource_id)
6987 {
6988         struct devlink_resource *resource;
6989
6990         mutex_lock(&devlink->lock);
6991         resource = devlink_resource_find(devlink, NULL, resource_id);
6992         if (WARN_ON(!resource))
6993                 goto out;
6994         WARN_ON(!resource->occ_get);
6995
6996         resource->occ_get = NULL;
6997         resource->occ_get_priv = NULL;
6998 out:
6999         mutex_unlock(&devlink->lock);
7000 }
7001 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
7002
7003 static int devlink_param_verify(const struct devlink_param *param)
7004 {
7005         if (!param || !param->name || !param->supported_cmodes)
7006                 return -EINVAL;
7007         if (param->generic)
7008                 return devlink_param_generic_verify(param);
7009         else
7010                 return devlink_param_driver_verify(param);
7011 }
7012
7013 static int __devlink_params_register(struct devlink *devlink,
7014                                      unsigned int port_index,
7015                                      struct list_head *param_list,
7016                                      const struct devlink_param *params,
7017                                      size_t params_count,
7018                                      enum devlink_command reg_cmd,
7019                                      enum devlink_command unreg_cmd)
7020 {
7021         const struct devlink_param *param = params;
7022         int i;
7023         int err;
7024
7025         mutex_lock(&devlink->lock);
7026         for (i = 0; i < params_count; i++, param++) {
7027                 err = devlink_param_verify(param);
7028                 if (err)
7029                         goto rollback;
7030
7031                 err = devlink_param_register_one(devlink, port_index,
7032                                                  param_list, param, reg_cmd);
7033                 if (err)
7034                         goto rollback;
7035         }
7036
7037         mutex_unlock(&devlink->lock);
7038         return 0;
7039
7040 rollback:
7041         if (!i)
7042                 goto unlock;
7043         for (param--; i > 0; i--, param--)
7044                 devlink_param_unregister_one(devlink, port_index, param_list,
7045                                              param, unreg_cmd);
7046 unlock:
7047         mutex_unlock(&devlink->lock);
7048         return err;
7049 }
7050
7051 static void __devlink_params_unregister(struct devlink *devlink,
7052                                         unsigned int port_index,
7053                                         struct list_head *param_list,
7054                                         const struct devlink_param *params,
7055                                         size_t params_count,
7056                                         enum devlink_command cmd)
7057 {
7058         const struct devlink_param *param = params;
7059         int i;
7060
7061         mutex_lock(&devlink->lock);
7062         for (i = 0; i < params_count; i++, param++)
7063                 devlink_param_unregister_one(devlink, 0, param_list, param,
7064                                              cmd);
7065         mutex_unlock(&devlink->lock);
7066 }
7067
7068 /**
7069  *      devlink_params_register - register configuration parameters
7070  *
7071  *      @devlink: devlink
7072  *      @params: configuration parameters array
7073  *      @params_count: number of parameters provided
7074  *
7075  *      Register the configuration parameters supported by the driver.
7076  */
7077 int devlink_params_register(struct devlink *devlink,
7078                             const struct devlink_param *params,
7079                             size_t params_count)
7080 {
7081         return __devlink_params_register(devlink, 0, &devlink->param_list,
7082                                          params, params_count,
7083                                          DEVLINK_CMD_PARAM_NEW,
7084                                          DEVLINK_CMD_PARAM_DEL);
7085 }
7086 EXPORT_SYMBOL_GPL(devlink_params_register);
7087
7088 /**
7089  *      devlink_params_unregister - unregister configuration parameters
7090  *      @devlink: devlink
7091  *      @params: configuration parameters to unregister
7092  *      @params_count: number of parameters provided
7093  */
7094 void devlink_params_unregister(struct devlink *devlink,
7095                                const struct devlink_param *params,
7096                                size_t params_count)
7097 {
7098         return __devlink_params_unregister(devlink, 0, &devlink->param_list,
7099                                            params, params_count,
7100                                            DEVLINK_CMD_PARAM_DEL);
7101 }
7102 EXPORT_SYMBOL_GPL(devlink_params_unregister);
7103
7104 /**
7105  *      devlink_params_publish - publish configuration parameters
7106  *
7107  *      @devlink: devlink
7108  *
7109  *      Publish previously registered configuration parameters.
7110  */
7111 void devlink_params_publish(struct devlink *devlink)
7112 {
7113         struct devlink_param_item *param_item;
7114
7115         list_for_each_entry(param_item, &devlink->param_list, list) {
7116                 if (param_item->published)
7117                         continue;
7118                 param_item->published = true;
7119                 devlink_param_notify(devlink, 0, param_item,
7120                                      DEVLINK_CMD_PARAM_NEW);
7121         }
7122 }
7123 EXPORT_SYMBOL_GPL(devlink_params_publish);
7124
7125 /**
7126  *      devlink_params_unpublish - unpublish configuration parameters
7127  *
7128  *      @devlink: devlink
7129  *
7130  *      Unpublish previously registered configuration parameters.
7131  */
7132 void devlink_params_unpublish(struct devlink *devlink)
7133 {
7134         struct devlink_param_item *param_item;
7135
7136         list_for_each_entry(param_item, &devlink->param_list, list) {
7137                 if (!param_item->published)
7138                         continue;
7139                 param_item->published = false;
7140                 devlink_param_notify(devlink, 0, param_item,
7141                                      DEVLINK_CMD_PARAM_DEL);
7142         }
7143 }
7144 EXPORT_SYMBOL_GPL(devlink_params_unpublish);
7145
7146 /**
7147  *      devlink_port_params_register - register port configuration parameters
7148  *
7149  *      @devlink_port: devlink port
7150  *      @params: configuration parameters array
7151  *      @params_count: number of parameters provided
7152  *
7153  *      Register the configuration parameters supported by the port.
7154  */
7155 int devlink_port_params_register(struct devlink_port *devlink_port,
7156                                  const struct devlink_param *params,
7157                                  size_t params_count)
7158 {
7159         return __devlink_params_register(devlink_port->devlink,
7160                                          devlink_port->index,
7161                                          &devlink_port->param_list, params,
7162                                          params_count,
7163                                          DEVLINK_CMD_PORT_PARAM_NEW,
7164                                          DEVLINK_CMD_PORT_PARAM_DEL);
7165 }
7166 EXPORT_SYMBOL_GPL(devlink_port_params_register);
7167
7168 /**
7169  *      devlink_port_params_unregister - unregister port configuration
7170  *      parameters
7171  *
7172  *      @devlink_port: devlink port
7173  *      @params: configuration parameters array
7174  *      @params_count: number of parameters provided
7175  */
7176 void devlink_port_params_unregister(struct devlink_port *devlink_port,
7177                                     const struct devlink_param *params,
7178                                     size_t params_count)
7179 {
7180         return __devlink_params_unregister(devlink_port->devlink,
7181                                            devlink_port->index,
7182                                            &devlink_port->param_list,
7183                                            params, params_count,
7184                                            DEVLINK_CMD_PORT_PARAM_DEL);
7185 }
7186 EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
7187
7188 static int
7189 __devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
7190                                      union devlink_param_value *init_val)
7191 {
7192         struct devlink_param_item *param_item;
7193
7194         param_item = devlink_param_find_by_id(param_list, param_id);
7195         if (!param_item)
7196                 return -EINVAL;
7197
7198         if (!param_item->driverinit_value_valid ||
7199             !devlink_param_cmode_is_supported(param_item->param,
7200                                               DEVLINK_PARAM_CMODE_DRIVERINIT))
7201                 return -EOPNOTSUPP;
7202
7203         if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7204                 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
7205         else
7206                 *init_val = param_item->driverinit_value;
7207
7208         return 0;
7209 }
7210
7211 static int
7212 __devlink_param_driverinit_value_set(struct devlink *devlink,
7213                                      unsigned int port_index,
7214                                      struct list_head *param_list, u32 param_id,
7215                                      union devlink_param_value init_val,
7216                                      enum devlink_command cmd)
7217 {
7218         struct devlink_param_item *param_item;
7219
7220         param_item = devlink_param_find_by_id(param_list, param_id);
7221         if (!param_item)
7222                 return -EINVAL;
7223
7224         if (!devlink_param_cmode_is_supported(param_item->param,
7225                                               DEVLINK_PARAM_CMODE_DRIVERINIT))
7226                 return -EOPNOTSUPP;
7227
7228         if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7229                 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
7230         else
7231                 param_item->driverinit_value = init_val;
7232         param_item->driverinit_value_valid = true;
7233
7234         devlink_param_notify(devlink, port_index, param_item, cmd);
7235         return 0;
7236 }
7237
7238 /**
7239  *      devlink_param_driverinit_value_get - get configuration parameter
7240  *                                           value for driver initializing
7241  *
7242  *      @devlink: devlink
7243  *      @param_id: parameter ID
7244  *      @init_val: value of parameter in driverinit configuration mode
7245  *
7246  *      This function should be used by the driver to get driverinit
7247  *      configuration for initialization after reload command.
7248  */
7249 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
7250                                        union devlink_param_value *init_val)
7251 {
7252         if (!devlink_reload_supported(devlink))
7253                 return -EOPNOTSUPP;
7254
7255         return __devlink_param_driverinit_value_get(&devlink->param_list,
7256                                                     param_id, init_val);
7257 }
7258 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
7259
7260 /**
7261  *      devlink_param_driverinit_value_set - set value of configuration
7262  *                                           parameter for driverinit
7263  *                                           configuration mode
7264  *
7265  *      @devlink: devlink
7266  *      @param_id: parameter ID
7267  *      @init_val: value of parameter to set for driverinit configuration mode
7268  *
7269  *      This function should be used by the driver to set driverinit
7270  *      configuration mode default value.
7271  */
7272 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
7273                                        union devlink_param_value init_val)
7274 {
7275         return __devlink_param_driverinit_value_set(devlink, 0,
7276                                                     &devlink->param_list,
7277                                                     param_id, init_val,
7278                                                     DEVLINK_CMD_PARAM_NEW);
7279 }
7280 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
7281
7282 /**
7283  *      devlink_port_param_driverinit_value_get - get configuration parameter
7284  *                                              value for driver initializing
7285  *
7286  *      @devlink_port: devlink_port
7287  *      @param_id: parameter ID
7288  *      @init_val: value of parameter in driverinit configuration mode
7289  *
7290  *      This function should be used by the driver to get driverinit
7291  *      configuration for initialization after reload command.
7292  */
7293 int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
7294                                             u32 param_id,
7295                                             union devlink_param_value *init_val)
7296 {
7297         struct devlink *devlink = devlink_port->devlink;
7298
7299         if (!devlink_reload_supported(devlink))
7300                 return -EOPNOTSUPP;
7301
7302         return __devlink_param_driverinit_value_get(&devlink_port->param_list,
7303                                                     param_id, init_val);
7304 }
7305 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
7306
7307 /**
7308  *     devlink_port_param_driverinit_value_set - set value of configuration
7309  *                                               parameter for driverinit
7310  *                                               configuration mode
7311  *
7312  *     @devlink_port: devlink_port
7313  *     @param_id: parameter ID
7314  *     @init_val: value of parameter to set for driverinit configuration mode
7315  *
7316  *     This function should be used by the driver to set driverinit
7317  *     configuration mode default value.
7318  */
7319 int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
7320                                             u32 param_id,
7321                                             union devlink_param_value init_val)
7322 {
7323         return __devlink_param_driverinit_value_set(devlink_port->devlink,
7324                                                     devlink_port->index,
7325                                                     &devlink_port->param_list,
7326                                                     param_id, init_val,
7327                                                     DEVLINK_CMD_PORT_PARAM_NEW);
7328 }
7329 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
7330
7331 /**
7332  *      devlink_param_value_changed - notify devlink on a parameter's value
7333  *                                    change. Should be called by the driver
7334  *                                    right after the change.
7335  *
7336  *      @devlink: devlink
7337  *      @param_id: parameter ID
7338  *
7339  *      This function should be used by the driver to notify devlink on value
7340  *      change, excluding driverinit configuration mode.
7341  *      For driverinit configuration mode driver should use the function
7342  */
7343 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
7344 {
7345         struct devlink_param_item *param_item;
7346
7347         param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
7348         WARN_ON(!param_item);
7349
7350         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
7351 }
7352 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
7353
7354 /**
7355  *     devlink_port_param_value_changed - notify devlink on a parameter's value
7356  *                                      change. Should be called by the driver
7357  *                                      right after the change.
7358  *
7359  *     @devlink_port: devlink_port
7360  *     @param_id: parameter ID
7361  *
7362  *     This function should be used by the driver to notify devlink on value
7363  *     change, excluding driverinit configuration mode.
7364  *     For driverinit configuration mode driver should use the function
7365  *     devlink_port_param_driverinit_value_set() instead.
7366  */
7367 void devlink_port_param_value_changed(struct devlink_port *devlink_port,
7368                                       u32 param_id)
7369 {
7370         struct devlink_param_item *param_item;
7371
7372         param_item = devlink_param_find_by_id(&devlink_port->param_list,
7373                                               param_id);
7374         WARN_ON(!param_item);
7375
7376         devlink_param_notify(devlink_port->devlink, devlink_port->index,
7377                              param_item, DEVLINK_CMD_PORT_PARAM_NEW);
7378 }
7379 EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
7380
7381 /**
7382  *      devlink_param_value_str_fill - Safely fill-up the string preventing
7383  *                                     from overflow of the preallocated buffer
7384  *
7385  *      @dst_val: destination devlink_param_value
7386  *      @src: source buffer
7387  */
7388 void devlink_param_value_str_fill(union devlink_param_value *dst_val,
7389                                   const char *src)
7390 {
7391         size_t len;
7392
7393         len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
7394         WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
7395 }
7396 EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
7397
7398 /**
7399  *      devlink_region_create - create a new address region
7400  *
7401  *      @devlink: devlink
7402  *      @region_name: region name
7403  *      @region_max_snapshots: Maximum supported number of snapshots for region
7404  *      @region_size: size of region
7405  */
7406 struct devlink_region *devlink_region_create(struct devlink *devlink,
7407                                              const char *region_name,
7408                                              u32 region_max_snapshots,
7409                                              u64 region_size)
7410 {
7411         struct devlink_region *region;
7412         int err = 0;
7413
7414         mutex_lock(&devlink->lock);
7415
7416         if (devlink_region_get_by_name(devlink, region_name)) {
7417                 err = -EEXIST;
7418                 goto unlock;
7419         }
7420
7421         region = kzalloc(sizeof(*region), GFP_KERNEL);
7422         if (!region) {
7423                 err = -ENOMEM;
7424                 goto unlock;
7425         }
7426
7427         region->devlink = devlink;
7428         region->max_snapshots = region_max_snapshots;
7429         region->name = region_name;
7430         region->size = region_size;
7431         INIT_LIST_HEAD(&region->snapshot_list);
7432         list_add_tail(&region->list, &devlink->region_list);
7433         devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
7434
7435         mutex_unlock(&devlink->lock);
7436         return region;
7437
7438 unlock:
7439         mutex_unlock(&devlink->lock);
7440         return ERR_PTR(err);
7441 }
7442 EXPORT_SYMBOL_GPL(devlink_region_create);
7443
7444 /**
7445  *      devlink_region_destroy - destroy address region
7446  *
7447  *      @region: devlink region to destroy
7448  */
7449 void devlink_region_destroy(struct devlink_region *region)
7450 {
7451         struct devlink *devlink = region->devlink;
7452         struct devlink_snapshot *snapshot, *ts;
7453
7454         mutex_lock(&devlink->lock);
7455
7456         /* Free all snapshots of region */
7457         list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
7458                 devlink_region_snapshot_del(region, snapshot);
7459
7460         list_del(&region->list);
7461
7462         devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
7463         mutex_unlock(&devlink->lock);
7464         kfree(region);
7465 }
7466 EXPORT_SYMBOL_GPL(devlink_region_destroy);
7467
7468 /**
7469  *      devlink_region_shapshot_id_get - get snapshot ID
7470  *
7471  *      This callback should be called when adding a new snapshot,
7472  *      Driver should use the same id for multiple snapshots taken
7473  *      on multiple regions at the same time/by the same trigger.
7474  *
7475  *      @devlink: devlink
7476  */
7477 u32 devlink_region_shapshot_id_get(struct devlink *devlink)
7478 {
7479         u32 id;
7480
7481         mutex_lock(&devlink->lock);
7482         id = ++devlink->snapshot_id;
7483         mutex_unlock(&devlink->lock);
7484
7485         return id;
7486 }
7487 EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
7488
7489 /**
7490  *      devlink_region_snapshot_create - create a new snapshot
7491  *      This will add a new snapshot of a region. The snapshot
7492  *      will be stored on the region struct and can be accessed
7493  *      from devlink. This is useful for future analyses of snapshots.
7494  *      Multiple snapshots can be created on a region.
7495  *      The @snapshot_id should be obtained using the getter function.
7496  *
7497  *      @region: devlink region of the snapshot
7498  *      @data: snapshot data
7499  *      @snapshot_id: snapshot id to be created
7500  *      @data_destructor: pointer to destructor function to free data
7501  */
7502 int devlink_region_snapshot_create(struct devlink_region *region,
7503                                    u8 *data, u32 snapshot_id,
7504                                    devlink_snapshot_data_dest_t *data_destructor)
7505 {
7506         struct devlink *devlink = region->devlink;
7507         struct devlink_snapshot *snapshot;
7508         int err;
7509
7510         mutex_lock(&devlink->lock);
7511
7512         /* check if region can hold one more snapshot */
7513         if (region->cur_snapshots == region->max_snapshots) {
7514                 err = -ENOMEM;
7515                 goto unlock;
7516         }
7517
7518         if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
7519                 err = -EEXIST;
7520                 goto unlock;
7521         }
7522
7523         snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
7524         if (!snapshot) {
7525                 err = -ENOMEM;
7526                 goto unlock;
7527         }
7528
7529         snapshot->id = snapshot_id;
7530         snapshot->region = region;
7531         snapshot->data = data;
7532         snapshot->data_destructor = data_destructor;
7533
7534         list_add_tail(&snapshot->list, &region->snapshot_list);
7535
7536         region->cur_snapshots++;
7537
7538         devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
7539         mutex_unlock(&devlink->lock);
7540         return 0;
7541
7542 unlock:
7543         mutex_unlock(&devlink->lock);
7544         return err;
7545 }
7546 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
7547
7548 #define DEVLINK_TRAP(_id, _type)                                              \
7549         {                                                                     \
7550                 .type = DEVLINK_TRAP_TYPE_##_type,                            \
7551                 .id = DEVLINK_TRAP_GENERIC_ID_##_id,                          \
7552                 .name = DEVLINK_TRAP_GENERIC_NAME_##_id,                      \
7553         }
7554
7555 static const struct devlink_trap devlink_trap_generic[] = {
7556         DEVLINK_TRAP(SMAC_MC, DROP),
7557         DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
7558         DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
7559         DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
7560         DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
7561         DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
7562         DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
7563         DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
7564         DEVLINK_TRAP(TAIL_DROP, DROP),
7565 };
7566
7567 #define DEVLINK_TRAP_GROUP(_id)                                               \
7568         {                                                                     \
7569                 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id,                    \
7570                 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id,                \
7571         }
7572
7573 static const struct devlink_trap_group devlink_trap_group_generic[] = {
7574         DEVLINK_TRAP_GROUP(L2_DROPS),
7575         DEVLINK_TRAP_GROUP(L3_DROPS),
7576         DEVLINK_TRAP_GROUP(BUFFER_DROPS),
7577 };
7578
7579 static int devlink_trap_generic_verify(const struct devlink_trap *trap)
7580 {
7581         if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
7582                 return -EINVAL;
7583
7584         if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
7585                 return -EINVAL;
7586
7587         if (trap->type != devlink_trap_generic[trap->id].type)
7588                 return -EINVAL;
7589
7590         return 0;
7591 }
7592
7593 static int devlink_trap_driver_verify(const struct devlink_trap *trap)
7594 {
7595         int i;
7596
7597         if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
7598                 return -EINVAL;
7599
7600         for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
7601                 if (!strcmp(trap->name, devlink_trap_generic[i].name))
7602                         return -EEXIST;
7603         }
7604
7605         return 0;
7606 }
7607
7608 static int devlink_trap_verify(const struct devlink_trap *trap)
7609 {
7610         if (!trap || !trap->name || !trap->group.name)
7611                 return -EINVAL;
7612
7613         if (trap->generic)
7614                 return devlink_trap_generic_verify(trap);
7615         else
7616                 return devlink_trap_driver_verify(trap);
7617 }
7618
7619 static int
7620 devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
7621 {
7622         if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7623                 return -EINVAL;
7624
7625         if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
7626                 return -EINVAL;
7627
7628         return 0;
7629 }
7630
7631 static int
7632 devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
7633 {
7634         int i;
7635
7636         if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7637                 return -EINVAL;
7638
7639         for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
7640                 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
7641                         return -EEXIST;
7642         }
7643
7644         return 0;
7645 }
7646
7647 static int devlink_trap_group_verify(const struct devlink_trap_group *group)
7648 {
7649         if (group->generic)
7650                 return devlink_trap_group_generic_verify(group);
7651         else
7652                 return devlink_trap_group_driver_verify(group);
7653 }
7654
7655 static void
7656 devlink_trap_group_notify(struct devlink *devlink,
7657                           const struct devlink_trap_group_item *group_item,
7658                           enum devlink_command cmd)
7659 {
7660         struct sk_buff *msg;
7661         int err;
7662
7663         WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
7664                      cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
7665
7666         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7667         if (!msg)
7668                 return;
7669
7670         err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
7671                                          0);
7672         if (err) {
7673                 nlmsg_free(msg);
7674                 return;
7675         }
7676
7677         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7678                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7679 }
7680
7681 static struct devlink_trap_group_item *
7682 devlink_trap_group_item_create(struct devlink *devlink,
7683                                const struct devlink_trap_group *group)
7684 {
7685         struct devlink_trap_group_item *group_item;
7686         int err;
7687
7688         err = devlink_trap_group_verify(group);
7689         if (err)
7690                 return ERR_PTR(err);
7691
7692         group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
7693         if (!group_item)
7694                 return ERR_PTR(-ENOMEM);
7695
7696         group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7697         if (!group_item->stats) {
7698                 err = -ENOMEM;
7699                 goto err_stats_alloc;
7700         }
7701
7702         group_item->group = group;
7703         refcount_set(&group_item->refcount, 1);
7704
7705         if (devlink->ops->trap_group_init) {
7706                 err = devlink->ops->trap_group_init(devlink, group);
7707                 if (err)
7708                         goto err_group_init;
7709         }
7710
7711         list_add_tail(&group_item->list, &devlink->trap_group_list);
7712         devlink_trap_group_notify(devlink, group_item,
7713                                   DEVLINK_CMD_TRAP_GROUP_NEW);
7714
7715         return group_item;
7716
7717 err_group_init:
7718         free_percpu(group_item->stats);
7719 err_stats_alloc:
7720         kfree(group_item);
7721         return ERR_PTR(err);
7722 }
7723
7724 static void
7725 devlink_trap_group_item_destroy(struct devlink *devlink,
7726                                 struct devlink_trap_group_item *group_item)
7727 {
7728         devlink_trap_group_notify(devlink, group_item,
7729                                   DEVLINK_CMD_TRAP_GROUP_DEL);
7730         list_del(&group_item->list);
7731         free_percpu(group_item->stats);
7732         kfree(group_item);
7733 }
7734
7735 static struct devlink_trap_group_item *
7736 devlink_trap_group_item_get(struct devlink *devlink,
7737                             const struct devlink_trap_group *group)
7738 {
7739         struct devlink_trap_group_item *group_item;
7740
7741         group_item = devlink_trap_group_item_lookup(devlink, group->name);
7742         if (group_item) {
7743                 refcount_inc(&group_item->refcount);
7744                 return group_item;
7745         }
7746
7747         return devlink_trap_group_item_create(devlink, group);
7748 }
7749
7750 static void
7751 devlink_trap_group_item_put(struct devlink *devlink,
7752                             struct devlink_trap_group_item *group_item)
7753 {
7754         if (!refcount_dec_and_test(&group_item->refcount))
7755                 return;
7756
7757         devlink_trap_group_item_destroy(devlink, group_item);
7758 }
7759
7760 static int
7761 devlink_trap_item_group_link(struct devlink *devlink,
7762                              struct devlink_trap_item *trap_item)
7763 {
7764         struct devlink_trap_group_item *group_item;
7765
7766         group_item = devlink_trap_group_item_get(devlink,
7767                                                  &trap_item->trap->group);
7768         if (IS_ERR(group_item))
7769                 return PTR_ERR(group_item);
7770
7771         trap_item->group_item = group_item;
7772
7773         return 0;
7774 }
7775
7776 static void
7777 devlink_trap_item_group_unlink(struct devlink *devlink,
7778                                struct devlink_trap_item *trap_item)
7779 {
7780         devlink_trap_group_item_put(devlink, trap_item->group_item);
7781 }
7782
7783 static void devlink_trap_notify(struct devlink *devlink,
7784                                 const struct devlink_trap_item *trap_item,
7785                                 enum devlink_command cmd)
7786 {
7787         struct sk_buff *msg;
7788         int err;
7789
7790         WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
7791                      cmd != DEVLINK_CMD_TRAP_DEL);
7792
7793         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7794         if (!msg)
7795                 return;
7796
7797         err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
7798         if (err) {
7799                 nlmsg_free(msg);
7800                 return;
7801         }
7802
7803         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7804                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7805 }
7806
7807 static int
7808 devlink_trap_register(struct devlink *devlink,
7809                       const struct devlink_trap *trap, void *priv)
7810 {
7811         struct devlink_trap_item *trap_item;
7812         int err;
7813
7814         if (devlink_trap_item_lookup(devlink, trap->name))
7815                 return -EEXIST;
7816
7817         trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
7818         if (!trap_item)
7819                 return -ENOMEM;
7820
7821         trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7822         if (!trap_item->stats) {
7823                 err = -ENOMEM;
7824                 goto err_stats_alloc;
7825         }
7826
7827         trap_item->trap = trap;
7828         trap_item->action = trap->init_action;
7829         trap_item->priv = priv;
7830
7831         err = devlink_trap_item_group_link(devlink, trap_item);
7832         if (err)
7833                 goto err_group_link;
7834
7835         err = devlink->ops->trap_init(devlink, trap, trap_item);
7836         if (err)
7837                 goto err_trap_init;
7838
7839         list_add_tail(&trap_item->list, &devlink->trap_list);
7840         devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
7841
7842         return 0;
7843
7844 err_trap_init:
7845         devlink_trap_item_group_unlink(devlink, trap_item);
7846 err_group_link:
7847         free_percpu(trap_item->stats);
7848 err_stats_alloc:
7849         kfree(trap_item);
7850         return err;
7851 }
7852
7853 static void devlink_trap_unregister(struct devlink *devlink,
7854                                     const struct devlink_trap *trap)
7855 {
7856         struct devlink_trap_item *trap_item;
7857
7858         trap_item = devlink_trap_item_lookup(devlink, trap->name);
7859         if (WARN_ON_ONCE(!trap_item))
7860                 return;
7861
7862         devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
7863         list_del(&trap_item->list);
7864         if (devlink->ops->trap_fini)
7865                 devlink->ops->trap_fini(devlink, trap, trap_item);
7866         devlink_trap_item_group_unlink(devlink, trap_item);
7867         free_percpu(trap_item->stats);
7868         kfree(trap_item);
7869 }
7870
7871 static void devlink_trap_disable(struct devlink *devlink,
7872                                  const struct devlink_trap *trap)
7873 {
7874         struct devlink_trap_item *trap_item;
7875
7876         trap_item = devlink_trap_item_lookup(devlink, trap->name);
7877         if (WARN_ON_ONCE(!trap_item))
7878                 return;
7879
7880         devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP);
7881         trap_item->action = DEVLINK_TRAP_ACTION_DROP;
7882 }
7883
7884 /**
7885  * devlink_traps_register - Register packet traps with devlink.
7886  * @devlink: devlink.
7887  * @traps: Packet traps.
7888  * @traps_count: Count of provided packet traps.
7889  * @priv: Driver private information.
7890  *
7891  * Return: Non-zero value on failure.
7892  */
7893 int devlink_traps_register(struct devlink *devlink,
7894                            const struct devlink_trap *traps,
7895                            size_t traps_count, void *priv)
7896 {
7897         int i, err;
7898
7899         if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
7900                 return -EINVAL;
7901
7902         mutex_lock(&devlink->lock);
7903         for (i = 0; i < traps_count; i++) {
7904                 const struct devlink_trap *trap = &traps[i];
7905
7906                 err = devlink_trap_verify(trap);
7907                 if (err)
7908                         goto err_trap_verify;
7909
7910                 err = devlink_trap_register(devlink, trap, priv);
7911                 if (err)
7912                         goto err_trap_register;
7913         }
7914         mutex_unlock(&devlink->lock);
7915
7916         return 0;
7917
7918 err_trap_register:
7919 err_trap_verify:
7920         for (i--; i >= 0; i--)
7921                 devlink_trap_unregister(devlink, &traps[i]);
7922         mutex_unlock(&devlink->lock);
7923         return err;
7924 }
7925 EXPORT_SYMBOL_GPL(devlink_traps_register);
7926
7927 /**
7928  * devlink_traps_unregister - Unregister packet traps from devlink.
7929  * @devlink: devlink.
7930  * @traps: Packet traps.
7931  * @traps_count: Count of provided packet traps.
7932  */
7933 void devlink_traps_unregister(struct devlink *devlink,
7934                               const struct devlink_trap *traps,
7935                               size_t traps_count)
7936 {
7937         int i;
7938
7939         mutex_lock(&devlink->lock);
7940         /* Make sure we do not have any packets in-flight while unregistering
7941          * traps by disabling all of them and waiting for a grace period.
7942          */
7943         for (i = traps_count - 1; i >= 0; i--)
7944                 devlink_trap_disable(devlink, &traps[i]);
7945         synchronize_rcu();
7946         for (i = traps_count - 1; i >= 0; i--)
7947                 devlink_trap_unregister(devlink, &traps[i]);
7948         mutex_unlock(&devlink->lock);
7949 }
7950 EXPORT_SYMBOL_GPL(devlink_traps_unregister);
7951
7952 static void
7953 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
7954                           size_t skb_len)
7955 {
7956         struct devlink_stats *stats;
7957
7958         stats = this_cpu_ptr(trap_stats);
7959         u64_stats_update_begin(&stats->syncp);
7960         stats->rx_bytes += skb_len;
7961         stats->rx_packets++;
7962         u64_stats_update_end(&stats->syncp);
7963 }
7964
7965 static void
7966 devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata,
7967                                   const struct devlink_trap_item *trap_item,
7968                                   struct devlink_port *in_devlink_port)
7969 {
7970         struct devlink_trap_group_item *group_item = trap_item->group_item;
7971
7972         hw_metadata->trap_group_name = group_item->group->name;
7973         hw_metadata->trap_name = trap_item->trap->name;
7974
7975         spin_lock(&in_devlink_port->type_lock);
7976         if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
7977                 hw_metadata->input_dev = in_devlink_port->type_dev;
7978         spin_unlock(&in_devlink_port->type_lock);
7979 }
7980
7981 /**
7982  * devlink_trap_report - Report trapped packet to drop monitor.
7983  * @devlink: devlink.
7984  * @skb: Trapped packet.
7985  * @trap_ctx: Trap context.
7986  * @in_devlink_port: Input devlink port.
7987  */
7988 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
7989                          void *trap_ctx, struct devlink_port *in_devlink_port)
7990 {
7991         struct devlink_trap_item *trap_item = trap_ctx;
7992         struct net_dm_hw_metadata hw_metadata = {};
7993
7994         devlink_trap_stats_update(trap_item->stats, skb->len);
7995         devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
7996
7997         devlink_trap_report_metadata_fill(&hw_metadata, trap_item,
7998                                           in_devlink_port);
7999         net_dm_hw_report(skb, &hw_metadata);
8000 }
8001 EXPORT_SYMBOL_GPL(devlink_trap_report);
8002
8003 /**
8004  * devlink_trap_ctx_priv - Trap context to driver private information.
8005  * @trap_ctx: Trap context.
8006  *
8007  * Return: Driver private information passed during registration.
8008  */
8009 void *devlink_trap_ctx_priv(void *trap_ctx)
8010 {
8011         struct devlink_trap_item *trap_item = trap_ctx;
8012
8013         return trap_item->priv;
8014 }
8015 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
8016
8017 static void __devlink_compat_running_version(struct devlink *devlink,
8018                                              char *buf, size_t len)
8019 {
8020         const struct nlattr *nlattr;
8021         struct devlink_info_req req;
8022         struct sk_buff *msg;
8023         int rem, err;
8024
8025         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8026         if (!msg)
8027                 return;
8028
8029         req.msg = msg;
8030         err = devlink->ops->info_get(devlink, &req, NULL);
8031         if (err)
8032                 goto free_msg;
8033
8034         nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
8035                 const struct nlattr *kv;
8036                 int rem_kv;
8037
8038                 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
8039                         continue;
8040
8041                 nla_for_each_nested(kv, nlattr, rem_kv) {
8042                         if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
8043                                 continue;
8044
8045                         strlcat(buf, nla_data(kv), len);
8046                         strlcat(buf, " ", len);
8047                 }
8048         }
8049 free_msg:
8050         nlmsg_free(msg);
8051 }
8052
8053 void devlink_compat_running_version(struct net_device *dev,
8054                                     char *buf, size_t len)
8055 {
8056         struct devlink *devlink;
8057
8058         dev_hold(dev);
8059         rtnl_unlock();
8060
8061         devlink = netdev_to_devlink(dev);
8062         if (!devlink || !devlink->ops->info_get)
8063                 goto out;
8064
8065         mutex_lock(&devlink->lock);
8066         __devlink_compat_running_version(devlink, buf, len);
8067         mutex_unlock(&devlink->lock);
8068
8069 out:
8070         rtnl_lock();
8071         dev_put(dev);
8072 }
8073
8074 int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
8075 {
8076         struct devlink *devlink;
8077         int ret;
8078
8079         dev_hold(dev);
8080         rtnl_unlock();
8081
8082         devlink = netdev_to_devlink(dev);
8083         if (!devlink || !devlink->ops->flash_update) {
8084                 ret = -EOPNOTSUPP;
8085                 goto out;
8086         }
8087
8088         mutex_lock(&devlink->lock);
8089         ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
8090         mutex_unlock(&devlink->lock);
8091
8092 out:
8093         rtnl_lock();
8094         dev_put(dev);
8095
8096         return ret;
8097 }
8098
8099 int devlink_compat_phys_port_name_get(struct net_device *dev,
8100                                       char *name, size_t len)
8101 {
8102         struct devlink_port *devlink_port;
8103
8104         /* RTNL mutex is held here which ensures that devlink_port
8105          * instance cannot disappear in the middle. No need to take
8106          * any devlink lock as only permanent values are accessed.
8107          */
8108         ASSERT_RTNL();
8109
8110         devlink_port = netdev_to_devlink_port(dev);
8111         if (!devlink_port)
8112                 return -EOPNOTSUPP;
8113
8114         return __devlink_port_phys_port_name_get(devlink_port, name, len);
8115 }
8116
8117 int devlink_compat_switch_id_get(struct net_device *dev,
8118                                  struct netdev_phys_item_id *ppid)
8119 {
8120         struct devlink_port *devlink_port;
8121
8122         /* Caller must hold RTNL mutex or reference to dev, which ensures that
8123          * devlink_port instance cannot disappear in the middle. No need to take
8124          * any devlink lock as only permanent values are accessed.
8125          */
8126         devlink_port = netdev_to_devlink_port(dev);
8127         if (!devlink_port || !devlink_port->attrs.switch_port)
8128                 return -EOPNOTSUPP;
8129
8130         memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
8131
8132         return 0;
8133 }
8134
8135 static int __init devlink_init(void)
8136 {
8137         return genl_register_family(&devlink_nl_family);
8138 }
8139
8140 subsys_initcall(devlink_init);