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