]> Git Repo - linux.git/blob - net/core/devlink.c
mm: introduce put_user_page*(), placeholder versions
[linux.git] / net / core / devlink.c
1 /*
2  * net/core/devlink.c - Network physical/parent device Netlink interface
3  *
4  * Heavily inspired by net/wireless/
5  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
6  * Copyright (c) 2016 Jiri Pirko <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/slab.h>
18 #include <linux/gfp.h>
19 #include <linux/device.h>
20 #include <linux/list.h>
21 #include <linux/netdevice.h>
22 #include <linux/spinlock.h>
23 #include <linux/refcount.h>
24 #include <rdma/ib_verbs.h>
25 #include <net/netlink.h>
26 #include <net/genetlink.h>
27 #include <net/rtnetlink.h>
28 #include <net/net_namespace.h>
29 #include <net/sock.h>
30 #include <net/devlink.h>
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/devlink.h>
33
34 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                                                       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, int port_index)
151 {
152         return devlink_port_get_by_index(devlink, port_index);
153 }
154
155 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
156                                                         struct nlattr **attrs)
157 {
158         if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
159                 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
160                 struct devlink_port *devlink_port;
161
162                 devlink_port = devlink_port_get_by_index(devlink, port_index);
163                 if (!devlink_port)
164                         return ERR_PTR(-ENODEV);
165                 return devlink_port;
166         }
167         return ERR_PTR(-EINVAL);
168 }
169
170 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
171                                                        struct genl_info *info)
172 {
173         return devlink_port_get_from_attrs(devlink, info->attrs);
174 }
175
176 struct devlink_sb {
177         struct list_head list;
178         unsigned int index;
179         u32 size;
180         u16 ingress_pools_count;
181         u16 egress_pools_count;
182         u16 ingress_tc_count;
183         u16 egress_tc_count;
184 };
185
186 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
187 {
188         return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
189 }
190
191 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
192                                                   unsigned int sb_index)
193 {
194         struct devlink_sb *devlink_sb;
195
196         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
197                 if (devlink_sb->index == sb_index)
198                         return devlink_sb;
199         }
200         return NULL;
201 }
202
203 static bool devlink_sb_index_exists(struct devlink *devlink,
204                                     unsigned int sb_index)
205 {
206         return devlink_sb_get_by_index(devlink, sb_index);
207 }
208
209 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
210                                                     struct nlattr **attrs)
211 {
212         if (attrs[DEVLINK_ATTR_SB_INDEX]) {
213                 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
214                 struct devlink_sb *devlink_sb;
215
216                 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
217                 if (!devlink_sb)
218                         return ERR_PTR(-ENODEV);
219                 return devlink_sb;
220         }
221         return ERR_PTR(-EINVAL);
222 }
223
224 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
225                                                    struct genl_info *info)
226 {
227         return devlink_sb_get_from_attrs(devlink, info->attrs);
228 }
229
230 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
231                                                 struct nlattr **attrs,
232                                                 u16 *p_pool_index)
233 {
234         u16 val;
235
236         if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
237                 return -EINVAL;
238
239         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
240         if (val >= devlink_sb_pool_count(devlink_sb))
241                 return -EINVAL;
242         *p_pool_index = val;
243         return 0;
244 }
245
246 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
247                                                struct genl_info *info,
248                                                u16 *p_pool_index)
249 {
250         return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
251                                                     p_pool_index);
252 }
253
254 static int
255 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
256                                     enum devlink_sb_pool_type *p_pool_type)
257 {
258         u8 val;
259
260         if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
261                 return -EINVAL;
262
263         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
264         if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
265             val != DEVLINK_SB_POOL_TYPE_EGRESS)
266                 return -EINVAL;
267         *p_pool_type = val;
268         return 0;
269 }
270
271 static int
272 devlink_sb_pool_type_get_from_info(struct genl_info *info,
273                                    enum devlink_sb_pool_type *p_pool_type)
274 {
275         return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
276 }
277
278 static int
279 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
280                                   enum devlink_sb_threshold_type *p_th_type)
281 {
282         u8 val;
283
284         if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
285                 return -EINVAL;
286
287         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
288         if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
289             val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
290                 return -EINVAL;
291         *p_th_type = val;
292         return 0;
293 }
294
295 static int
296 devlink_sb_th_type_get_from_info(struct genl_info *info,
297                                  enum devlink_sb_threshold_type *p_th_type)
298 {
299         return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
300 }
301
302 static int
303 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
304                                    struct nlattr **attrs,
305                                    enum devlink_sb_pool_type pool_type,
306                                    u16 *p_tc_index)
307 {
308         u16 val;
309
310         if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
311                 return -EINVAL;
312
313         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
314         if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
315             val >= devlink_sb->ingress_tc_count)
316                 return -EINVAL;
317         if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
318             val >= devlink_sb->egress_tc_count)
319                 return -EINVAL;
320         *p_tc_index = val;
321         return 0;
322 }
323
324 static int
325 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
326                                   struct genl_info *info,
327                                   enum devlink_sb_pool_type pool_type,
328                                   u16 *p_tc_index)
329 {
330         return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
331                                                   pool_type, p_tc_index);
332 }
333
334 struct devlink_region {
335         struct devlink *devlink;
336         struct list_head list;
337         const char *name;
338         struct list_head snapshot_list;
339         u32 max_snapshots;
340         u32 cur_snapshots;
341         u64 size;
342 };
343
344 struct devlink_snapshot {
345         struct list_head list;
346         struct devlink_region *region;
347         devlink_snapshot_data_dest_t *data_destructor;
348         u64 data_len;
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 static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot)
378 {
379         snapshot->region->cur_snapshots--;
380         list_del(&snapshot->list);
381         (*snapshot->data_destructor)(snapshot->data);
382         kfree(snapshot);
383 }
384
385 #define DEVLINK_NL_FLAG_NEED_DEVLINK    BIT(0)
386 #define DEVLINK_NL_FLAG_NEED_PORT       BIT(1)
387 #define DEVLINK_NL_FLAG_NEED_SB         BIT(2)
388
389 /* The per devlink instance lock is taken by default in the pre-doit
390  * operation, yet several commands do not require this. The global
391  * devlink lock is taken and protects from disruption by user-calls.
392  */
393 #define DEVLINK_NL_FLAG_NO_LOCK         BIT(3)
394
395 static int devlink_nl_pre_doit(const struct genl_ops *ops,
396                                struct sk_buff *skb, struct genl_info *info)
397 {
398         struct devlink *devlink;
399         int err;
400
401         mutex_lock(&devlink_mutex);
402         devlink = devlink_get_from_info(info);
403         if (IS_ERR(devlink)) {
404                 mutex_unlock(&devlink_mutex);
405                 return PTR_ERR(devlink);
406         }
407         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
408                 mutex_lock(&devlink->lock);
409         if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
410                 info->user_ptr[0] = devlink;
411         } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
412                 struct devlink_port *devlink_port;
413
414                 devlink_port = devlink_port_get_from_info(devlink, info);
415                 if (IS_ERR(devlink_port)) {
416                         err = PTR_ERR(devlink_port);
417                         goto unlock;
418                 }
419                 info->user_ptr[0] = devlink_port;
420         }
421         if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
422                 struct devlink_sb *devlink_sb;
423
424                 devlink_sb = devlink_sb_get_from_info(devlink, info);
425                 if (IS_ERR(devlink_sb)) {
426                         err = PTR_ERR(devlink_sb);
427                         goto unlock;
428                 }
429                 info->user_ptr[1] = devlink_sb;
430         }
431         return 0;
432
433 unlock:
434         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
435                 mutex_unlock(&devlink->lock);
436         mutex_unlock(&devlink_mutex);
437         return err;
438 }
439
440 static void devlink_nl_post_doit(const struct genl_ops *ops,
441                                  struct sk_buff *skb, struct genl_info *info)
442 {
443         struct devlink *devlink;
444
445         devlink = devlink_get_from_info(info);
446         if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
447                 mutex_unlock(&devlink->lock);
448         mutex_unlock(&devlink_mutex);
449 }
450
451 static struct genl_family devlink_nl_family;
452
453 enum devlink_multicast_groups {
454         DEVLINK_MCGRP_CONFIG,
455 };
456
457 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
458         [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
459 };
460
461 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
462 {
463         if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
464                 return -EMSGSIZE;
465         if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
466                 return -EMSGSIZE;
467         return 0;
468 }
469
470 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
471                            enum devlink_command cmd, u32 portid,
472                            u32 seq, int flags)
473 {
474         void *hdr;
475
476         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
477         if (!hdr)
478                 return -EMSGSIZE;
479
480         if (devlink_nl_put_handle(msg, devlink))
481                 goto nla_put_failure;
482
483         genlmsg_end(msg, hdr);
484         return 0;
485
486 nla_put_failure:
487         genlmsg_cancel(msg, hdr);
488         return -EMSGSIZE;
489 }
490
491 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
492 {
493         struct sk_buff *msg;
494         int err;
495
496         WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
497
498         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
499         if (!msg)
500                 return;
501
502         err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
503         if (err) {
504                 nlmsg_free(msg);
505                 return;
506         }
507
508         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
509                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
510 }
511
512 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
513                                      struct devlink_port *devlink_port)
514 {
515         struct devlink_port_attrs *attrs = &devlink_port->attrs;
516
517         if (!attrs->set)
518                 return 0;
519         if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
520                 return -EMSGSIZE;
521         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
522                 return -EMSGSIZE;
523         if (!attrs->split)
524                 return 0;
525         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
526                 return -EMSGSIZE;
527         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
528                         attrs->split_subport_number))
529                 return -EMSGSIZE;
530         return 0;
531 }
532
533 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
534                                 struct devlink_port *devlink_port,
535                                 enum devlink_command cmd, u32 portid,
536                                 u32 seq, int flags)
537 {
538         void *hdr;
539
540         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
541         if (!hdr)
542                 return -EMSGSIZE;
543
544         if (devlink_nl_put_handle(msg, devlink))
545                 goto nla_put_failure;
546         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
547                 goto nla_put_failure;
548
549         spin_lock(&devlink_port->type_lock);
550         if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
551                 goto nla_put_failure_type_locked;
552         if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
553             nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
554                         devlink_port->desired_type))
555                 goto nla_put_failure_type_locked;
556         if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
557                 struct net_device *netdev = devlink_port->type_dev;
558
559                 if (netdev &&
560                     (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
561                                  netdev->ifindex) ||
562                      nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
563                                     netdev->name)))
564                         goto nla_put_failure_type_locked;
565         }
566         if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
567                 struct ib_device *ibdev = devlink_port->type_dev;
568
569                 if (ibdev &&
570                     nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
571                                    ibdev->name))
572                         goto nla_put_failure_type_locked;
573         }
574         spin_unlock(&devlink_port->type_lock);
575         if (devlink_nl_port_attrs_put(msg, devlink_port))
576                 goto nla_put_failure;
577
578         genlmsg_end(msg, hdr);
579         return 0;
580
581 nla_put_failure_type_locked:
582         spin_unlock(&devlink_port->type_lock);
583 nla_put_failure:
584         genlmsg_cancel(msg, hdr);
585         return -EMSGSIZE;
586 }
587
588 static void devlink_port_notify(struct devlink_port *devlink_port,
589                                 enum devlink_command cmd)
590 {
591         struct devlink *devlink = devlink_port->devlink;
592         struct sk_buff *msg;
593         int err;
594
595         if (!devlink_port->registered)
596                 return;
597
598         WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
599
600         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
601         if (!msg)
602                 return;
603
604         err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
605         if (err) {
606                 nlmsg_free(msg);
607                 return;
608         }
609
610         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
611                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
612 }
613
614 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
615 {
616         struct devlink *devlink = info->user_ptr[0];
617         struct sk_buff *msg;
618         int err;
619
620         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
621         if (!msg)
622                 return -ENOMEM;
623
624         err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
625                               info->snd_portid, info->snd_seq, 0);
626         if (err) {
627                 nlmsg_free(msg);
628                 return err;
629         }
630
631         return genlmsg_reply(msg, info);
632 }
633
634 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
635                                      struct netlink_callback *cb)
636 {
637         struct devlink *devlink;
638         int start = cb->args[0];
639         int idx = 0;
640         int err;
641
642         mutex_lock(&devlink_mutex);
643         list_for_each_entry(devlink, &devlink_list, list) {
644                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
645                         continue;
646                 if (idx < start) {
647                         idx++;
648                         continue;
649                 }
650                 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
651                                       NETLINK_CB(cb->skb).portid,
652                                       cb->nlh->nlmsg_seq, NLM_F_MULTI);
653                 if (err)
654                         goto out;
655                 idx++;
656         }
657 out:
658         mutex_unlock(&devlink_mutex);
659
660         cb->args[0] = idx;
661         return msg->len;
662 }
663
664 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
665                                         struct genl_info *info)
666 {
667         struct devlink_port *devlink_port = info->user_ptr[0];
668         struct devlink *devlink = devlink_port->devlink;
669         struct sk_buff *msg;
670         int err;
671
672         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
673         if (!msg)
674                 return -ENOMEM;
675
676         err = devlink_nl_port_fill(msg, devlink, devlink_port,
677                                    DEVLINK_CMD_PORT_NEW,
678                                    info->snd_portid, info->snd_seq, 0);
679         if (err) {
680                 nlmsg_free(msg);
681                 return err;
682         }
683
684         return genlmsg_reply(msg, info);
685 }
686
687 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
688                                           struct netlink_callback *cb)
689 {
690         struct devlink *devlink;
691         struct devlink_port *devlink_port;
692         int start = cb->args[0];
693         int idx = 0;
694         int err;
695
696         mutex_lock(&devlink_mutex);
697         list_for_each_entry(devlink, &devlink_list, list) {
698                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
699                         continue;
700                 mutex_lock(&devlink->lock);
701                 list_for_each_entry(devlink_port, &devlink->port_list, list) {
702                         if (idx < start) {
703                                 idx++;
704                                 continue;
705                         }
706                         err = devlink_nl_port_fill(msg, devlink, devlink_port,
707                                                    DEVLINK_CMD_NEW,
708                                                    NETLINK_CB(cb->skb).portid,
709                                                    cb->nlh->nlmsg_seq,
710                                                    NLM_F_MULTI);
711                         if (err) {
712                                 mutex_unlock(&devlink->lock);
713                                 goto out;
714                         }
715                         idx++;
716                 }
717                 mutex_unlock(&devlink->lock);
718         }
719 out:
720         mutex_unlock(&devlink_mutex);
721
722         cb->args[0] = idx;
723         return msg->len;
724 }
725
726 static int devlink_port_type_set(struct devlink *devlink,
727                                  struct devlink_port *devlink_port,
728                                  enum devlink_port_type port_type)
729
730 {
731         int err;
732
733         if (devlink->ops->port_type_set) {
734                 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
735                         return -EINVAL;
736                 if (port_type == devlink_port->type)
737                         return 0;
738                 err = devlink->ops->port_type_set(devlink_port, port_type);
739                 if (err)
740                         return err;
741                 devlink_port->desired_type = port_type;
742                 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
743                 return 0;
744         }
745         return -EOPNOTSUPP;
746 }
747
748 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
749                                         struct genl_info *info)
750 {
751         struct devlink_port *devlink_port = info->user_ptr[0];
752         struct devlink *devlink = devlink_port->devlink;
753         int err;
754
755         if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
756                 enum devlink_port_type port_type;
757
758                 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
759                 err = devlink_port_type_set(devlink, devlink_port, port_type);
760                 if (err)
761                         return err;
762         }
763         return 0;
764 }
765
766 static int devlink_port_split(struct devlink *devlink, u32 port_index,
767                               u32 count, struct netlink_ext_ack *extack)
768
769 {
770         if (devlink->ops->port_split)
771                 return devlink->ops->port_split(devlink, port_index, count,
772                                                 extack);
773         return -EOPNOTSUPP;
774 }
775
776 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
777                                           struct genl_info *info)
778 {
779         struct devlink *devlink = info->user_ptr[0];
780         u32 port_index;
781         u32 count;
782
783         if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
784             !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
785                 return -EINVAL;
786
787         port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
788         count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
789         return devlink_port_split(devlink, port_index, count, info->extack);
790 }
791
792 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
793                                 struct netlink_ext_ack *extack)
794
795 {
796         if (devlink->ops->port_unsplit)
797                 return devlink->ops->port_unsplit(devlink, port_index, extack);
798         return -EOPNOTSUPP;
799 }
800
801 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
802                                             struct genl_info *info)
803 {
804         struct devlink *devlink = info->user_ptr[0];
805         u32 port_index;
806
807         if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
808                 return -EINVAL;
809
810         port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
811         return devlink_port_unsplit(devlink, port_index, info->extack);
812 }
813
814 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
815                               struct devlink_sb *devlink_sb,
816                               enum devlink_command cmd, u32 portid,
817                               u32 seq, int flags)
818 {
819         void *hdr;
820
821         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
822         if (!hdr)
823                 return -EMSGSIZE;
824
825         if (devlink_nl_put_handle(msg, devlink))
826                 goto nla_put_failure;
827         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
828                 goto nla_put_failure;
829         if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
830                 goto nla_put_failure;
831         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
832                         devlink_sb->ingress_pools_count))
833                 goto nla_put_failure;
834         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
835                         devlink_sb->egress_pools_count))
836                 goto nla_put_failure;
837         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
838                         devlink_sb->ingress_tc_count))
839                 goto nla_put_failure;
840         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
841                         devlink_sb->egress_tc_count))
842                 goto nla_put_failure;
843
844         genlmsg_end(msg, hdr);
845         return 0;
846
847 nla_put_failure:
848         genlmsg_cancel(msg, hdr);
849         return -EMSGSIZE;
850 }
851
852 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
853                                       struct genl_info *info)
854 {
855         struct devlink *devlink = info->user_ptr[0];
856         struct devlink_sb *devlink_sb = info->user_ptr[1];
857         struct sk_buff *msg;
858         int err;
859
860         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
861         if (!msg)
862                 return -ENOMEM;
863
864         err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
865                                  DEVLINK_CMD_SB_NEW,
866                                  info->snd_portid, info->snd_seq, 0);
867         if (err) {
868                 nlmsg_free(msg);
869                 return err;
870         }
871
872         return genlmsg_reply(msg, info);
873 }
874
875 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
876                                         struct netlink_callback *cb)
877 {
878         struct devlink *devlink;
879         struct devlink_sb *devlink_sb;
880         int start = cb->args[0];
881         int idx = 0;
882         int err;
883
884         mutex_lock(&devlink_mutex);
885         list_for_each_entry(devlink, &devlink_list, list) {
886                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
887                         continue;
888                 mutex_lock(&devlink->lock);
889                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
890                         if (idx < start) {
891                                 idx++;
892                                 continue;
893                         }
894                         err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
895                                                  DEVLINK_CMD_SB_NEW,
896                                                  NETLINK_CB(cb->skb).portid,
897                                                  cb->nlh->nlmsg_seq,
898                                                  NLM_F_MULTI);
899                         if (err) {
900                                 mutex_unlock(&devlink->lock);
901                                 goto out;
902                         }
903                         idx++;
904                 }
905                 mutex_unlock(&devlink->lock);
906         }
907 out:
908         mutex_unlock(&devlink_mutex);
909
910         cb->args[0] = idx;
911         return msg->len;
912 }
913
914 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
915                                    struct devlink_sb *devlink_sb,
916                                    u16 pool_index, enum devlink_command cmd,
917                                    u32 portid, u32 seq, int flags)
918 {
919         struct devlink_sb_pool_info pool_info;
920         void *hdr;
921         int err;
922
923         err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
924                                         pool_index, &pool_info);
925         if (err)
926                 return err;
927
928         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
929         if (!hdr)
930                 return -EMSGSIZE;
931
932         if (devlink_nl_put_handle(msg, devlink))
933                 goto nla_put_failure;
934         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
935                 goto nla_put_failure;
936         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
937                 goto nla_put_failure;
938         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
939                 goto nla_put_failure;
940         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
941                 goto nla_put_failure;
942         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
943                        pool_info.threshold_type))
944                 goto nla_put_failure;
945         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
946                         pool_info.cell_size))
947                 goto nla_put_failure;
948
949         genlmsg_end(msg, hdr);
950         return 0;
951
952 nla_put_failure:
953         genlmsg_cancel(msg, hdr);
954         return -EMSGSIZE;
955 }
956
957 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
958                                            struct genl_info *info)
959 {
960         struct devlink *devlink = info->user_ptr[0];
961         struct devlink_sb *devlink_sb = info->user_ptr[1];
962         struct sk_buff *msg;
963         u16 pool_index;
964         int err;
965
966         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
967                                                   &pool_index);
968         if (err)
969                 return err;
970
971         if (!devlink->ops->sb_pool_get)
972                 return -EOPNOTSUPP;
973
974         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
975         if (!msg)
976                 return -ENOMEM;
977
978         err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
979                                       DEVLINK_CMD_SB_POOL_NEW,
980                                       info->snd_portid, info->snd_seq, 0);
981         if (err) {
982                 nlmsg_free(msg);
983                 return err;
984         }
985
986         return genlmsg_reply(msg, info);
987 }
988
989 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
990                                 struct devlink *devlink,
991                                 struct devlink_sb *devlink_sb,
992                                 u32 portid, u32 seq)
993 {
994         u16 pool_count = devlink_sb_pool_count(devlink_sb);
995         u16 pool_index;
996         int err;
997
998         for (pool_index = 0; pool_index < pool_count; pool_index++) {
999                 if (*p_idx < start) {
1000                         (*p_idx)++;
1001                         continue;
1002                 }
1003                 err = devlink_nl_sb_pool_fill(msg, devlink,
1004                                               devlink_sb,
1005                                               pool_index,
1006                                               DEVLINK_CMD_SB_POOL_NEW,
1007                                               portid, seq, NLM_F_MULTI);
1008                 if (err)
1009                         return err;
1010                 (*p_idx)++;
1011         }
1012         return 0;
1013 }
1014
1015 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1016                                              struct netlink_callback *cb)
1017 {
1018         struct devlink *devlink;
1019         struct devlink_sb *devlink_sb;
1020         int start = cb->args[0];
1021         int idx = 0;
1022         int err;
1023
1024         mutex_lock(&devlink_mutex);
1025         list_for_each_entry(devlink, &devlink_list, list) {
1026                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1027                     !devlink->ops->sb_pool_get)
1028                         continue;
1029                 mutex_lock(&devlink->lock);
1030                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1031                         err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1032                                                    devlink_sb,
1033                                                    NETLINK_CB(cb->skb).portid,
1034                                                    cb->nlh->nlmsg_seq);
1035                         if (err && err != -EOPNOTSUPP) {
1036                                 mutex_unlock(&devlink->lock);
1037                                 goto out;
1038                         }
1039                 }
1040                 mutex_unlock(&devlink->lock);
1041         }
1042 out:
1043         mutex_unlock(&devlink_mutex);
1044
1045         cb->args[0] = idx;
1046         return msg->len;
1047 }
1048
1049 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1050                                u16 pool_index, u32 size,
1051                                enum devlink_sb_threshold_type threshold_type,
1052                                struct netlink_ext_ack *extack)
1053
1054 {
1055         const struct devlink_ops *ops = devlink->ops;
1056
1057         if (ops->sb_pool_set)
1058                 return ops->sb_pool_set(devlink, sb_index, pool_index,
1059                                         size, threshold_type, extack);
1060         return -EOPNOTSUPP;
1061 }
1062
1063 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1064                                            struct genl_info *info)
1065 {
1066         struct devlink *devlink = info->user_ptr[0];
1067         struct devlink_sb *devlink_sb = info->user_ptr[1];
1068         enum devlink_sb_threshold_type threshold_type;
1069         u16 pool_index;
1070         u32 size;
1071         int err;
1072
1073         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1074                                                   &pool_index);
1075         if (err)
1076                 return err;
1077
1078         err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1079         if (err)
1080                 return err;
1081
1082         if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1083                 return -EINVAL;
1084
1085         size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1086         return devlink_sb_pool_set(devlink, devlink_sb->index,
1087                                    pool_index, size, threshold_type,
1088                                    info->extack);
1089 }
1090
1091 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1092                                         struct devlink *devlink,
1093                                         struct devlink_port *devlink_port,
1094                                         struct devlink_sb *devlink_sb,
1095                                         u16 pool_index,
1096                                         enum devlink_command cmd,
1097                                         u32 portid, u32 seq, int flags)
1098 {
1099         const struct devlink_ops *ops = devlink->ops;
1100         u32 threshold;
1101         void *hdr;
1102         int err;
1103
1104         err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1105                                     pool_index, &threshold);
1106         if (err)
1107                 return err;
1108
1109         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1110         if (!hdr)
1111                 return -EMSGSIZE;
1112
1113         if (devlink_nl_put_handle(msg, devlink))
1114                 goto nla_put_failure;
1115         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1116                 goto nla_put_failure;
1117         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1118                 goto nla_put_failure;
1119         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1120                 goto nla_put_failure;
1121         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1122                 goto nla_put_failure;
1123
1124         if (ops->sb_occ_port_pool_get) {
1125                 u32 cur;
1126                 u32 max;
1127
1128                 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1129                                                 pool_index, &cur, &max);
1130                 if (err && err != -EOPNOTSUPP)
1131                         return err;
1132                 if (!err) {
1133                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1134                                 goto nla_put_failure;
1135                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1136                                 goto nla_put_failure;
1137                 }
1138         }
1139
1140         genlmsg_end(msg, hdr);
1141         return 0;
1142
1143 nla_put_failure:
1144         genlmsg_cancel(msg, hdr);
1145         return -EMSGSIZE;
1146 }
1147
1148 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1149                                                 struct genl_info *info)
1150 {
1151         struct devlink_port *devlink_port = info->user_ptr[0];
1152         struct devlink *devlink = devlink_port->devlink;
1153         struct devlink_sb *devlink_sb = info->user_ptr[1];
1154         struct sk_buff *msg;
1155         u16 pool_index;
1156         int err;
1157
1158         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1159                                                   &pool_index);
1160         if (err)
1161                 return err;
1162
1163         if (!devlink->ops->sb_port_pool_get)
1164                 return -EOPNOTSUPP;
1165
1166         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1167         if (!msg)
1168                 return -ENOMEM;
1169
1170         err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1171                                            devlink_sb, pool_index,
1172                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
1173                                            info->snd_portid, info->snd_seq, 0);
1174         if (err) {
1175                 nlmsg_free(msg);
1176                 return err;
1177         }
1178
1179         return genlmsg_reply(msg, info);
1180 }
1181
1182 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1183                                      struct devlink *devlink,
1184                                      struct devlink_sb *devlink_sb,
1185                                      u32 portid, u32 seq)
1186 {
1187         struct devlink_port *devlink_port;
1188         u16 pool_count = devlink_sb_pool_count(devlink_sb);
1189         u16 pool_index;
1190         int err;
1191
1192         list_for_each_entry(devlink_port, &devlink->port_list, list) {
1193                 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1194                         if (*p_idx < start) {
1195                                 (*p_idx)++;
1196                                 continue;
1197                         }
1198                         err = devlink_nl_sb_port_pool_fill(msg, devlink,
1199                                                            devlink_port,
1200                                                            devlink_sb,
1201                                                            pool_index,
1202                                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
1203                                                            portid, seq,
1204                                                            NLM_F_MULTI);
1205                         if (err)
1206                                 return err;
1207                         (*p_idx)++;
1208                 }
1209         }
1210         return 0;
1211 }
1212
1213 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1214                                                   struct netlink_callback *cb)
1215 {
1216         struct devlink *devlink;
1217         struct devlink_sb *devlink_sb;
1218         int start = cb->args[0];
1219         int idx = 0;
1220         int err;
1221
1222         mutex_lock(&devlink_mutex);
1223         list_for_each_entry(devlink, &devlink_list, list) {
1224                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1225                     !devlink->ops->sb_port_pool_get)
1226                         continue;
1227                 mutex_lock(&devlink->lock);
1228                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1229                         err = __sb_port_pool_get_dumpit(msg, start, &idx,
1230                                                         devlink, devlink_sb,
1231                                                         NETLINK_CB(cb->skb).portid,
1232                                                         cb->nlh->nlmsg_seq);
1233                         if (err && err != -EOPNOTSUPP) {
1234                                 mutex_unlock(&devlink->lock);
1235                                 goto out;
1236                         }
1237                 }
1238                 mutex_unlock(&devlink->lock);
1239         }
1240 out:
1241         mutex_unlock(&devlink_mutex);
1242
1243         cb->args[0] = idx;
1244         return msg->len;
1245 }
1246
1247 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1248                                     unsigned int sb_index, u16 pool_index,
1249                                     u32 threshold,
1250                                     struct netlink_ext_ack *extack)
1251
1252 {
1253         const struct devlink_ops *ops = devlink_port->devlink->ops;
1254
1255         if (ops->sb_port_pool_set)
1256                 return ops->sb_port_pool_set(devlink_port, sb_index,
1257                                              pool_index, threshold, extack);
1258         return -EOPNOTSUPP;
1259 }
1260
1261 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1262                                                 struct genl_info *info)
1263 {
1264         struct devlink_port *devlink_port = info->user_ptr[0];
1265         struct devlink_sb *devlink_sb = info->user_ptr[1];
1266         u16 pool_index;
1267         u32 threshold;
1268         int err;
1269
1270         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1271                                                   &pool_index);
1272         if (err)
1273                 return err;
1274
1275         if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1276                 return -EINVAL;
1277
1278         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1279         return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1280                                         pool_index, threshold, info->extack);
1281 }
1282
1283 static int
1284 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1285                                 struct devlink_port *devlink_port,
1286                                 struct devlink_sb *devlink_sb, u16 tc_index,
1287                                 enum devlink_sb_pool_type pool_type,
1288                                 enum devlink_command cmd,
1289                                 u32 portid, u32 seq, int flags)
1290 {
1291         const struct devlink_ops *ops = devlink->ops;
1292         u16 pool_index;
1293         u32 threshold;
1294         void *hdr;
1295         int err;
1296
1297         err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1298                                        tc_index, pool_type,
1299                                        &pool_index, &threshold);
1300         if (err)
1301                 return err;
1302
1303         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1304         if (!hdr)
1305                 return -EMSGSIZE;
1306
1307         if (devlink_nl_put_handle(msg, devlink))
1308                 goto nla_put_failure;
1309         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1310                 goto nla_put_failure;
1311         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1312                 goto nla_put_failure;
1313         if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1314                 goto nla_put_failure;
1315         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1316                 goto nla_put_failure;
1317         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1318                 goto nla_put_failure;
1319         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1320                 goto nla_put_failure;
1321
1322         if (ops->sb_occ_tc_port_bind_get) {
1323                 u32 cur;
1324                 u32 max;
1325
1326                 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1327                                                    devlink_sb->index,
1328                                                    tc_index, pool_type,
1329                                                    &cur, &max);
1330                 if (err && err != -EOPNOTSUPP)
1331                         return err;
1332                 if (!err) {
1333                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1334                                 goto nla_put_failure;
1335                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1336                                 goto nla_put_failure;
1337                 }
1338         }
1339
1340         genlmsg_end(msg, hdr);
1341         return 0;
1342
1343 nla_put_failure:
1344         genlmsg_cancel(msg, hdr);
1345         return -EMSGSIZE;
1346 }
1347
1348 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1349                                                    struct genl_info *info)
1350 {
1351         struct devlink_port *devlink_port = info->user_ptr[0];
1352         struct devlink *devlink = devlink_port->devlink;
1353         struct devlink_sb *devlink_sb = info->user_ptr[1];
1354         struct sk_buff *msg;
1355         enum devlink_sb_pool_type pool_type;
1356         u16 tc_index;
1357         int err;
1358
1359         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1360         if (err)
1361                 return err;
1362
1363         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1364                                                 pool_type, &tc_index);
1365         if (err)
1366                 return err;
1367
1368         if (!devlink->ops->sb_tc_pool_bind_get)
1369                 return -EOPNOTSUPP;
1370
1371         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1372         if (!msg)
1373                 return -ENOMEM;
1374
1375         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1376                                               devlink_sb, tc_index, pool_type,
1377                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1378                                               info->snd_portid,
1379                                               info->snd_seq, 0);
1380         if (err) {
1381                 nlmsg_free(msg);
1382                 return err;
1383         }
1384
1385         return genlmsg_reply(msg, info);
1386 }
1387
1388 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1389                                         int start, int *p_idx,
1390                                         struct devlink *devlink,
1391                                         struct devlink_sb *devlink_sb,
1392                                         u32 portid, u32 seq)
1393 {
1394         struct devlink_port *devlink_port;
1395         u16 tc_index;
1396         int err;
1397
1398         list_for_each_entry(devlink_port, &devlink->port_list, list) {
1399                 for (tc_index = 0;
1400                      tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1401                         if (*p_idx < start) {
1402                                 (*p_idx)++;
1403                                 continue;
1404                         }
1405                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1406                                                               devlink_port,
1407                                                               devlink_sb,
1408                                                               tc_index,
1409                                                               DEVLINK_SB_POOL_TYPE_INGRESS,
1410                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1411                                                               portid, seq,
1412                                                               NLM_F_MULTI);
1413                         if (err)
1414                                 return err;
1415                         (*p_idx)++;
1416                 }
1417                 for (tc_index = 0;
1418                      tc_index < devlink_sb->egress_tc_count; tc_index++) {
1419                         if (*p_idx < start) {
1420                                 (*p_idx)++;
1421                                 continue;
1422                         }
1423                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1424                                                               devlink_port,
1425                                                               devlink_sb,
1426                                                               tc_index,
1427                                                               DEVLINK_SB_POOL_TYPE_EGRESS,
1428                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1429                                                               portid, seq,
1430                                                               NLM_F_MULTI);
1431                         if (err)
1432                                 return err;
1433                         (*p_idx)++;
1434                 }
1435         }
1436         return 0;
1437 }
1438
1439 static int
1440 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1441                                           struct netlink_callback *cb)
1442 {
1443         struct devlink *devlink;
1444         struct devlink_sb *devlink_sb;
1445         int start = cb->args[0];
1446         int idx = 0;
1447         int err;
1448
1449         mutex_lock(&devlink_mutex);
1450         list_for_each_entry(devlink, &devlink_list, list) {
1451                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1452                     !devlink->ops->sb_tc_pool_bind_get)
1453                         continue;
1454
1455                 mutex_lock(&devlink->lock);
1456                 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1457                         err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1458                                                            devlink,
1459                                                            devlink_sb,
1460                                                            NETLINK_CB(cb->skb).portid,
1461                                                            cb->nlh->nlmsg_seq);
1462                         if (err && err != -EOPNOTSUPP) {
1463                                 mutex_unlock(&devlink->lock);
1464                                 goto out;
1465                         }
1466                 }
1467                 mutex_unlock(&devlink->lock);
1468         }
1469 out:
1470         mutex_unlock(&devlink_mutex);
1471
1472         cb->args[0] = idx;
1473         return msg->len;
1474 }
1475
1476 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1477                                        unsigned int sb_index, u16 tc_index,
1478                                        enum devlink_sb_pool_type pool_type,
1479                                        u16 pool_index, u32 threshold,
1480                                        struct netlink_ext_ack *extack)
1481
1482 {
1483         const struct devlink_ops *ops = devlink_port->devlink->ops;
1484
1485         if (ops->sb_tc_pool_bind_set)
1486                 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1487                                                 tc_index, pool_type,
1488                                                 pool_index, threshold, extack);
1489         return -EOPNOTSUPP;
1490 }
1491
1492 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1493                                                    struct genl_info *info)
1494 {
1495         struct devlink_port *devlink_port = info->user_ptr[0];
1496         struct devlink_sb *devlink_sb = info->user_ptr[1];
1497         enum devlink_sb_pool_type pool_type;
1498         u16 tc_index;
1499         u16 pool_index;
1500         u32 threshold;
1501         int err;
1502
1503         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1504         if (err)
1505                 return err;
1506
1507         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1508                                                 pool_type, &tc_index);
1509         if (err)
1510                 return err;
1511
1512         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1513                                                   &pool_index);
1514         if (err)
1515                 return err;
1516
1517         if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1518                 return -EINVAL;
1519
1520         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1521         return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1522                                            tc_index, pool_type,
1523                                            pool_index, threshold, info->extack);
1524 }
1525
1526 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1527                                                struct genl_info *info)
1528 {
1529         struct devlink *devlink = info->user_ptr[0];
1530         struct devlink_sb *devlink_sb = info->user_ptr[1];
1531         const struct devlink_ops *ops = devlink->ops;
1532
1533         if (ops->sb_occ_snapshot)
1534                 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1535         return -EOPNOTSUPP;
1536 }
1537
1538 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1539                                                 struct genl_info *info)
1540 {
1541         struct devlink *devlink = info->user_ptr[0];
1542         struct devlink_sb *devlink_sb = info->user_ptr[1];
1543         const struct devlink_ops *ops = devlink->ops;
1544
1545         if (ops->sb_occ_max_clear)
1546                 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1547         return -EOPNOTSUPP;
1548 }
1549
1550 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1551                                    enum devlink_command cmd, u32 portid,
1552                                    u32 seq, int flags)
1553 {
1554         const struct devlink_ops *ops = devlink->ops;
1555         u8 inline_mode, encap_mode;
1556         void *hdr;
1557         int err = 0;
1558         u16 mode;
1559
1560         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1561         if (!hdr)
1562                 return -EMSGSIZE;
1563
1564         err = devlink_nl_put_handle(msg, devlink);
1565         if (err)
1566                 goto nla_put_failure;
1567
1568         if (ops->eswitch_mode_get) {
1569                 err = ops->eswitch_mode_get(devlink, &mode);
1570                 if (err)
1571                         goto nla_put_failure;
1572                 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1573                 if (err)
1574                         goto nla_put_failure;
1575         }
1576
1577         if (ops->eswitch_inline_mode_get) {
1578                 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1579                 if (err)
1580                         goto nla_put_failure;
1581                 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1582                                  inline_mode);
1583                 if (err)
1584                         goto nla_put_failure;
1585         }
1586
1587         if (ops->eswitch_encap_mode_get) {
1588                 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1589                 if (err)
1590                         goto nla_put_failure;
1591                 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1592                 if (err)
1593                         goto nla_put_failure;
1594         }
1595
1596         genlmsg_end(msg, hdr);
1597         return 0;
1598
1599 nla_put_failure:
1600         genlmsg_cancel(msg, hdr);
1601         return err;
1602 }
1603
1604 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1605                                            struct genl_info *info)
1606 {
1607         struct devlink *devlink = info->user_ptr[0];
1608         struct sk_buff *msg;
1609         int err;
1610
1611         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1612         if (!msg)
1613                 return -ENOMEM;
1614
1615         err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1616                                       info->snd_portid, info->snd_seq, 0);
1617
1618         if (err) {
1619                 nlmsg_free(msg);
1620                 return err;
1621         }
1622
1623         return genlmsg_reply(msg, info);
1624 }
1625
1626 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1627                                            struct genl_info *info)
1628 {
1629         struct devlink *devlink = info->user_ptr[0];
1630         const struct devlink_ops *ops = devlink->ops;
1631         u8 inline_mode, encap_mode;
1632         int err = 0;
1633         u16 mode;
1634
1635         if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1636                 if (!ops->eswitch_mode_set)
1637                         return -EOPNOTSUPP;
1638                 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1639                 err = ops->eswitch_mode_set(devlink, mode, info->extack);
1640                 if (err)
1641                         return err;
1642         }
1643
1644         if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1645                 if (!ops->eswitch_inline_mode_set)
1646                         return -EOPNOTSUPP;
1647                 inline_mode = nla_get_u8(
1648                                 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1649                 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1650                                                    info->extack);
1651                 if (err)
1652                         return err;
1653         }
1654
1655         if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1656                 if (!ops->eswitch_encap_mode_set)
1657                         return -EOPNOTSUPP;
1658                 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1659                 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1660                                                   info->extack);
1661                 if (err)
1662                         return err;
1663         }
1664
1665         return 0;
1666 }
1667
1668 int devlink_dpipe_match_put(struct sk_buff *skb,
1669                             struct devlink_dpipe_match *match)
1670 {
1671         struct devlink_dpipe_header *header = match->header;
1672         struct devlink_dpipe_field *field = &header->fields[match->field_id];
1673         struct nlattr *match_attr;
1674
1675         match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1676         if (!match_attr)
1677                 return -EMSGSIZE;
1678
1679         if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1680             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1681             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1682             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1683             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1684                 goto nla_put_failure;
1685
1686         nla_nest_end(skb, match_attr);
1687         return 0;
1688
1689 nla_put_failure:
1690         nla_nest_cancel(skb, match_attr);
1691         return -EMSGSIZE;
1692 }
1693 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1694
1695 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1696                                      struct sk_buff *skb)
1697 {
1698         struct nlattr *matches_attr;
1699
1700         matches_attr = nla_nest_start_noflag(skb,
1701                                              DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1702         if (!matches_attr)
1703                 return -EMSGSIZE;
1704
1705         if (table->table_ops->matches_dump(table->priv, skb))
1706                 goto nla_put_failure;
1707
1708         nla_nest_end(skb, matches_attr);
1709         return 0;
1710
1711 nla_put_failure:
1712         nla_nest_cancel(skb, matches_attr);
1713         return -EMSGSIZE;
1714 }
1715
1716 int devlink_dpipe_action_put(struct sk_buff *skb,
1717                              struct devlink_dpipe_action *action)
1718 {
1719         struct devlink_dpipe_header *header = action->header;
1720         struct devlink_dpipe_field *field = &header->fields[action->field_id];
1721         struct nlattr *action_attr;
1722
1723         action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1724         if (!action_attr)
1725                 return -EMSGSIZE;
1726
1727         if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1728             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1729             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1730             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1731             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1732                 goto nla_put_failure;
1733
1734         nla_nest_end(skb, action_attr);
1735         return 0;
1736
1737 nla_put_failure:
1738         nla_nest_cancel(skb, action_attr);
1739         return -EMSGSIZE;
1740 }
1741 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1742
1743 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1744                                      struct sk_buff *skb)
1745 {
1746         struct nlattr *actions_attr;
1747
1748         actions_attr = nla_nest_start_noflag(skb,
1749                                              DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1750         if (!actions_attr)
1751                 return -EMSGSIZE;
1752
1753         if (table->table_ops->actions_dump(table->priv, skb))
1754                 goto nla_put_failure;
1755
1756         nla_nest_end(skb, actions_attr);
1757         return 0;
1758
1759 nla_put_failure:
1760         nla_nest_cancel(skb, actions_attr);
1761         return -EMSGSIZE;
1762 }
1763
1764 static int devlink_dpipe_table_put(struct sk_buff *skb,
1765                                    struct devlink_dpipe_table *table)
1766 {
1767         struct nlattr *table_attr;
1768         u64 table_size;
1769
1770         table_size = table->table_ops->size_get(table->priv);
1771         table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1772         if (!table_attr)
1773                 return -EMSGSIZE;
1774
1775         if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1776             nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1777                               DEVLINK_ATTR_PAD))
1778                 goto nla_put_failure;
1779         if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1780                        table->counters_enabled))
1781                 goto nla_put_failure;
1782
1783         if (table->resource_valid) {
1784                 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1785                                       table->resource_id, DEVLINK_ATTR_PAD) ||
1786                     nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1787                                       table->resource_units, DEVLINK_ATTR_PAD))
1788                         goto nla_put_failure;
1789         }
1790         if (devlink_dpipe_matches_put(table, skb))
1791                 goto nla_put_failure;
1792
1793         if (devlink_dpipe_actions_put(table, skb))
1794                 goto nla_put_failure;
1795
1796         nla_nest_end(skb, table_attr);
1797         return 0;
1798
1799 nla_put_failure:
1800         nla_nest_cancel(skb, table_attr);
1801         return -EMSGSIZE;
1802 }
1803
1804 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1805                                             struct genl_info *info)
1806 {
1807         int err;
1808
1809         if (*pskb) {
1810                 err = genlmsg_reply(*pskb, info);
1811                 if (err)
1812                         return err;
1813         }
1814         *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1815         if (!*pskb)
1816                 return -ENOMEM;
1817         return 0;
1818 }
1819
1820 static int devlink_dpipe_tables_fill(struct genl_info *info,
1821                                      enum devlink_command cmd, int flags,
1822                                      struct list_head *dpipe_tables,
1823                                      const char *table_name)
1824 {
1825         struct devlink *devlink = info->user_ptr[0];
1826         struct devlink_dpipe_table *table;
1827         struct nlattr *tables_attr;
1828         struct sk_buff *skb = NULL;
1829         struct nlmsghdr *nlh;
1830         bool incomplete;
1831         void *hdr;
1832         int i;
1833         int err;
1834
1835         table = list_first_entry(dpipe_tables,
1836                                  struct devlink_dpipe_table, list);
1837 start_again:
1838         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1839         if (err)
1840                 return err;
1841
1842         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1843                           &devlink_nl_family, NLM_F_MULTI, cmd);
1844         if (!hdr) {
1845                 nlmsg_free(skb);
1846                 return -EMSGSIZE;
1847         }
1848
1849         if (devlink_nl_put_handle(skb, devlink))
1850                 goto nla_put_failure;
1851         tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1852         if (!tables_attr)
1853                 goto nla_put_failure;
1854
1855         i = 0;
1856         incomplete = false;
1857         list_for_each_entry_from(table, dpipe_tables, list) {
1858                 if (!table_name) {
1859                         err = devlink_dpipe_table_put(skb, table);
1860                         if (err) {
1861                                 if (!i)
1862                                         goto err_table_put;
1863                                 incomplete = true;
1864                                 break;
1865                         }
1866                 } else {
1867                         if (!strcmp(table->name, table_name)) {
1868                                 err = devlink_dpipe_table_put(skb, table);
1869                                 if (err)
1870                                         break;
1871                         }
1872                 }
1873                 i++;
1874         }
1875
1876         nla_nest_end(skb, tables_attr);
1877         genlmsg_end(skb, hdr);
1878         if (incomplete)
1879                 goto start_again;
1880
1881 send_done:
1882         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1883                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
1884         if (!nlh) {
1885                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1886                 if (err)
1887                         return err;
1888                 goto send_done;
1889         }
1890
1891         return genlmsg_reply(skb, info);
1892
1893 nla_put_failure:
1894         err = -EMSGSIZE;
1895 err_table_put:
1896         nlmsg_free(skb);
1897         return err;
1898 }
1899
1900 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1901                                           struct genl_info *info)
1902 {
1903         struct devlink *devlink = info->user_ptr[0];
1904         const char *table_name =  NULL;
1905
1906         if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1907                 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1908
1909         return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1910                                          &devlink->dpipe_table_list,
1911                                          table_name);
1912 }
1913
1914 static int devlink_dpipe_value_put(struct sk_buff *skb,
1915                                    struct devlink_dpipe_value *value)
1916 {
1917         if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1918                     value->value_size, value->value))
1919                 return -EMSGSIZE;
1920         if (value->mask)
1921                 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1922                             value->value_size, value->mask))
1923                         return -EMSGSIZE;
1924         if (value->mapping_valid)
1925                 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1926                                 value->mapping_value))
1927                         return -EMSGSIZE;
1928         return 0;
1929 }
1930
1931 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1932                                           struct devlink_dpipe_value *value)
1933 {
1934         if (!value->action)
1935                 return -EINVAL;
1936         if (devlink_dpipe_action_put(skb, value->action))
1937                 return -EMSGSIZE;
1938         if (devlink_dpipe_value_put(skb, value))
1939                 return -EMSGSIZE;
1940         return 0;
1941 }
1942
1943 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1944                                            struct devlink_dpipe_value *values,
1945                                            unsigned int values_count)
1946 {
1947         struct nlattr *action_attr;
1948         int i;
1949         int err;
1950
1951         for (i = 0; i < values_count; i++) {
1952                 action_attr = nla_nest_start_noflag(skb,
1953                                                     DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1954                 if (!action_attr)
1955                         return -EMSGSIZE;
1956                 err = devlink_dpipe_action_value_put(skb, &values[i]);
1957                 if (err)
1958                         goto err_action_value_put;
1959                 nla_nest_end(skb, action_attr);
1960         }
1961         return 0;
1962
1963 err_action_value_put:
1964         nla_nest_cancel(skb, action_attr);
1965         return err;
1966 }
1967
1968 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1969                                          struct devlink_dpipe_value *value)
1970 {
1971         if (!value->match)
1972                 return -EINVAL;
1973         if (devlink_dpipe_match_put(skb, value->match))
1974                 return -EMSGSIZE;
1975         if (devlink_dpipe_value_put(skb, value))
1976                 return -EMSGSIZE;
1977         return 0;
1978 }
1979
1980 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
1981                                           struct devlink_dpipe_value *values,
1982                                           unsigned int values_count)
1983 {
1984         struct nlattr *match_attr;
1985         int i;
1986         int err;
1987
1988         for (i = 0; i < values_count; i++) {
1989                 match_attr = nla_nest_start_noflag(skb,
1990                                                    DEVLINK_ATTR_DPIPE_MATCH_VALUE);
1991                 if (!match_attr)
1992                         return -EMSGSIZE;
1993                 err = devlink_dpipe_match_value_put(skb, &values[i]);
1994                 if (err)
1995                         goto err_match_value_put;
1996                 nla_nest_end(skb, match_attr);
1997         }
1998         return 0;
1999
2000 err_match_value_put:
2001         nla_nest_cancel(skb, match_attr);
2002         return err;
2003 }
2004
2005 static int devlink_dpipe_entry_put(struct sk_buff *skb,
2006                                    struct devlink_dpipe_entry *entry)
2007 {
2008         struct nlattr *entry_attr, *matches_attr, *actions_attr;
2009         int err;
2010
2011         entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2012         if (!entry_attr)
2013                 return  -EMSGSIZE;
2014
2015         if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2016                               DEVLINK_ATTR_PAD))
2017                 goto nla_put_failure;
2018         if (entry->counter_valid)
2019                 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2020                                       entry->counter, DEVLINK_ATTR_PAD))
2021                         goto nla_put_failure;
2022
2023         matches_attr = nla_nest_start_noflag(skb,
2024                                              DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2025         if (!matches_attr)
2026                 goto nla_put_failure;
2027
2028         err = devlink_dpipe_match_values_put(skb, entry->match_values,
2029                                              entry->match_values_count);
2030         if (err) {
2031                 nla_nest_cancel(skb, matches_attr);
2032                 goto err_match_values_put;
2033         }
2034         nla_nest_end(skb, matches_attr);
2035
2036         actions_attr = nla_nest_start_noflag(skb,
2037                                              DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2038         if (!actions_attr)
2039                 goto nla_put_failure;
2040
2041         err = devlink_dpipe_action_values_put(skb, entry->action_values,
2042                                               entry->action_values_count);
2043         if (err) {
2044                 nla_nest_cancel(skb, actions_attr);
2045                 goto err_action_values_put;
2046         }
2047         nla_nest_end(skb, actions_attr);
2048
2049         nla_nest_end(skb, entry_attr);
2050         return 0;
2051
2052 nla_put_failure:
2053         err = -EMSGSIZE;
2054 err_match_values_put:
2055 err_action_values_put:
2056         nla_nest_cancel(skb, entry_attr);
2057         return err;
2058 }
2059
2060 static struct devlink_dpipe_table *
2061 devlink_dpipe_table_find(struct list_head *dpipe_tables,
2062                          const char *table_name)
2063 {
2064         struct devlink_dpipe_table *table;
2065
2066         list_for_each_entry_rcu(table, dpipe_tables, list) {
2067                 if (!strcmp(table->name, table_name))
2068                         return table;
2069         }
2070         return NULL;
2071 }
2072
2073 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2074 {
2075         struct devlink *devlink;
2076         int err;
2077
2078         err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2079                                                dump_ctx->info);
2080         if (err)
2081                 return err;
2082
2083         dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2084                                     dump_ctx->info->snd_portid,
2085                                     dump_ctx->info->snd_seq,
2086                                     &devlink_nl_family, NLM_F_MULTI,
2087                                     dump_ctx->cmd);
2088         if (!dump_ctx->hdr)
2089                 goto nla_put_failure;
2090
2091         devlink = dump_ctx->info->user_ptr[0];
2092         if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2093                 goto nla_put_failure;
2094         dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2095                                                DEVLINK_ATTR_DPIPE_ENTRIES);
2096         if (!dump_ctx->nest)
2097                 goto nla_put_failure;
2098         return 0;
2099
2100 nla_put_failure:
2101         nlmsg_free(dump_ctx->skb);
2102         return -EMSGSIZE;
2103 }
2104 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2105
2106 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2107                                    struct devlink_dpipe_entry *entry)
2108 {
2109         return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2110 }
2111 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2112
2113 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2114 {
2115         nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2116         genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2117         return 0;
2118 }
2119 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2120
2121 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2122
2123 {
2124         unsigned int value_count, value_index;
2125         struct devlink_dpipe_value *value;
2126
2127         value = entry->action_values;
2128         value_count = entry->action_values_count;
2129         for (value_index = 0; value_index < value_count; value_index++) {
2130                 kfree(value[value_index].value);
2131                 kfree(value[value_index].mask);
2132         }
2133
2134         value = entry->match_values;
2135         value_count = entry->match_values_count;
2136         for (value_index = 0; value_index < value_count; value_index++) {
2137                 kfree(value[value_index].value);
2138                 kfree(value[value_index].mask);
2139         }
2140 }
2141 EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2142
2143 static int devlink_dpipe_entries_fill(struct genl_info *info,
2144                                       enum devlink_command cmd, int flags,
2145                                       struct devlink_dpipe_table *table)
2146 {
2147         struct devlink_dpipe_dump_ctx dump_ctx;
2148         struct nlmsghdr *nlh;
2149         int err;
2150
2151         dump_ctx.skb = NULL;
2152         dump_ctx.cmd = cmd;
2153         dump_ctx.info = info;
2154
2155         err = table->table_ops->entries_dump(table->priv,
2156                                              table->counters_enabled,
2157                                              &dump_ctx);
2158         if (err)
2159                 return err;
2160
2161 send_done:
2162         nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2163                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2164         if (!nlh) {
2165                 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2166                 if (err)
2167                         return err;
2168                 goto send_done;
2169         }
2170         return genlmsg_reply(dump_ctx.skb, info);
2171 }
2172
2173 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2174                                             struct genl_info *info)
2175 {
2176         struct devlink *devlink = info->user_ptr[0];
2177         struct devlink_dpipe_table *table;
2178         const char *table_name;
2179
2180         if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2181                 return -EINVAL;
2182
2183         table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2184         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2185                                          table_name);
2186         if (!table)
2187                 return -EINVAL;
2188
2189         if (!table->table_ops->entries_dump)
2190                 return -EINVAL;
2191
2192         return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2193                                           0, table);
2194 }
2195
2196 static int devlink_dpipe_fields_put(struct sk_buff *skb,
2197                                     const struct devlink_dpipe_header *header)
2198 {
2199         struct devlink_dpipe_field *field;
2200         struct nlattr *field_attr;
2201         int i;
2202
2203         for (i = 0; i < header->fields_count; i++) {
2204                 field = &header->fields[i];
2205                 field_attr = nla_nest_start_noflag(skb,
2206                                                    DEVLINK_ATTR_DPIPE_FIELD);
2207                 if (!field_attr)
2208                         return -EMSGSIZE;
2209                 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2210                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2211                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2212                     nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2213                         goto nla_put_failure;
2214                 nla_nest_end(skb, field_attr);
2215         }
2216         return 0;
2217
2218 nla_put_failure:
2219         nla_nest_cancel(skb, field_attr);
2220         return -EMSGSIZE;
2221 }
2222
2223 static int devlink_dpipe_header_put(struct sk_buff *skb,
2224                                     struct devlink_dpipe_header *header)
2225 {
2226         struct nlattr *fields_attr, *header_attr;
2227         int err;
2228
2229         header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2230         if (!header_attr)
2231                 return -EMSGSIZE;
2232
2233         if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2234             nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2235             nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2236                 goto nla_put_failure;
2237
2238         fields_attr = nla_nest_start_noflag(skb,
2239                                             DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2240         if (!fields_attr)
2241                 goto nla_put_failure;
2242
2243         err = devlink_dpipe_fields_put(skb, header);
2244         if (err) {
2245                 nla_nest_cancel(skb, fields_attr);
2246                 goto nla_put_failure;
2247         }
2248         nla_nest_end(skb, fields_attr);
2249         nla_nest_end(skb, header_attr);
2250         return 0;
2251
2252 nla_put_failure:
2253         err = -EMSGSIZE;
2254         nla_nest_cancel(skb, header_attr);
2255         return err;
2256 }
2257
2258 static int devlink_dpipe_headers_fill(struct genl_info *info,
2259                                       enum devlink_command cmd, int flags,
2260                                       struct devlink_dpipe_headers *
2261                                       dpipe_headers)
2262 {
2263         struct devlink *devlink = info->user_ptr[0];
2264         struct nlattr *headers_attr;
2265         struct sk_buff *skb = NULL;
2266         struct nlmsghdr *nlh;
2267         void *hdr;
2268         int i, j;
2269         int err;
2270
2271         i = 0;
2272 start_again:
2273         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2274         if (err)
2275                 return err;
2276
2277         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2278                           &devlink_nl_family, NLM_F_MULTI, cmd);
2279         if (!hdr) {
2280                 nlmsg_free(skb);
2281                 return -EMSGSIZE;
2282         }
2283
2284         if (devlink_nl_put_handle(skb, devlink))
2285                 goto nla_put_failure;
2286         headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2287         if (!headers_attr)
2288                 goto nla_put_failure;
2289
2290         j = 0;
2291         for (; i < dpipe_headers->headers_count; i++) {
2292                 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2293                 if (err) {
2294                         if (!j)
2295                                 goto err_table_put;
2296                         break;
2297                 }
2298                 j++;
2299         }
2300         nla_nest_end(skb, headers_attr);
2301         genlmsg_end(skb, hdr);
2302         if (i != dpipe_headers->headers_count)
2303                 goto start_again;
2304
2305 send_done:
2306         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2307                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2308         if (!nlh) {
2309                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2310                 if (err)
2311                         return err;
2312                 goto send_done;
2313         }
2314         return genlmsg_reply(skb, info);
2315
2316 nla_put_failure:
2317         err = -EMSGSIZE;
2318 err_table_put:
2319         nlmsg_free(skb);
2320         return err;
2321 }
2322
2323 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2324                                             struct genl_info *info)
2325 {
2326         struct devlink *devlink = info->user_ptr[0];
2327
2328         if (!devlink->dpipe_headers)
2329                 return -EOPNOTSUPP;
2330         return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2331                                           0, devlink->dpipe_headers);
2332 }
2333
2334 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2335                                             const char *table_name,
2336                                             bool enable)
2337 {
2338         struct devlink_dpipe_table *table;
2339
2340         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2341                                          table_name);
2342         if (!table)
2343                 return -EINVAL;
2344
2345         if (table->counter_control_extern)
2346                 return -EOPNOTSUPP;
2347
2348         if (!(table->counters_enabled ^ enable))
2349                 return 0;
2350
2351         table->counters_enabled = enable;
2352         if (table->table_ops->counters_set_update)
2353                 table->table_ops->counters_set_update(table->priv, enable);
2354         return 0;
2355 }
2356
2357 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2358                                                    struct genl_info *info)
2359 {
2360         struct devlink *devlink = info->user_ptr[0];
2361         const char *table_name;
2362         bool counters_enable;
2363
2364         if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2365             !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2366                 return -EINVAL;
2367
2368         table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2369         counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2370
2371         return devlink_dpipe_table_counters_set(devlink, table_name,
2372                                                 counters_enable);
2373 }
2374
2375 static struct devlink_resource *
2376 devlink_resource_find(struct devlink *devlink,
2377                       struct devlink_resource *resource, u64 resource_id)
2378 {
2379         struct list_head *resource_list;
2380
2381         if (resource)
2382                 resource_list = &resource->resource_list;
2383         else
2384                 resource_list = &devlink->resource_list;
2385
2386         list_for_each_entry(resource, resource_list, list) {
2387                 struct devlink_resource *child_resource;
2388
2389                 if (resource->id == resource_id)
2390                         return resource;
2391
2392                 child_resource = devlink_resource_find(devlink, resource,
2393                                                        resource_id);
2394                 if (child_resource)
2395                         return child_resource;
2396         }
2397         return NULL;
2398 }
2399
2400 static void
2401 devlink_resource_validate_children(struct devlink_resource *resource)
2402 {
2403         struct devlink_resource *child_resource;
2404         bool size_valid = true;
2405         u64 parts_size = 0;
2406
2407         if (list_empty(&resource->resource_list))
2408                 goto out;
2409
2410         list_for_each_entry(child_resource, &resource->resource_list, list)
2411                 parts_size += child_resource->size_new;
2412
2413         if (parts_size > resource->size_new)
2414                 size_valid = false;
2415 out:
2416         resource->size_valid = size_valid;
2417 }
2418
2419 static int
2420 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2421                                struct netlink_ext_ack *extack)
2422 {
2423         u64 reminder;
2424         int err = 0;
2425
2426         if (size > resource->size_params.size_max) {
2427                 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2428                 err = -EINVAL;
2429         }
2430
2431         if (size < resource->size_params.size_min) {
2432                 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2433                 err = -EINVAL;
2434         }
2435
2436         div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2437         if (reminder) {
2438                 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2439                 err = -EINVAL;
2440         }
2441
2442         return err;
2443 }
2444
2445 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2446                                        struct genl_info *info)
2447 {
2448         struct devlink *devlink = info->user_ptr[0];
2449         struct devlink_resource *resource;
2450         u64 resource_id;
2451         u64 size;
2452         int err;
2453
2454         if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2455             !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2456                 return -EINVAL;
2457         resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2458
2459         resource = devlink_resource_find(devlink, NULL, resource_id);
2460         if (!resource)
2461                 return -EINVAL;
2462
2463         size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2464         err = devlink_resource_validate_size(resource, size, info->extack);
2465         if (err)
2466                 return err;
2467
2468         resource->size_new = size;
2469         devlink_resource_validate_children(resource);
2470         if (resource->parent)
2471                 devlink_resource_validate_children(resource->parent);
2472         return 0;
2473 }
2474
2475 static int
2476 devlink_resource_size_params_put(struct devlink_resource *resource,
2477                                  struct sk_buff *skb)
2478 {
2479         struct devlink_resource_size_params *size_params;
2480
2481         size_params = &resource->size_params;
2482         if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2483                               size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2484             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2485                               size_params->size_max, DEVLINK_ATTR_PAD) ||
2486             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2487                               size_params->size_min, DEVLINK_ATTR_PAD) ||
2488             nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2489                 return -EMSGSIZE;
2490         return 0;
2491 }
2492
2493 static int devlink_resource_occ_put(struct devlink_resource *resource,
2494                                     struct sk_buff *skb)
2495 {
2496         if (!resource->occ_get)
2497                 return 0;
2498         return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2499                                  resource->occ_get(resource->occ_get_priv),
2500                                  DEVLINK_ATTR_PAD);
2501 }
2502
2503 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2504                                 struct devlink_resource *resource)
2505 {
2506         struct devlink_resource *child_resource;
2507         struct nlattr *child_resource_attr;
2508         struct nlattr *resource_attr;
2509
2510         resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2511         if (!resource_attr)
2512                 return -EMSGSIZE;
2513
2514         if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2515             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2516                               DEVLINK_ATTR_PAD) ||
2517             nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2518                               DEVLINK_ATTR_PAD))
2519                 goto nla_put_failure;
2520         if (resource->size != resource->size_new)
2521                 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2522                                   resource->size_new, DEVLINK_ATTR_PAD);
2523         if (devlink_resource_occ_put(resource, skb))
2524                 goto nla_put_failure;
2525         if (devlink_resource_size_params_put(resource, skb))
2526                 goto nla_put_failure;
2527         if (list_empty(&resource->resource_list))
2528                 goto out;
2529
2530         if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2531                        resource->size_valid))
2532                 goto nla_put_failure;
2533
2534         child_resource_attr = nla_nest_start_noflag(skb,
2535                                                     DEVLINK_ATTR_RESOURCE_LIST);
2536         if (!child_resource_attr)
2537                 goto nla_put_failure;
2538
2539         list_for_each_entry(child_resource, &resource->resource_list, list) {
2540                 if (devlink_resource_put(devlink, skb, child_resource))
2541                         goto resource_put_failure;
2542         }
2543
2544         nla_nest_end(skb, child_resource_attr);
2545 out:
2546         nla_nest_end(skb, resource_attr);
2547         return 0;
2548
2549 resource_put_failure:
2550         nla_nest_cancel(skb, child_resource_attr);
2551 nla_put_failure:
2552         nla_nest_cancel(skb, resource_attr);
2553         return -EMSGSIZE;
2554 }
2555
2556 static int devlink_resource_fill(struct genl_info *info,
2557                                  enum devlink_command cmd, int flags)
2558 {
2559         struct devlink *devlink = info->user_ptr[0];
2560         struct devlink_resource *resource;
2561         struct nlattr *resources_attr;
2562         struct sk_buff *skb = NULL;
2563         struct nlmsghdr *nlh;
2564         bool incomplete;
2565         void *hdr;
2566         int i;
2567         int err;
2568
2569         resource = list_first_entry(&devlink->resource_list,
2570                                     struct devlink_resource, list);
2571 start_again:
2572         err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2573         if (err)
2574                 return err;
2575
2576         hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2577                           &devlink_nl_family, NLM_F_MULTI, cmd);
2578         if (!hdr) {
2579                 nlmsg_free(skb);
2580                 return -EMSGSIZE;
2581         }
2582
2583         if (devlink_nl_put_handle(skb, devlink))
2584                 goto nla_put_failure;
2585
2586         resources_attr = nla_nest_start_noflag(skb,
2587                                                DEVLINK_ATTR_RESOURCE_LIST);
2588         if (!resources_attr)
2589                 goto nla_put_failure;
2590
2591         incomplete = false;
2592         i = 0;
2593         list_for_each_entry_from(resource, &devlink->resource_list, list) {
2594                 err = devlink_resource_put(devlink, skb, resource);
2595                 if (err) {
2596                         if (!i)
2597                                 goto err_resource_put;
2598                         incomplete = true;
2599                         break;
2600                 }
2601                 i++;
2602         }
2603         nla_nest_end(skb, resources_attr);
2604         genlmsg_end(skb, hdr);
2605         if (incomplete)
2606                 goto start_again;
2607 send_done:
2608         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2609                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
2610         if (!nlh) {
2611                 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2612                 if (err)
2613                         return err;
2614                 goto send_done;
2615         }
2616         return genlmsg_reply(skb, info);
2617
2618 nla_put_failure:
2619         err = -EMSGSIZE;
2620 err_resource_put:
2621         nlmsg_free(skb);
2622         return err;
2623 }
2624
2625 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2626                                         struct genl_info *info)
2627 {
2628         struct devlink *devlink = info->user_ptr[0];
2629
2630         if (list_empty(&devlink->resource_list))
2631                 return -EOPNOTSUPP;
2632
2633         return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2634 }
2635
2636 static int
2637 devlink_resources_validate(struct devlink *devlink,
2638                            struct devlink_resource *resource,
2639                            struct genl_info *info)
2640 {
2641         struct list_head *resource_list;
2642         int err = 0;
2643
2644         if (resource)
2645                 resource_list = &resource->resource_list;
2646         else
2647                 resource_list = &devlink->resource_list;
2648
2649         list_for_each_entry(resource, resource_list, list) {
2650                 if (!resource->size_valid)
2651                         return -EINVAL;
2652                 err = devlink_resources_validate(devlink, resource, info);
2653                 if (err)
2654                         return err;
2655         }
2656         return err;
2657 }
2658
2659 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2660 {
2661         struct devlink *devlink = info->user_ptr[0];
2662         int err;
2663
2664         if (!devlink->ops->reload)
2665                 return -EOPNOTSUPP;
2666
2667         err = devlink_resources_validate(devlink, NULL, info);
2668         if (err) {
2669                 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2670                 return err;
2671         }
2672         return devlink->ops->reload(devlink, info->extack);
2673 }
2674
2675 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2676                                        struct genl_info *info)
2677 {
2678         struct devlink *devlink = info->user_ptr[0];
2679         const char *file_name, *component;
2680         struct nlattr *nla_component;
2681
2682         if (!devlink->ops->flash_update)
2683                 return -EOPNOTSUPP;
2684
2685         if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2686                 return -EINVAL;
2687         file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2688
2689         nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2690         component = nla_component ? nla_data(nla_component) : NULL;
2691
2692         return devlink->ops->flash_update(devlink, file_name, component,
2693                                           info->extack);
2694 }
2695
2696 static const struct devlink_param devlink_param_generic[] = {
2697         {
2698                 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2699                 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2700                 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2701         },
2702         {
2703                 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2704                 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2705                 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2706         },
2707         {
2708                 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2709                 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2710                 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2711         },
2712         {
2713                 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2714                 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2715                 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2716         },
2717         {
2718                 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2719                 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2720                 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2721         },
2722         {
2723                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2724                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2725                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2726         },
2727         {
2728                 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
2729                 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
2730                 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
2731         },
2732         {
2733                 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
2734                 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
2735                 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
2736         },
2737 };
2738
2739 static int devlink_param_generic_verify(const struct devlink_param *param)
2740 {
2741         /* verify it match generic parameter by id and name */
2742         if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2743                 return -EINVAL;
2744         if (strcmp(param->name, devlink_param_generic[param->id].name))
2745                 return -ENOENT;
2746
2747         WARN_ON(param->type != devlink_param_generic[param->id].type);
2748
2749         return 0;
2750 }
2751
2752 static int devlink_param_driver_verify(const struct devlink_param *param)
2753 {
2754         int i;
2755
2756         if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2757                 return -EINVAL;
2758         /* verify no such name in generic params */
2759         for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2760                 if (!strcmp(param->name, devlink_param_generic[i].name))
2761                         return -EEXIST;
2762
2763         return 0;
2764 }
2765
2766 static struct devlink_param_item *
2767 devlink_param_find_by_name(struct list_head *param_list,
2768                            const char *param_name)
2769 {
2770         struct devlink_param_item *param_item;
2771
2772         list_for_each_entry(param_item, param_list, list)
2773                 if (!strcmp(param_item->param->name, param_name))
2774                         return param_item;
2775         return NULL;
2776 }
2777
2778 static struct devlink_param_item *
2779 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2780 {
2781         struct devlink_param_item *param_item;
2782
2783         list_for_each_entry(param_item, param_list, list)
2784                 if (param_item->param->id == param_id)
2785                         return param_item;
2786         return NULL;
2787 }
2788
2789 static bool
2790 devlink_param_cmode_is_supported(const struct devlink_param *param,
2791                                  enum devlink_param_cmode cmode)
2792 {
2793         return test_bit(cmode, &param->supported_cmodes);
2794 }
2795
2796 static int devlink_param_get(struct devlink *devlink,
2797                              const struct devlink_param *param,
2798                              struct devlink_param_gset_ctx *ctx)
2799 {
2800         if (!param->get)
2801                 return -EOPNOTSUPP;
2802         return param->get(devlink, param->id, ctx);
2803 }
2804
2805 static int devlink_param_set(struct devlink *devlink,
2806                              const struct devlink_param *param,
2807                              struct devlink_param_gset_ctx *ctx)
2808 {
2809         if (!param->set)
2810                 return -EOPNOTSUPP;
2811         return param->set(devlink, param->id, ctx);
2812 }
2813
2814 static int
2815 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2816 {
2817         switch (param_type) {
2818         case DEVLINK_PARAM_TYPE_U8:
2819                 return NLA_U8;
2820         case DEVLINK_PARAM_TYPE_U16:
2821                 return NLA_U16;
2822         case DEVLINK_PARAM_TYPE_U32:
2823                 return NLA_U32;
2824         case DEVLINK_PARAM_TYPE_STRING:
2825                 return NLA_STRING;
2826         case DEVLINK_PARAM_TYPE_BOOL:
2827                 return NLA_FLAG;
2828         default:
2829                 return -EINVAL;
2830         }
2831 }
2832
2833 static int
2834 devlink_nl_param_value_fill_one(struct sk_buff *msg,
2835                                 enum devlink_param_type type,
2836                                 enum devlink_param_cmode cmode,
2837                                 union devlink_param_value val)
2838 {
2839         struct nlattr *param_value_attr;
2840
2841         param_value_attr = nla_nest_start_noflag(msg,
2842                                                  DEVLINK_ATTR_PARAM_VALUE);
2843         if (!param_value_attr)
2844                 goto nla_put_failure;
2845
2846         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
2847                 goto value_nest_cancel;
2848
2849         switch (type) {
2850         case DEVLINK_PARAM_TYPE_U8:
2851                 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
2852                         goto value_nest_cancel;
2853                 break;
2854         case DEVLINK_PARAM_TYPE_U16:
2855                 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
2856                         goto value_nest_cancel;
2857                 break;
2858         case DEVLINK_PARAM_TYPE_U32:
2859                 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
2860                         goto value_nest_cancel;
2861                 break;
2862         case DEVLINK_PARAM_TYPE_STRING:
2863                 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
2864                                    val.vstr))
2865                         goto value_nest_cancel;
2866                 break;
2867         case DEVLINK_PARAM_TYPE_BOOL:
2868                 if (val.vbool &&
2869                     nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
2870                         goto value_nest_cancel;
2871                 break;
2872         }
2873
2874         nla_nest_end(msg, param_value_attr);
2875         return 0;
2876
2877 value_nest_cancel:
2878         nla_nest_cancel(msg, param_value_attr);
2879 nla_put_failure:
2880         return -EMSGSIZE;
2881 }
2882
2883 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
2884                                  unsigned int port_index,
2885                                  struct devlink_param_item *param_item,
2886                                  enum devlink_command cmd,
2887                                  u32 portid, u32 seq, int flags)
2888 {
2889         union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
2890         bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
2891         const struct devlink_param *param = param_item->param;
2892         struct devlink_param_gset_ctx ctx;
2893         struct nlattr *param_values_list;
2894         struct nlattr *param_attr;
2895         int nla_type;
2896         void *hdr;
2897         int err;
2898         int i;
2899
2900         /* Get value from driver part to driverinit configuration mode */
2901         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
2902                 if (!devlink_param_cmode_is_supported(param, i))
2903                         continue;
2904                 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
2905                         if (!param_item->driverinit_value_valid)
2906                                 return -EOPNOTSUPP;
2907                         param_value[i] = param_item->driverinit_value;
2908                 } else {
2909                         if (!param_item->published)
2910                                 continue;
2911                         ctx.cmode = i;
2912                         err = devlink_param_get(devlink, param, &ctx);
2913                         if (err)
2914                                 return err;
2915                         param_value[i] = ctx.val;
2916                 }
2917                 param_value_set[i] = true;
2918         }
2919
2920         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2921         if (!hdr)
2922                 return -EMSGSIZE;
2923
2924         if (devlink_nl_put_handle(msg, devlink))
2925                 goto genlmsg_cancel;
2926
2927         if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
2928             cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
2929             cmd == DEVLINK_CMD_PORT_PARAM_DEL)
2930                 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
2931                         goto genlmsg_cancel;
2932
2933         param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
2934         if (!param_attr)
2935                 goto genlmsg_cancel;
2936         if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
2937                 goto param_nest_cancel;
2938         if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
2939                 goto param_nest_cancel;
2940
2941         nla_type = devlink_param_type_to_nla_type(param->type);
2942         if (nla_type < 0)
2943                 goto param_nest_cancel;
2944         if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
2945                 goto param_nest_cancel;
2946
2947         param_values_list = nla_nest_start_noflag(msg,
2948                                                   DEVLINK_ATTR_PARAM_VALUES_LIST);
2949         if (!param_values_list)
2950                 goto param_nest_cancel;
2951
2952         for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
2953                 if (!param_value_set[i])
2954                         continue;
2955                 err = devlink_nl_param_value_fill_one(msg, param->type,
2956                                                       i, param_value[i]);
2957                 if (err)
2958                         goto values_list_nest_cancel;
2959         }
2960
2961         nla_nest_end(msg, param_values_list);
2962         nla_nest_end(msg, param_attr);
2963         genlmsg_end(msg, hdr);
2964         return 0;
2965
2966 values_list_nest_cancel:
2967         nla_nest_end(msg, param_values_list);
2968 param_nest_cancel:
2969         nla_nest_cancel(msg, param_attr);
2970 genlmsg_cancel:
2971         genlmsg_cancel(msg, hdr);
2972         return -EMSGSIZE;
2973 }
2974
2975 static void devlink_param_notify(struct devlink *devlink,
2976                                  unsigned int port_index,
2977                                  struct devlink_param_item *param_item,
2978                                  enum devlink_command cmd)
2979 {
2980         struct sk_buff *msg;
2981         int err;
2982
2983         WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
2984                 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
2985                 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
2986
2987         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2988         if (!msg)
2989                 return;
2990         err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
2991                                     0, 0, 0);
2992         if (err) {
2993                 nlmsg_free(msg);
2994                 return;
2995         }
2996
2997         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2998                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2999 }
3000
3001 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3002                                            struct netlink_callback *cb)
3003 {
3004         struct devlink_param_item *param_item;
3005         struct devlink *devlink;
3006         int start = cb->args[0];
3007         int idx = 0;
3008         int err;
3009
3010         mutex_lock(&devlink_mutex);
3011         list_for_each_entry(devlink, &devlink_list, list) {
3012                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3013                         continue;
3014                 mutex_lock(&devlink->lock);
3015                 list_for_each_entry(param_item, &devlink->param_list, list) {
3016                         if (idx < start) {
3017                                 idx++;
3018                                 continue;
3019                         }
3020                         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3021                                                     DEVLINK_CMD_PARAM_GET,
3022                                                     NETLINK_CB(cb->skb).portid,
3023                                                     cb->nlh->nlmsg_seq,
3024                                                     NLM_F_MULTI);
3025                         if (err) {
3026                                 mutex_unlock(&devlink->lock);
3027                                 goto out;
3028                         }
3029                         idx++;
3030                 }
3031                 mutex_unlock(&devlink->lock);
3032         }
3033 out:
3034         mutex_unlock(&devlink_mutex);
3035
3036         cb->args[0] = idx;
3037         return msg->len;
3038 }
3039
3040 static int
3041 devlink_param_type_get_from_info(struct genl_info *info,
3042                                  enum devlink_param_type *param_type)
3043 {
3044         if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3045                 return -EINVAL;
3046
3047         switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3048         case NLA_U8:
3049                 *param_type = DEVLINK_PARAM_TYPE_U8;
3050                 break;
3051         case NLA_U16:
3052                 *param_type = DEVLINK_PARAM_TYPE_U16;
3053                 break;
3054         case NLA_U32:
3055                 *param_type = DEVLINK_PARAM_TYPE_U32;
3056                 break;
3057         case NLA_STRING:
3058                 *param_type = DEVLINK_PARAM_TYPE_STRING;
3059                 break;
3060         case NLA_FLAG:
3061                 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3062                 break;
3063         default:
3064                 return -EINVAL;
3065         }
3066
3067         return 0;
3068 }
3069
3070 static int
3071 devlink_param_value_get_from_info(const struct devlink_param *param,
3072                                   struct genl_info *info,
3073                                   union devlink_param_value *value)
3074 {
3075         int len;
3076
3077         if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
3078             !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
3079                 return -EINVAL;
3080
3081         switch (param->type) {
3082         case DEVLINK_PARAM_TYPE_U8:
3083                 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3084                 break;
3085         case DEVLINK_PARAM_TYPE_U16:
3086                 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3087                 break;
3088         case DEVLINK_PARAM_TYPE_U32:
3089                 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3090                 break;
3091         case DEVLINK_PARAM_TYPE_STRING:
3092                 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
3093                               nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3094                 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
3095                     len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3096                         return -EINVAL;
3097                 strcpy(value->vstr,
3098                        nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3099                 break;
3100         case DEVLINK_PARAM_TYPE_BOOL:
3101                 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
3102                                true : false;
3103                 break;
3104         }
3105         return 0;
3106 }
3107
3108 static struct devlink_param_item *
3109 devlink_param_get_from_info(struct list_head *param_list,
3110                             struct genl_info *info)
3111 {
3112         char *param_name;
3113
3114         if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3115                 return NULL;
3116
3117         param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3118         return devlink_param_find_by_name(param_list, param_name);
3119 }
3120
3121 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3122                                          struct genl_info *info)
3123 {
3124         struct devlink *devlink = info->user_ptr[0];
3125         struct devlink_param_item *param_item;
3126         struct sk_buff *msg;
3127         int err;
3128
3129         param_item = devlink_param_get_from_info(&devlink->param_list, info);
3130         if (!param_item)
3131                 return -EINVAL;
3132
3133         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3134         if (!msg)
3135                 return -ENOMEM;
3136
3137         err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3138                                     DEVLINK_CMD_PARAM_GET,
3139                                     info->snd_portid, info->snd_seq, 0);
3140         if (err) {
3141                 nlmsg_free(msg);
3142                 return err;
3143         }
3144
3145         return genlmsg_reply(msg, info);
3146 }
3147
3148 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3149                                            unsigned int port_index,
3150                                            struct list_head *param_list,
3151                                            struct genl_info *info,
3152                                            enum devlink_command cmd)
3153 {
3154         enum devlink_param_type param_type;
3155         struct devlink_param_gset_ctx ctx;
3156         enum devlink_param_cmode cmode;
3157         struct devlink_param_item *param_item;
3158         const struct devlink_param *param;
3159         union devlink_param_value value;
3160         int err = 0;
3161
3162         param_item = devlink_param_get_from_info(param_list, info);
3163         if (!param_item)
3164                 return -EINVAL;
3165         param = param_item->param;
3166         err = devlink_param_type_get_from_info(info, &param_type);
3167         if (err)
3168                 return err;
3169         if (param_type != param->type)
3170                 return -EINVAL;
3171         err = devlink_param_value_get_from_info(param, info, &value);
3172         if (err)
3173                 return err;
3174         if (param->validate) {
3175                 err = param->validate(devlink, param->id, value, info->extack);
3176                 if (err)
3177                         return err;
3178         }
3179
3180         if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3181                 return -EINVAL;
3182         cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3183         if (!devlink_param_cmode_is_supported(param, cmode))
3184                 return -EOPNOTSUPP;
3185
3186         if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3187                 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3188                         strcpy(param_item->driverinit_value.vstr, value.vstr);
3189                 else
3190                         param_item->driverinit_value = value;
3191                 param_item->driverinit_value_valid = true;
3192         } else {
3193                 if (!param->set)
3194                         return -EOPNOTSUPP;
3195                 ctx.val = value;
3196                 ctx.cmode = cmode;
3197                 err = devlink_param_set(devlink, param, &ctx);
3198                 if (err)
3199                         return err;
3200         }
3201
3202         devlink_param_notify(devlink, port_index, param_item, cmd);
3203         return 0;
3204 }
3205
3206 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3207                                          struct genl_info *info)
3208 {
3209         struct devlink *devlink = info->user_ptr[0];
3210
3211         return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3212                                                info, DEVLINK_CMD_PARAM_NEW);
3213 }
3214
3215 static int devlink_param_register_one(struct devlink *devlink,
3216                                       unsigned int port_index,
3217                                       struct list_head *param_list,
3218                                       const struct devlink_param *param,
3219                                       enum devlink_command cmd)
3220 {
3221         struct devlink_param_item *param_item;
3222
3223         if (devlink_param_find_by_name(param_list, param->name))
3224                 return -EEXIST;
3225
3226         if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3227                 WARN_ON(param->get || param->set);
3228         else
3229                 WARN_ON(!param->get || !param->set);
3230
3231         param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3232         if (!param_item)
3233                 return -ENOMEM;
3234         param_item->param = param;
3235
3236         list_add_tail(&param_item->list, param_list);
3237         devlink_param_notify(devlink, port_index, param_item, cmd);
3238         return 0;
3239 }
3240
3241 static void devlink_param_unregister_one(struct devlink *devlink,
3242                                          unsigned int port_index,
3243                                          struct list_head *param_list,
3244                                          const struct devlink_param *param,
3245                                          enum devlink_command cmd)
3246 {
3247         struct devlink_param_item *param_item;
3248
3249         param_item = devlink_param_find_by_name(param_list, param->name);
3250         WARN_ON(!param_item);
3251         devlink_param_notify(devlink, port_index, param_item, cmd);
3252         list_del(&param_item->list);
3253         kfree(param_item);
3254 }
3255
3256 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3257                                                 struct netlink_callback *cb)
3258 {
3259         struct devlink_param_item *param_item;
3260         struct devlink_port *devlink_port;
3261         struct devlink *devlink;
3262         int start = cb->args[0];
3263         int idx = 0;
3264         int err;
3265
3266         mutex_lock(&devlink_mutex);
3267         list_for_each_entry(devlink, &devlink_list, list) {
3268                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3269                         continue;
3270                 mutex_lock(&devlink->lock);
3271                 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3272                         list_for_each_entry(param_item,
3273                                             &devlink_port->param_list, list) {
3274                                 if (idx < start) {
3275                                         idx++;
3276                                         continue;
3277                                 }
3278                                 err = devlink_nl_param_fill(msg,
3279                                                 devlink_port->devlink,
3280                                                 devlink_port->index, param_item,
3281                                                 DEVLINK_CMD_PORT_PARAM_GET,
3282                                                 NETLINK_CB(cb->skb).portid,
3283                                                 cb->nlh->nlmsg_seq,
3284                                                 NLM_F_MULTI);
3285                                 if (err) {
3286                                         mutex_unlock(&devlink->lock);
3287                                         goto out;
3288                                 }
3289                                 idx++;
3290                         }
3291                 }
3292                 mutex_unlock(&devlink->lock);
3293         }
3294 out:
3295         mutex_unlock(&devlink_mutex);
3296
3297         cb->args[0] = idx;
3298         return msg->len;
3299 }
3300
3301 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3302                                               struct genl_info *info)
3303 {
3304         struct devlink_port *devlink_port = info->user_ptr[0];
3305         struct devlink_param_item *param_item;
3306         struct sk_buff *msg;
3307         int err;
3308
3309         param_item = devlink_param_get_from_info(&devlink_port->param_list,
3310                                                  info);
3311         if (!param_item)
3312                 return -EINVAL;
3313
3314         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3315         if (!msg)
3316                 return -ENOMEM;
3317
3318         err = devlink_nl_param_fill(msg, devlink_port->devlink,
3319                                     devlink_port->index, param_item,
3320                                     DEVLINK_CMD_PORT_PARAM_GET,
3321                                     info->snd_portid, info->snd_seq, 0);
3322         if (err) {
3323                 nlmsg_free(msg);
3324                 return err;
3325         }
3326
3327         return genlmsg_reply(msg, info);
3328 }
3329
3330 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3331                                               struct genl_info *info)
3332 {
3333         struct devlink_port *devlink_port = info->user_ptr[0];
3334
3335         return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3336                                                devlink_port->index,
3337                                                &devlink_port->param_list, info,
3338                                                DEVLINK_CMD_PORT_PARAM_NEW);
3339 }
3340
3341 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3342                                              struct devlink *devlink,
3343                                              struct devlink_snapshot *snapshot)
3344 {
3345         struct nlattr *snap_attr;
3346         int err;
3347
3348         snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3349         if (!snap_attr)
3350                 return -EINVAL;
3351
3352         err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3353         if (err)
3354                 goto nla_put_failure;
3355
3356         nla_nest_end(msg, snap_attr);
3357         return 0;
3358
3359 nla_put_failure:
3360         nla_nest_cancel(msg, snap_attr);
3361         return err;
3362 }
3363
3364 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3365                                               struct devlink *devlink,
3366                                               struct devlink_region *region)
3367 {
3368         struct devlink_snapshot *snapshot;
3369         struct nlattr *snapshots_attr;
3370         int err;
3371
3372         snapshots_attr = nla_nest_start_noflag(msg,
3373                                                DEVLINK_ATTR_REGION_SNAPSHOTS);
3374         if (!snapshots_attr)
3375                 return -EINVAL;
3376
3377         list_for_each_entry(snapshot, &region->snapshot_list, list) {
3378                 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3379                 if (err)
3380                         goto nla_put_failure;
3381         }
3382
3383         nla_nest_end(msg, snapshots_attr);
3384         return 0;
3385
3386 nla_put_failure:
3387         nla_nest_cancel(msg, snapshots_attr);
3388         return err;
3389 }
3390
3391 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3392                                   enum devlink_command cmd, u32 portid,
3393                                   u32 seq, int flags,
3394                                   struct devlink_region *region)
3395 {
3396         void *hdr;
3397         int err;
3398
3399         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3400         if (!hdr)
3401                 return -EMSGSIZE;
3402
3403         err = devlink_nl_put_handle(msg, devlink);
3404         if (err)
3405                 goto nla_put_failure;
3406
3407         err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3408         if (err)
3409                 goto nla_put_failure;
3410
3411         err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3412                                 region->size,
3413                                 DEVLINK_ATTR_PAD);
3414         if (err)
3415                 goto nla_put_failure;
3416
3417         err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3418         if (err)
3419                 goto nla_put_failure;
3420
3421         genlmsg_end(msg, hdr);
3422         return 0;
3423
3424 nla_put_failure:
3425         genlmsg_cancel(msg, hdr);
3426         return err;
3427 }
3428
3429 static void devlink_nl_region_notify(struct devlink_region *region,
3430                                      struct devlink_snapshot *snapshot,
3431                                      enum devlink_command cmd)
3432 {
3433         struct devlink *devlink = region->devlink;
3434         struct sk_buff *msg;
3435         void *hdr;
3436         int err;
3437
3438         WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3439
3440         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3441         if (!msg)
3442                 return;
3443
3444         hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3445         if (!hdr)
3446                 goto out_free_msg;
3447
3448         err = devlink_nl_put_handle(msg, devlink);
3449         if (err)
3450                 goto out_cancel_msg;
3451
3452         err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3453                              region->name);
3454         if (err)
3455                 goto out_cancel_msg;
3456
3457         if (snapshot) {
3458                 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3459                                   snapshot->id);
3460                 if (err)
3461                         goto out_cancel_msg;
3462         } else {
3463                 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3464                                         region->size, DEVLINK_ATTR_PAD);
3465                 if (err)
3466                         goto out_cancel_msg;
3467         }
3468         genlmsg_end(msg, hdr);
3469
3470         genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3471                                 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3472
3473         return;
3474
3475 out_cancel_msg:
3476         genlmsg_cancel(msg, hdr);
3477 out_free_msg:
3478         nlmsg_free(msg);
3479 }
3480
3481 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3482                                           struct genl_info *info)
3483 {
3484         struct devlink *devlink = info->user_ptr[0];
3485         struct devlink_region *region;
3486         const char *region_name;
3487         struct sk_buff *msg;
3488         int err;
3489
3490         if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3491                 return -EINVAL;
3492
3493         region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3494         region = devlink_region_get_by_name(devlink, region_name);
3495         if (!region)
3496                 return -EINVAL;
3497
3498         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3499         if (!msg)
3500                 return -ENOMEM;
3501
3502         err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3503                                      info->snd_portid, info->snd_seq, 0,
3504                                      region);
3505         if (err) {
3506                 nlmsg_free(msg);
3507                 return err;
3508         }
3509
3510         return genlmsg_reply(msg, info);
3511 }
3512
3513 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3514                                             struct netlink_callback *cb)
3515 {
3516         struct devlink_region *region;
3517         struct devlink *devlink;
3518         int start = cb->args[0];
3519         int idx = 0;
3520         int err;
3521
3522         mutex_lock(&devlink_mutex);
3523         list_for_each_entry(devlink, &devlink_list, list) {
3524                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3525                         continue;
3526
3527                 mutex_lock(&devlink->lock);
3528                 list_for_each_entry(region, &devlink->region_list, list) {
3529                         if (idx < start) {
3530                                 idx++;
3531                                 continue;
3532                         }
3533                         err = devlink_nl_region_fill(msg, devlink,
3534                                                      DEVLINK_CMD_REGION_GET,
3535                                                      NETLINK_CB(cb->skb).portid,
3536                                                      cb->nlh->nlmsg_seq,
3537                                                      NLM_F_MULTI, region);
3538                         if (err) {
3539                                 mutex_unlock(&devlink->lock);
3540                                 goto out;
3541                         }
3542                         idx++;
3543                 }
3544                 mutex_unlock(&devlink->lock);
3545         }
3546 out:
3547         mutex_unlock(&devlink_mutex);
3548         cb->args[0] = idx;
3549         return msg->len;
3550 }
3551
3552 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3553                                      struct genl_info *info)
3554 {
3555         struct devlink *devlink = info->user_ptr[0];
3556         struct devlink_snapshot *snapshot;
3557         struct devlink_region *region;
3558         const char *region_name;
3559         u32 snapshot_id;
3560
3561         if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3562             !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3563                 return -EINVAL;
3564
3565         region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3566         snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3567
3568         region = devlink_region_get_by_name(devlink, region_name);
3569         if (!region)
3570                 return -EINVAL;
3571
3572         snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3573         if (!snapshot)
3574                 return -EINVAL;
3575
3576         devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3577         devlink_region_snapshot_del(snapshot);
3578         return 0;
3579 }
3580
3581 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3582                                                  struct devlink *devlink,
3583                                                  u8 *chunk, u32 chunk_size,
3584                                                  u64 addr)
3585 {
3586         struct nlattr *chunk_attr;
3587         int err;
3588
3589         chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
3590         if (!chunk_attr)
3591                 return -EINVAL;
3592
3593         err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3594         if (err)
3595                 goto nla_put_failure;
3596
3597         err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3598                                 DEVLINK_ATTR_PAD);
3599         if (err)
3600                 goto nla_put_failure;
3601
3602         nla_nest_end(msg, chunk_attr);
3603         return 0;
3604
3605 nla_put_failure:
3606         nla_nest_cancel(msg, chunk_attr);
3607         return err;
3608 }
3609
3610 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
3611
3612 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3613                                                 struct devlink *devlink,
3614                                                 struct devlink_region *region,
3615                                                 struct nlattr **attrs,
3616                                                 u64 start_offset,
3617                                                 u64 end_offset,
3618                                                 bool dump,
3619                                                 u64 *new_offset)
3620 {
3621         struct devlink_snapshot *snapshot;
3622         u64 curr_offset = start_offset;
3623         u32 snapshot_id;
3624         int err = 0;
3625
3626         *new_offset = start_offset;
3627
3628         snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3629         snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3630         if (!snapshot)
3631                 return -EINVAL;
3632
3633         if (end_offset > snapshot->data_len || dump)
3634                 end_offset = snapshot->data_len;
3635
3636         while (curr_offset < end_offset) {
3637                 u32 data_size;
3638                 u8 *data;
3639
3640                 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3641                         data_size = end_offset - curr_offset;
3642                 else
3643                         data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3644
3645                 data = &snapshot->data[curr_offset];
3646                 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3647                                                             data, data_size,
3648                                                             curr_offset);
3649                 if (err)
3650                         break;
3651
3652                 curr_offset += data_size;
3653         }
3654         *new_offset = curr_offset;
3655
3656         return err;
3657 }
3658
3659 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3660                                              struct netlink_callback *cb)
3661 {
3662         u64 ret_offset, start_offset, end_offset = 0;
3663         struct devlink_region *region;
3664         struct nlattr *chunks_attr;
3665         const char *region_name;
3666         struct devlink *devlink;
3667         struct nlattr **attrs;
3668         bool dump = true;
3669         void *hdr;
3670         int err;
3671
3672         start_offset = *((u64 *)&cb->args[0]);
3673
3674         attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
3675         if (!attrs)
3676                 return -ENOMEM;
3677
3678         err = nlmsg_parse_deprecated(cb->nlh,
3679                                      GENL_HDRLEN + devlink_nl_family.hdrsize,
3680                                      attrs, DEVLINK_ATTR_MAX,
3681                                      devlink_nl_family.policy, cb->extack);
3682         if (err)
3683                 goto out_free;
3684
3685         mutex_lock(&devlink_mutex);
3686         devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3687         if (IS_ERR(devlink)) {
3688                 err = PTR_ERR(devlink);
3689                 goto out_dev;
3690         }
3691
3692         mutex_lock(&devlink->lock);
3693
3694         if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3695             !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
3696                 err = -EINVAL;
3697                 goto out_unlock;
3698         }
3699
3700         region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3701         region = devlink_region_get_by_name(devlink, region_name);
3702         if (!region) {
3703                 err = -EINVAL;
3704                 goto out_unlock;
3705         }
3706
3707         hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3708                           &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3709                           DEVLINK_CMD_REGION_READ);
3710         if (!hdr) {
3711                 err = -EMSGSIZE;
3712                 goto out_unlock;
3713         }
3714
3715         err = devlink_nl_put_handle(skb, devlink);
3716         if (err)
3717                 goto nla_put_failure;
3718
3719         err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3720         if (err)
3721                 goto nla_put_failure;
3722
3723         chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
3724         if (!chunks_attr) {
3725                 err = -EMSGSIZE;
3726                 goto nla_put_failure;
3727         }
3728
3729         if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3730             attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3731                 if (!start_offset)
3732                         start_offset =
3733                                 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3734
3735                 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3736                 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3737                 dump = false;
3738         }
3739
3740         err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3741                                                    region, attrs,
3742                                                    start_offset,
3743                                                    end_offset, dump,
3744                                                    &ret_offset);
3745
3746         if (err && err != -EMSGSIZE)
3747                 goto nla_put_failure;
3748
3749         /* Check if there was any progress done to prevent infinite loop */
3750         if (ret_offset == start_offset) {
3751                 err = -EINVAL;
3752                 goto nla_put_failure;
3753         }
3754
3755         *((u64 *)&cb->args[0]) = ret_offset;
3756
3757         nla_nest_end(skb, chunks_attr);
3758         genlmsg_end(skb, hdr);
3759         mutex_unlock(&devlink->lock);
3760         mutex_unlock(&devlink_mutex);
3761         kfree(attrs);
3762
3763         return skb->len;
3764
3765 nla_put_failure:
3766         genlmsg_cancel(skb, hdr);
3767 out_unlock:
3768         mutex_unlock(&devlink->lock);
3769 out_dev:
3770         mutex_unlock(&devlink_mutex);
3771 out_free:
3772         kfree(attrs);
3773         return err;
3774 }
3775
3776 struct devlink_info_req {
3777         struct sk_buff *msg;
3778 };
3779
3780 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3781 {
3782         return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3783 }
3784 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3785
3786 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3787 {
3788         return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3789 }
3790 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3791
3792 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
3793                                     const char *version_name,
3794                                     const char *version_value)
3795 {
3796         struct nlattr *nest;
3797         int err;
3798
3799         nest = nla_nest_start_noflag(req->msg, attr);
3800         if (!nest)
3801                 return -EMSGSIZE;
3802
3803         err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
3804                              version_name);
3805         if (err)
3806                 goto nla_put_failure;
3807
3808         err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
3809                              version_value);
3810         if (err)
3811                 goto nla_put_failure;
3812
3813         nla_nest_end(req->msg, nest);
3814
3815         return 0;
3816
3817 nla_put_failure:
3818         nla_nest_cancel(req->msg, nest);
3819         return err;
3820 }
3821
3822 int devlink_info_version_fixed_put(struct devlink_info_req *req,
3823                                    const char *version_name,
3824                                    const char *version_value)
3825 {
3826         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
3827                                         version_name, version_value);
3828 }
3829 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
3830
3831 int devlink_info_version_stored_put(struct devlink_info_req *req,
3832                                     const char *version_name,
3833                                     const char *version_value)
3834 {
3835         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
3836                                         version_name, version_value);
3837 }
3838 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
3839
3840 int devlink_info_version_running_put(struct devlink_info_req *req,
3841                                      const char *version_name,
3842                                      const char *version_value)
3843 {
3844         return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
3845                                         version_name, version_value);
3846 }
3847 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
3848
3849 static int
3850 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
3851                      enum devlink_command cmd, u32 portid,
3852                      u32 seq, int flags, struct netlink_ext_ack *extack)
3853 {
3854         struct devlink_info_req req;
3855         void *hdr;
3856         int err;
3857
3858         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3859         if (!hdr)
3860                 return -EMSGSIZE;
3861
3862         err = -EMSGSIZE;
3863         if (devlink_nl_put_handle(msg, devlink))
3864                 goto err_cancel_msg;
3865
3866         req.msg = msg;
3867         err = devlink->ops->info_get(devlink, &req, extack);
3868         if (err)
3869                 goto err_cancel_msg;
3870
3871         genlmsg_end(msg, hdr);
3872         return 0;
3873
3874 err_cancel_msg:
3875         genlmsg_cancel(msg, hdr);
3876         return err;
3877 }
3878
3879 static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
3880                                         struct genl_info *info)
3881 {
3882         struct devlink *devlink = info->user_ptr[0];
3883         struct sk_buff *msg;
3884         int err;
3885
3886         if (!devlink->ops->info_get)
3887                 return -EOPNOTSUPP;
3888
3889         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3890         if (!msg)
3891                 return -ENOMEM;
3892
3893         err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
3894                                    info->snd_portid, info->snd_seq, 0,
3895                                    info->extack);
3896         if (err) {
3897                 nlmsg_free(msg);
3898                 return err;
3899         }
3900
3901         return genlmsg_reply(msg, info);
3902 }
3903
3904 static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
3905                                           struct netlink_callback *cb)
3906 {
3907         struct devlink *devlink;
3908         int start = cb->args[0];
3909         int idx = 0;
3910         int err;
3911
3912         mutex_lock(&devlink_mutex);
3913         list_for_each_entry(devlink, &devlink_list, list) {
3914                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3915                         continue;
3916                 if (idx < start) {
3917                         idx++;
3918                         continue;
3919                 }
3920
3921                 if (!devlink->ops->info_get) {
3922                         idx++;
3923                         continue;
3924                 }
3925
3926                 mutex_lock(&devlink->lock);
3927                 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
3928                                            NETLINK_CB(cb->skb).portid,
3929                                            cb->nlh->nlmsg_seq, NLM_F_MULTI,
3930                                            cb->extack);
3931                 mutex_unlock(&devlink->lock);
3932                 if (err)
3933                         break;
3934                 idx++;
3935         }
3936         mutex_unlock(&devlink_mutex);
3937
3938         cb->args[0] = idx;
3939         return msg->len;
3940 }
3941
3942 struct devlink_fmsg_item {
3943         struct list_head list;
3944         int attrtype;
3945         u8 nla_type;
3946         u16 len;
3947         int value[0];
3948 };
3949
3950 struct devlink_fmsg {
3951         struct list_head item_list;
3952 };
3953
3954 static struct devlink_fmsg *devlink_fmsg_alloc(void)
3955 {
3956         struct devlink_fmsg *fmsg;
3957
3958         fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
3959         if (!fmsg)
3960                 return NULL;
3961
3962         INIT_LIST_HEAD(&fmsg->item_list);
3963
3964         return fmsg;
3965 }
3966
3967 static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
3968 {
3969         struct devlink_fmsg_item *item, *tmp;
3970
3971         list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
3972                 list_del(&item->list);
3973                 kfree(item);
3974         }
3975         kfree(fmsg);
3976 }
3977
3978 static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
3979                                     int attrtype)
3980 {
3981         struct devlink_fmsg_item *item;
3982
3983         item = kzalloc(sizeof(*item), GFP_KERNEL);
3984         if (!item)
3985                 return -ENOMEM;
3986
3987         item->attrtype = attrtype;
3988         list_add_tail(&item->list, &fmsg->item_list);
3989
3990         return 0;
3991 }
3992
3993 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
3994 {
3995         return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
3996 }
3997 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
3998
3999 static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4000 {
4001         return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4002 }
4003
4004 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4005 {
4006         return devlink_fmsg_nest_end(fmsg);
4007 }
4008 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4009
4010 #define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4011
4012 static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4013 {
4014         struct devlink_fmsg_item *item;
4015
4016         if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4017                 return -EMSGSIZE;
4018
4019         item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4020         if (!item)
4021                 return -ENOMEM;
4022
4023         item->nla_type = NLA_NUL_STRING;
4024         item->len = strlen(name) + 1;
4025         item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4026         memcpy(&item->value, name, item->len);
4027         list_add_tail(&item->list, &fmsg->item_list);
4028
4029         return 0;
4030 }
4031
4032 int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4033 {
4034         int err;
4035
4036         err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4037         if (err)
4038                 return err;
4039
4040         err = devlink_fmsg_put_name(fmsg, name);
4041         if (err)
4042                 return err;
4043
4044         return 0;
4045 }
4046 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4047
4048 int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4049 {
4050         return devlink_fmsg_nest_end(fmsg);
4051 }
4052 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4053
4054 int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4055                                      const char *name)
4056 {
4057         int err;
4058
4059         err = devlink_fmsg_pair_nest_start(fmsg, name);
4060         if (err)
4061                 return err;
4062
4063         err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4064         if (err)
4065                 return err;
4066
4067         return 0;
4068 }
4069 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4070
4071 int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4072 {
4073         int err;
4074
4075         err = devlink_fmsg_nest_end(fmsg);
4076         if (err)
4077                 return err;
4078
4079         err = devlink_fmsg_nest_end(fmsg);
4080         if (err)
4081                 return err;
4082
4083         return 0;
4084 }
4085 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4086
4087 static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4088                                   const void *value, u16 value_len,
4089                                   u8 value_nla_type)
4090 {
4091         struct devlink_fmsg_item *item;
4092
4093         if (value_len > DEVLINK_FMSG_MAX_SIZE)
4094                 return -EMSGSIZE;
4095
4096         item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4097         if (!item)
4098                 return -ENOMEM;
4099
4100         item->nla_type = value_nla_type;
4101         item->len = value_len;
4102         item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4103         memcpy(&item->value, value, item->len);
4104         list_add_tail(&item->list, &fmsg->item_list);
4105
4106         return 0;
4107 }
4108
4109 int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4110 {
4111         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4112 }
4113 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4114
4115 int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4116 {
4117         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4118 }
4119 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4120
4121 int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4122 {
4123         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4124 }
4125 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4126
4127 int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4128 {
4129         return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4130 }
4131 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4132
4133 int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4134 {
4135         return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4136                                       NLA_NUL_STRING);
4137 }
4138 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4139
4140 int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4141                             u16 value_len)
4142 {
4143         return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4144 }
4145 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4146
4147 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4148                                bool value)
4149 {
4150         int err;
4151
4152         err = devlink_fmsg_pair_nest_start(fmsg, name);
4153         if (err)
4154                 return err;
4155
4156         err = devlink_fmsg_bool_put(fmsg, value);
4157         if (err)
4158                 return err;
4159
4160         err = devlink_fmsg_pair_nest_end(fmsg);
4161         if (err)
4162                 return err;
4163
4164         return 0;
4165 }
4166 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4167
4168 int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4169                              u8 value)
4170 {
4171         int err;
4172
4173         err = devlink_fmsg_pair_nest_start(fmsg, name);
4174         if (err)
4175                 return err;
4176
4177         err = devlink_fmsg_u8_put(fmsg, value);
4178         if (err)
4179                 return err;
4180
4181         err = devlink_fmsg_pair_nest_end(fmsg);
4182         if (err)
4183                 return err;
4184
4185         return 0;
4186 }
4187 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4188
4189 int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4190                               u32 value)
4191 {
4192         int err;
4193
4194         err = devlink_fmsg_pair_nest_start(fmsg, name);
4195         if (err)
4196                 return err;
4197
4198         err = devlink_fmsg_u32_put(fmsg, value);
4199         if (err)
4200                 return err;
4201
4202         err = devlink_fmsg_pair_nest_end(fmsg);
4203         if (err)
4204                 return err;
4205
4206         return 0;
4207 }
4208 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4209
4210 int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4211                               u64 value)
4212 {
4213         int err;
4214
4215         err = devlink_fmsg_pair_nest_start(fmsg, name);
4216         if (err)
4217                 return err;
4218
4219         err = devlink_fmsg_u64_put(fmsg, value);
4220         if (err)
4221                 return err;
4222
4223         err = devlink_fmsg_pair_nest_end(fmsg);
4224         if (err)
4225                 return err;
4226
4227         return 0;
4228 }
4229 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4230
4231 int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4232                                  const char *value)
4233 {
4234         int err;
4235
4236         err = devlink_fmsg_pair_nest_start(fmsg, name);
4237         if (err)
4238                 return err;
4239
4240         err = devlink_fmsg_string_put(fmsg, value);
4241         if (err)
4242                 return err;
4243
4244         err = devlink_fmsg_pair_nest_end(fmsg);
4245         if (err)
4246                 return err;
4247
4248         return 0;
4249 }
4250 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4251
4252 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4253                                  const void *value, u16 value_len)
4254 {
4255         int err;
4256
4257         err = devlink_fmsg_pair_nest_start(fmsg, name);
4258         if (err)
4259                 return err;
4260
4261         err = devlink_fmsg_binary_put(fmsg, value, value_len);
4262         if (err)
4263                 return err;
4264
4265         err = devlink_fmsg_pair_nest_end(fmsg);
4266         if (err)
4267                 return err;
4268
4269         return 0;
4270 }
4271 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4272
4273 static int
4274 devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4275 {
4276         switch (msg->nla_type) {
4277         case NLA_FLAG:
4278         case NLA_U8:
4279         case NLA_U32:
4280         case NLA_U64:
4281         case NLA_NUL_STRING:
4282         case NLA_BINARY:
4283                 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4284                                   msg->nla_type);
4285         default:
4286                 return -EINVAL;
4287         }
4288 }
4289
4290 static int
4291 devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4292 {
4293         int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4294         u8 tmp;
4295
4296         switch (msg->nla_type) {
4297         case NLA_FLAG:
4298                 /* Always provide flag data, regardless of its value */
4299                 tmp = *(bool *) msg->value;
4300
4301                 return nla_put_u8(skb, attrtype, tmp);
4302         case NLA_U8:
4303                 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4304         case NLA_U32:
4305                 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4306         case NLA_U64:
4307                 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4308                                          DEVLINK_ATTR_PAD);
4309         case NLA_NUL_STRING:
4310                 return nla_put_string(skb, attrtype, (char *) &msg->value);
4311         case NLA_BINARY:
4312                 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
4313         default:
4314                 return -EINVAL;
4315         }
4316 }
4317
4318 static int
4319 devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4320                          int *start)
4321 {
4322         struct devlink_fmsg_item *item;
4323         struct nlattr *fmsg_nlattr;
4324         int i = 0;
4325         int err;
4326
4327         fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
4328         if (!fmsg_nlattr)
4329                 return -EMSGSIZE;
4330
4331         list_for_each_entry(item, &fmsg->item_list, list) {
4332                 if (i < *start) {
4333                         i++;
4334                         continue;
4335                 }
4336
4337                 switch (item->attrtype) {
4338                 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
4339                 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
4340                 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
4341                 case DEVLINK_ATTR_FMSG_NEST_END:
4342                         err = nla_put_flag(skb, item->attrtype);
4343                         break;
4344                 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
4345                         err = devlink_fmsg_item_fill_type(item, skb);
4346                         if (err)
4347                                 break;
4348                         err = devlink_fmsg_item_fill_data(item, skb);
4349                         break;
4350                 case DEVLINK_ATTR_FMSG_OBJ_NAME:
4351                         err = nla_put_string(skb, item->attrtype,
4352                                              (char *) &item->value);
4353                         break;
4354                 default:
4355                         err = -EINVAL;
4356                         break;
4357                 }
4358                 if (!err)
4359                         *start = ++i;
4360                 else
4361                         break;
4362         }
4363
4364         nla_nest_end(skb, fmsg_nlattr);
4365         return err;
4366 }
4367
4368 static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
4369                             struct genl_info *info,
4370                             enum devlink_command cmd, int flags)
4371 {
4372         struct nlmsghdr *nlh;
4373         struct sk_buff *skb;
4374         bool last = false;
4375         int index = 0;
4376         void *hdr;
4377         int err;
4378
4379         while (!last) {
4380                 int tmp_index = index;
4381
4382                 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4383                 if (!skb)
4384                         return -ENOMEM;
4385
4386                 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4387                                   &devlink_nl_family, flags | NLM_F_MULTI, cmd);
4388                 if (!hdr) {
4389                         err = -EMSGSIZE;
4390                         goto nla_put_failure;
4391                 }
4392
4393                 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4394                 if (!err)
4395                         last = true;
4396                 else if (err != -EMSGSIZE || tmp_index == index)
4397                         goto nla_put_failure;
4398
4399                 genlmsg_end(skb, hdr);
4400                 err = genlmsg_reply(skb, info);
4401                 if (err)
4402                         return err;
4403         }
4404
4405         skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4406         if (!skb)
4407                 return -ENOMEM;
4408         nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4409                         NLMSG_DONE, 0, flags | NLM_F_MULTI);
4410         if (!nlh) {
4411                 err = -EMSGSIZE;
4412                 goto nla_put_failure;
4413         }
4414
4415         return genlmsg_reply(skb, info);
4416
4417 nla_put_failure:
4418         nlmsg_free(skb);
4419         return err;
4420 }
4421
4422 struct devlink_health_reporter {
4423         struct list_head list;
4424         void *priv;
4425         const struct devlink_health_reporter_ops *ops;
4426         struct devlink *devlink;
4427         struct devlink_fmsg *dump_fmsg;
4428         struct mutex dump_lock; /* lock parallel read/write from dump buffers */
4429         u64 graceful_period;
4430         bool auto_recover;
4431         u8 health_state;
4432         u64 dump_ts;
4433         u64 error_count;
4434         u64 recovery_count;
4435         u64 last_recovery_ts;
4436         refcount_t refcount;
4437 };
4438
4439 void *
4440 devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
4441 {
4442         return reporter->priv;
4443 }
4444 EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
4445
4446 static struct devlink_health_reporter *
4447 devlink_health_reporter_find_by_name(struct devlink *devlink,
4448                                      const char *reporter_name)
4449 {
4450         struct devlink_health_reporter *reporter;
4451
4452         lockdep_assert_held(&devlink->reporters_lock);
4453         list_for_each_entry(reporter, &devlink->reporter_list, list)
4454                 if (!strcmp(reporter->ops->name, reporter_name))
4455                         return reporter;
4456         return NULL;
4457 }
4458
4459 /**
4460  *      devlink_health_reporter_create - create devlink health reporter
4461  *
4462  *      @devlink: devlink
4463  *      @ops: ops
4464  *      @graceful_period: to avoid recovery loops, in msecs
4465  *      @auto_recover: auto recover when error occurs
4466  *      @priv: priv
4467  */
4468 struct devlink_health_reporter *
4469 devlink_health_reporter_create(struct devlink *devlink,
4470                                const struct devlink_health_reporter_ops *ops,
4471                                u64 graceful_period, bool auto_recover,
4472                                void *priv)
4473 {
4474         struct devlink_health_reporter *reporter;
4475
4476         mutex_lock(&devlink->reporters_lock);
4477         if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
4478                 reporter = ERR_PTR(-EEXIST);
4479                 goto unlock;
4480         }
4481
4482         if (WARN_ON(auto_recover && !ops->recover) ||
4483             WARN_ON(graceful_period && !ops->recover)) {
4484                 reporter = ERR_PTR(-EINVAL);
4485                 goto unlock;
4486         }
4487
4488         reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
4489         if (!reporter) {
4490                 reporter = ERR_PTR(-ENOMEM);
4491                 goto unlock;
4492         }
4493
4494         reporter->priv = priv;
4495         reporter->ops = ops;
4496         reporter->devlink = devlink;
4497         reporter->graceful_period = graceful_period;
4498         reporter->auto_recover = auto_recover;
4499         mutex_init(&reporter->dump_lock);
4500         refcount_set(&reporter->refcount, 1);
4501         list_add_tail(&reporter->list, &devlink->reporter_list);
4502 unlock:
4503         mutex_unlock(&devlink->reporters_lock);
4504         return reporter;
4505 }
4506 EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
4507
4508 /**
4509  *      devlink_health_reporter_destroy - destroy devlink health reporter
4510  *
4511  *      @reporter: devlink health reporter to destroy
4512  */
4513 void
4514 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
4515 {
4516         mutex_lock(&reporter->devlink->reporters_lock);
4517         list_del(&reporter->list);
4518         mutex_unlock(&reporter->devlink->reporters_lock);
4519         while (refcount_read(&reporter->refcount) > 1)
4520                 msleep(100);
4521         mutex_destroy(&reporter->dump_lock);
4522         if (reporter->dump_fmsg)
4523                 devlink_fmsg_free(reporter->dump_fmsg);
4524         kfree(reporter);
4525 }
4526 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
4527
4528 void
4529 devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
4530                                      enum devlink_health_reporter_state state)
4531 {
4532         if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
4533                     state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
4534                 return;
4535
4536         if (reporter->health_state == state)
4537                 return;
4538
4539         reporter->health_state = state;
4540         trace_devlink_health_reporter_state_update(reporter->devlink,
4541                                                    reporter->ops->name, state);
4542 }
4543 EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
4544
4545 static int
4546 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
4547                                 void *priv_ctx)
4548 {
4549         int err;
4550
4551         if (!reporter->ops->recover)
4552                 return -EOPNOTSUPP;
4553
4554         err = reporter->ops->recover(reporter, priv_ctx);
4555         if (err)
4556                 return err;
4557
4558         reporter->recovery_count++;
4559         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
4560         reporter->last_recovery_ts = jiffies;
4561
4562         return 0;
4563 }
4564
4565 static void
4566 devlink_health_dump_clear(struct devlink_health_reporter *reporter)
4567 {
4568         if (!reporter->dump_fmsg)
4569                 return;
4570         devlink_fmsg_free(reporter->dump_fmsg);
4571         reporter->dump_fmsg = NULL;
4572 }
4573
4574 static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
4575                                   void *priv_ctx)
4576 {
4577         int err;
4578
4579         if (!reporter->ops->dump)
4580                 return 0;
4581
4582         if (reporter->dump_fmsg)
4583                 return 0;
4584
4585         reporter->dump_fmsg = devlink_fmsg_alloc();
4586         if (!reporter->dump_fmsg) {
4587                 err = -ENOMEM;
4588                 return err;
4589         }
4590
4591         err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
4592         if (err)
4593                 goto dump_err;
4594
4595         err = reporter->ops->dump(reporter, reporter->dump_fmsg,
4596                                   priv_ctx);
4597         if (err)
4598                 goto dump_err;
4599
4600         err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
4601         if (err)
4602                 goto dump_err;
4603
4604         reporter->dump_ts = jiffies;
4605
4606         return 0;
4607
4608 dump_err:
4609         devlink_health_dump_clear(reporter);
4610         return err;
4611 }
4612
4613 int devlink_health_report(struct devlink_health_reporter *reporter,
4614                           const char *msg, void *priv_ctx)
4615 {
4616         enum devlink_health_reporter_state prev_health_state;
4617         struct devlink *devlink = reporter->devlink;
4618
4619         /* write a log message of the current error */
4620         WARN_ON(!msg);
4621         trace_devlink_health_report(devlink, reporter->ops->name, msg);
4622         reporter->error_count++;
4623         prev_health_state = reporter->health_state;
4624         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4625
4626         /* abort if the previous error wasn't recovered */
4627         if (reporter->auto_recover &&
4628             (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
4629              jiffies - reporter->last_recovery_ts <
4630              msecs_to_jiffies(reporter->graceful_period))) {
4631                 trace_devlink_health_recover_aborted(devlink,
4632                                                      reporter->ops->name,
4633                                                      reporter->health_state,
4634                                                      jiffies -
4635                                                      reporter->last_recovery_ts);
4636                 return -ECANCELED;
4637         }
4638
4639         reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4640
4641         mutex_lock(&reporter->dump_lock);
4642         /* store current dump of current error, for later analysis */
4643         devlink_health_do_dump(reporter, priv_ctx);
4644         mutex_unlock(&reporter->dump_lock);
4645
4646         if (reporter->auto_recover)
4647                 return devlink_health_reporter_recover(reporter, priv_ctx);
4648
4649         return 0;
4650 }
4651 EXPORT_SYMBOL_GPL(devlink_health_report);
4652
4653 static struct devlink_health_reporter *
4654 devlink_health_reporter_get_from_info(struct devlink *devlink,
4655                                       struct genl_info *info)
4656 {
4657         struct devlink_health_reporter *reporter;
4658         char *reporter_name;
4659
4660         if (!info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
4661                 return NULL;
4662
4663         reporter_name =
4664                 nla_data(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
4665         mutex_lock(&devlink->reporters_lock);
4666         reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
4667         if (reporter)
4668                 refcount_inc(&reporter->refcount);
4669         mutex_unlock(&devlink->reporters_lock);
4670         return reporter;
4671 }
4672
4673 static void
4674 devlink_health_reporter_put(struct devlink_health_reporter *reporter)
4675 {
4676         refcount_dec(&reporter->refcount);
4677 }
4678
4679 static int
4680 devlink_nl_health_reporter_fill(struct sk_buff *msg,
4681                                 struct devlink *devlink,
4682                                 struct devlink_health_reporter *reporter,
4683                                 enum devlink_command cmd, u32 portid,
4684                                 u32 seq, int flags)
4685 {
4686         struct nlattr *reporter_attr;
4687         void *hdr;
4688
4689         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4690         if (!hdr)
4691                 return -EMSGSIZE;
4692
4693         if (devlink_nl_put_handle(msg, devlink))
4694                 goto genlmsg_cancel;
4695
4696         reporter_attr = nla_nest_start_noflag(msg,
4697                                               DEVLINK_ATTR_HEALTH_REPORTER);
4698         if (!reporter_attr)
4699                 goto genlmsg_cancel;
4700         if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
4701                            reporter->ops->name))
4702                 goto reporter_nest_cancel;
4703         if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
4704                        reporter->health_state))
4705                 goto reporter_nest_cancel;
4706         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
4707                               reporter->error_count, DEVLINK_ATTR_PAD))
4708                 goto reporter_nest_cancel;
4709         if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
4710                               reporter->recovery_count, DEVLINK_ATTR_PAD))
4711                 goto reporter_nest_cancel;
4712         if (reporter->ops->recover &&
4713             nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
4714                               reporter->graceful_period,
4715                               DEVLINK_ATTR_PAD))
4716                 goto reporter_nest_cancel;
4717         if (reporter->ops->recover &&
4718             nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
4719                        reporter->auto_recover))
4720                 goto reporter_nest_cancel;
4721         if (reporter->dump_fmsg &&
4722             nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
4723                               jiffies_to_msecs(reporter->dump_ts),
4724                               DEVLINK_ATTR_PAD))
4725                 goto reporter_nest_cancel;
4726
4727         nla_nest_end(msg, reporter_attr);
4728         genlmsg_end(msg, hdr);
4729         return 0;
4730
4731 reporter_nest_cancel:
4732         nla_nest_end(msg, reporter_attr);
4733 genlmsg_cancel:
4734         genlmsg_cancel(msg, hdr);
4735         return -EMSGSIZE;
4736 }
4737
4738 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
4739                                                    struct genl_info *info)
4740 {
4741         struct devlink *devlink = info->user_ptr[0];
4742         struct devlink_health_reporter *reporter;
4743         struct sk_buff *msg;
4744         int err;
4745
4746         reporter = devlink_health_reporter_get_from_info(devlink, info);
4747         if (!reporter)
4748                 return -EINVAL;
4749
4750         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4751         if (!msg) {
4752                 err = -ENOMEM;
4753                 goto out;
4754         }
4755
4756         err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
4757                                               DEVLINK_CMD_HEALTH_REPORTER_GET,
4758                                               info->snd_portid, info->snd_seq,
4759                                               0);
4760         if (err) {
4761                 nlmsg_free(msg);
4762                 goto out;
4763         }
4764
4765         err = genlmsg_reply(msg, info);
4766 out:
4767         devlink_health_reporter_put(reporter);
4768         return err;
4769 }
4770
4771 static int
4772 devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
4773                                           struct netlink_callback *cb)
4774 {
4775         struct devlink_health_reporter *reporter;
4776         struct devlink *devlink;
4777         int start = cb->args[0];
4778         int idx = 0;
4779         int err;
4780
4781         mutex_lock(&devlink_mutex);
4782         list_for_each_entry(devlink, &devlink_list, list) {
4783                 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4784                         continue;
4785                 mutex_lock(&devlink->reporters_lock);
4786                 list_for_each_entry(reporter, &devlink->reporter_list,
4787                                     list) {
4788                         if (idx < start) {
4789                                 idx++;
4790                                 continue;
4791                         }
4792                         err = devlink_nl_health_reporter_fill(msg, devlink,
4793                                                               reporter,
4794                                                               DEVLINK_CMD_HEALTH_REPORTER_GET,
4795                                                               NETLINK_CB(cb->skb).portid,
4796                                                               cb->nlh->nlmsg_seq,
4797                                                               NLM_F_MULTI);
4798                         if (err) {
4799                                 mutex_unlock(&devlink->reporters_lock);
4800                                 goto out;
4801                         }
4802                         idx++;
4803                 }
4804                 mutex_unlock(&devlink->reporters_lock);
4805         }
4806 out:
4807         mutex_unlock(&devlink_mutex);
4808
4809         cb->args[0] = idx;
4810         return msg->len;
4811 }
4812
4813 static int
4814 devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
4815                                         struct genl_info *info)
4816 {
4817         struct devlink *devlink = info->user_ptr[0];
4818         struct devlink_health_reporter *reporter;
4819         int err;
4820
4821         reporter = devlink_health_reporter_get_from_info(devlink, info);
4822         if (!reporter)
4823                 return -EINVAL;
4824
4825         if (!reporter->ops->recover &&
4826             (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
4827              info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
4828                 err = -EOPNOTSUPP;
4829                 goto out;
4830         }
4831
4832         if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
4833                 reporter->graceful_period =
4834                         nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
4835
4836         if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
4837                 reporter->auto_recover =
4838                         nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
4839
4840         devlink_health_reporter_put(reporter);
4841         return 0;
4842 out:
4843         devlink_health_reporter_put(reporter);
4844         return err;
4845 }
4846
4847 static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
4848                                                        struct genl_info *info)
4849 {
4850         struct devlink *devlink = info->user_ptr[0];
4851         struct devlink_health_reporter *reporter;
4852         int err;
4853
4854         reporter = devlink_health_reporter_get_from_info(devlink, info);
4855         if (!reporter)
4856                 return -EINVAL;
4857
4858         err = devlink_health_reporter_recover(reporter, NULL);
4859
4860         devlink_health_reporter_put(reporter);
4861         return err;
4862 }
4863
4864 static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
4865                                                         struct genl_info *info)
4866 {
4867         struct devlink *devlink = info->user_ptr[0];
4868         struct devlink_health_reporter *reporter;
4869         struct devlink_fmsg *fmsg;
4870         int err;
4871
4872         reporter = devlink_health_reporter_get_from_info(devlink, info);
4873         if (!reporter)
4874                 return -EINVAL;
4875
4876         if (!reporter->ops->diagnose) {
4877                 devlink_health_reporter_put(reporter);
4878                 return -EOPNOTSUPP;
4879         }
4880
4881         fmsg = devlink_fmsg_alloc();
4882         if (!fmsg) {
4883                 devlink_health_reporter_put(reporter);
4884                 return -ENOMEM;
4885         }
4886
4887         err = devlink_fmsg_obj_nest_start(fmsg);
4888         if (err)
4889                 goto out;
4890
4891         err = reporter->ops->diagnose(reporter, fmsg);
4892         if (err)
4893                 goto out;
4894
4895         err = devlink_fmsg_obj_nest_end(fmsg);
4896         if (err)
4897                 goto out;
4898
4899         err = devlink_fmsg_snd(fmsg, info,
4900                                DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
4901
4902 out:
4903         devlink_fmsg_free(fmsg);
4904         devlink_health_reporter_put(reporter);
4905         return err;
4906 }
4907
4908 static int devlink_nl_cmd_health_reporter_dump_get_doit(struct sk_buff *skb,
4909                                                         struct genl_info *info)
4910 {
4911         struct devlink *devlink = info->user_ptr[0];
4912         struct devlink_health_reporter *reporter;
4913         int err;
4914
4915         reporter = devlink_health_reporter_get_from_info(devlink, info);
4916         if (!reporter)
4917                 return -EINVAL;
4918
4919         if (!reporter->ops->dump) {
4920                 devlink_health_reporter_put(reporter);
4921                 return -EOPNOTSUPP;
4922         }
4923
4924         mutex_lock(&reporter->dump_lock);
4925         err = devlink_health_do_dump(reporter, NULL);
4926         if (err)
4927                 goto out;
4928
4929         err = devlink_fmsg_snd(reporter->dump_fmsg, info,
4930                                DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 0);
4931
4932 out:
4933         mutex_unlock(&reporter->dump_lock);
4934         devlink_health_reporter_put(reporter);
4935         return err;
4936 }
4937
4938 static int
4939 devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
4940                                                struct genl_info *info)
4941 {
4942         struct devlink *devlink = info->user_ptr[0];
4943         struct devlink_health_reporter *reporter;
4944
4945         reporter = devlink_health_reporter_get_from_info(devlink, info);
4946         if (!reporter)
4947                 return -EINVAL;
4948
4949         if (!reporter->ops->dump) {
4950                 devlink_health_reporter_put(reporter);
4951                 return -EOPNOTSUPP;
4952         }
4953
4954         mutex_lock(&reporter->dump_lock);
4955         devlink_health_dump_clear(reporter);
4956         mutex_unlock(&reporter->dump_lock);
4957         devlink_health_reporter_put(reporter);
4958         return 0;
4959 }
4960
4961 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
4962         [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
4963         [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
4964         [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
4965         [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
4966         [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
4967         [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
4968         [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
4969         [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
4970         [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
4971         [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
4972         [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
4973         [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
4974         [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
4975         [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
4976         [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
4977         [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
4978         [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
4979         [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
4980         [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
4981         [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
4982         [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
4983         [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
4984         [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
4985         [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
4986         [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
4987         [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
4988         [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
4989         [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
4990         [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
4991 };
4992
4993 static const struct genl_ops devlink_nl_ops[] = {
4994         {
4995                 .cmd = DEVLINK_CMD_GET,
4996                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
4997                 .doit = devlink_nl_cmd_get_doit,
4998                 .dumpit = devlink_nl_cmd_get_dumpit,
4999                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5000                 /* can be retrieved by unprivileged users */
5001         },
5002         {
5003                 .cmd = DEVLINK_CMD_PORT_GET,
5004                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5005                 .doit = devlink_nl_cmd_port_get_doit,
5006                 .dumpit = devlink_nl_cmd_port_get_dumpit,
5007                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5008                 /* can be retrieved by unprivileged users */
5009         },
5010         {
5011                 .cmd = DEVLINK_CMD_PORT_SET,
5012                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5013                 .doit = devlink_nl_cmd_port_set_doit,
5014                 .flags = GENL_ADMIN_PERM,
5015                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5016         },
5017         {
5018                 .cmd = DEVLINK_CMD_PORT_SPLIT,
5019                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5020                 .doit = devlink_nl_cmd_port_split_doit,
5021                 .flags = GENL_ADMIN_PERM,
5022                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5023                                   DEVLINK_NL_FLAG_NO_LOCK,
5024         },
5025         {
5026                 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
5027                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5028                 .doit = devlink_nl_cmd_port_unsplit_doit,
5029                 .flags = GENL_ADMIN_PERM,
5030                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5031                                   DEVLINK_NL_FLAG_NO_LOCK,
5032         },
5033         {
5034                 .cmd = DEVLINK_CMD_SB_GET,
5035                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5036                 .doit = devlink_nl_cmd_sb_get_doit,
5037                 .dumpit = devlink_nl_cmd_sb_get_dumpit,
5038                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5039                                   DEVLINK_NL_FLAG_NEED_SB,
5040                 /* can be retrieved by unprivileged users */
5041         },
5042         {
5043                 .cmd = DEVLINK_CMD_SB_POOL_GET,
5044                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5045                 .doit = devlink_nl_cmd_sb_pool_get_doit,
5046                 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
5047                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5048                                   DEVLINK_NL_FLAG_NEED_SB,
5049                 /* can be retrieved by unprivileged users */
5050         },
5051         {
5052                 .cmd = DEVLINK_CMD_SB_POOL_SET,
5053                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5054                 .doit = devlink_nl_cmd_sb_pool_set_doit,
5055                 .flags = GENL_ADMIN_PERM,
5056                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5057                                   DEVLINK_NL_FLAG_NEED_SB,
5058         },
5059         {
5060                 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
5061                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5062                 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
5063                 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
5064                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5065                                   DEVLINK_NL_FLAG_NEED_SB,
5066                 /* can be retrieved by unprivileged users */
5067         },
5068         {
5069                 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
5070                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5071                 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
5072                 .flags = GENL_ADMIN_PERM,
5073                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5074                                   DEVLINK_NL_FLAG_NEED_SB,
5075         },
5076         {
5077                 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
5078                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5079                 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5080                 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
5081                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5082                                   DEVLINK_NL_FLAG_NEED_SB,
5083                 /* can be retrieved by unprivileged users */
5084         },
5085         {
5086                 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
5087                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5088                 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
5089                 .flags = GENL_ADMIN_PERM,
5090                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5091                                   DEVLINK_NL_FLAG_NEED_SB,
5092         },
5093         {
5094                 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
5095                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5096                 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
5097                 .flags = GENL_ADMIN_PERM,
5098                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5099                                   DEVLINK_NL_FLAG_NEED_SB,
5100         },
5101         {
5102                 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
5103                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5104                 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
5105                 .flags = GENL_ADMIN_PERM,
5106                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5107                                   DEVLINK_NL_FLAG_NEED_SB,
5108         },
5109         {
5110                 .cmd = DEVLINK_CMD_ESWITCH_GET,
5111                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5112                 .doit = devlink_nl_cmd_eswitch_get_doit,
5113                 .flags = GENL_ADMIN_PERM,
5114                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5115         },
5116         {
5117                 .cmd = DEVLINK_CMD_ESWITCH_SET,
5118                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5119                 .doit = devlink_nl_cmd_eswitch_set_doit,
5120                 .flags = GENL_ADMIN_PERM,
5121                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5122                                   DEVLINK_NL_FLAG_NO_LOCK,
5123         },
5124         {
5125                 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
5126                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5127                 .doit = devlink_nl_cmd_dpipe_table_get,
5128                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5129                 /* can be retrieved by unprivileged users */
5130         },
5131         {
5132                 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
5133                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5134                 .doit = devlink_nl_cmd_dpipe_entries_get,
5135                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5136                 /* can be retrieved by unprivileged users */
5137         },
5138         {
5139                 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
5140                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5141                 .doit = devlink_nl_cmd_dpipe_headers_get,
5142                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5143                 /* can be retrieved by unprivileged users */
5144         },
5145         {
5146                 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
5147                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5148                 .doit = devlink_nl_cmd_dpipe_table_counters_set,
5149                 .flags = GENL_ADMIN_PERM,
5150                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5151         },
5152         {
5153                 .cmd = DEVLINK_CMD_RESOURCE_SET,
5154                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5155                 .doit = devlink_nl_cmd_resource_set,
5156                 .flags = GENL_ADMIN_PERM,
5157                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5158         },
5159         {
5160                 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
5161                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5162                 .doit = devlink_nl_cmd_resource_dump,
5163                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5164                 /* can be retrieved by unprivileged users */
5165         },
5166         {
5167                 .cmd = DEVLINK_CMD_RELOAD,
5168                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5169                 .doit = devlink_nl_cmd_reload,
5170                 .flags = GENL_ADMIN_PERM,
5171                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5172                                   DEVLINK_NL_FLAG_NO_LOCK,
5173         },
5174         {
5175                 .cmd = DEVLINK_CMD_PARAM_GET,
5176                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5177                 .doit = devlink_nl_cmd_param_get_doit,
5178                 .dumpit = devlink_nl_cmd_param_get_dumpit,
5179                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5180                 /* can be retrieved by unprivileged users */
5181         },
5182         {
5183                 .cmd = DEVLINK_CMD_PARAM_SET,
5184                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5185                 .doit = devlink_nl_cmd_param_set_doit,
5186                 .flags = GENL_ADMIN_PERM,
5187                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5188         },
5189         {
5190                 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
5191                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5192                 .doit = devlink_nl_cmd_port_param_get_doit,
5193                 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
5194                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5195                 /* can be retrieved by unprivileged users */
5196         },
5197         {
5198                 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
5199                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5200                 .doit = devlink_nl_cmd_port_param_set_doit,
5201                 .flags = GENL_ADMIN_PERM,
5202                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5203         },
5204         {
5205                 .cmd = DEVLINK_CMD_REGION_GET,
5206                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5207                 .doit = devlink_nl_cmd_region_get_doit,
5208                 .dumpit = devlink_nl_cmd_region_get_dumpit,
5209                 .flags = GENL_ADMIN_PERM,
5210                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5211         },
5212         {
5213                 .cmd = DEVLINK_CMD_REGION_DEL,
5214                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5215                 .doit = devlink_nl_cmd_region_del,
5216                 .flags = GENL_ADMIN_PERM,
5217                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5218         },
5219         {
5220                 .cmd = DEVLINK_CMD_REGION_READ,
5221                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5222                 .dumpit = devlink_nl_cmd_region_read_dumpit,
5223                 .flags = GENL_ADMIN_PERM,
5224                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5225         },
5226         {
5227                 .cmd = DEVLINK_CMD_INFO_GET,
5228                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5229                 .doit = devlink_nl_cmd_info_get_doit,
5230                 .dumpit = devlink_nl_cmd_info_get_dumpit,
5231                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5232                 /* can be retrieved by unprivileged users */
5233         },
5234         {
5235                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
5236                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5237                 .doit = devlink_nl_cmd_health_reporter_get_doit,
5238                 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
5239                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5240                                   DEVLINK_NL_FLAG_NO_LOCK,
5241                 /* can be retrieved by unprivileged users */
5242         },
5243         {
5244                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
5245                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5246                 .doit = devlink_nl_cmd_health_reporter_set_doit,
5247                 .flags = GENL_ADMIN_PERM,
5248                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5249                                   DEVLINK_NL_FLAG_NO_LOCK,
5250         },
5251         {
5252                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
5253                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5254                 .doit = devlink_nl_cmd_health_reporter_recover_doit,
5255                 .flags = GENL_ADMIN_PERM,
5256                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5257                                   DEVLINK_NL_FLAG_NO_LOCK,
5258         },
5259         {
5260                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
5261                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5262                 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
5263                 .flags = GENL_ADMIN_PERM,
5264                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5265                                   DEVLINK_NL_FLAG_NO_LOCK,
5266         },
5267         {
5268                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
5269                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5270                 .doit = devlink_nl_cmd_health_reporter_dump_get_doit,
5271                 .flags = GENL_ADMIN_PERM,
5272                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5273                                   DEVLINK_NL_FLAG_NO_LOCK,
5274         },
5275         {
5276                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
5277                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5278                 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
5279                 .flags = GENL_ADMIN_PERM,
5280                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5281                                   DEVLINK_NL_FLAG_NO_LOCK,
5282         },
5283         {
5284                 .cmd = DEVLINK_CMD_FLASH_UPDATE,
5285                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5286                 .doit = devlink_nl_cmd_flash_update,
5287                 .flags = GENL_ADMIN_PERM,
5288                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5289         },
5290 };
5291
5292 static struct genl_family devlink_nl_family __ro_after_init = {
5293         .name           = DEVLINK_GENL_NAME,
5294         .version        = DEVLINK_GENL_VERSION,
5295         .maxattr        = DEVLINK_ATTR_MAX,
5296         .policy = devlink_nl_policy,
5297         .netnsok        = true,
5298         .pre_doit       = devlink_nl_pre_doit,
5299         .post_doit      = devlink_nl_post_doit,
5300         .module         = THIS_MODULE,
5301         .ops            = devlink_nl_ops,
5302         .n_ops          = ARRAY_SIZE(devlink_nl_ops),
5303         .mcgrps         = devlink_nl_mcgrps,
5304         .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
5305 };
5306
5307 /**
5308  *      devlink_alloc - Allocate new devlink instance resources
5309  *
5310  *      @ops: ops
5311  *      @priv_size: size of user private data
5312  *
5313  *      Allocate new devlink instance resources, including devlink index
5314  *      and name.
5315  */
5316 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
5317 {
5318         struct devlink *devlink;
5319
5320         if (WARN_ON(!ops))
5321                 return NULL;
5322
5323         devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
5324         if (!devlink)
5325                 return NULL;
5326         devlink->ops = ops;
5327         devlink_net_set(devlink, &init_net);
5328         INIT_LIST_HEAD(&devlink->port_list);
5329         INIT_LIST_HEAD(&devlink->sb_list);
5330         INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
5331         INIT_LIST_HEAD(&devlink->resource_list);
5332         INIT_LIST_HEAD(&devlink->param_list);
5333         INIT_LIST_HEAD(&devlink->region_list);
5334         INIT_LIST_HEAD(&devlink->reporter_list);
5335         mutex_init(&devlink->lock);
5336         mutex_init(&devlink->reporters_lock);
5337         return devlink;
5338 }
5339 EXPORT_SYMBOL_GPL(devlink_alloc);
5340
5341 /**
5342  *      devlink_register - Register devlink instance
5343  *
5344  *      @devlink: devlink
5345  *      @dev: parent device
5346  */
5347 int devlink_register(struct devlink *devlink, struct device *dev)
5348 {
5349         mutex_lock(&devlink_mutex);
5350         devlink->dev = dev;
5351         list_add_tail(&devlink->list, &devlink_list);
5352         devlink_notify(devlink, DEVLINK_CMD_NEW);
5353         mutex_unlock(&devlink_mutex);
5354         return 0;
5355 }
5356 EXPORT_SYMBOL_GPL(devlink_register);
5357
5358 /**
5359  *      devlink_unregister - Unregister devlink instance
5360  *
5361  *      @devlink: devlink
5362  */
5363 void devlink_unregister(struct devlink *devlink)
5364 {
5365         mutex_lock(&devlink_mutex);
5366         devlink_notify(devlink, DEVLINK_CMD_DEL);
5367         list_del(&devlink->list);
5368         mutex_unlock(&devlink_mutex);
5369 }
5370 EXPORT_SYMBOL_GPL(devlink_unregister);
5371
5372 /**
5373  *      devlink_free - Free devlink instance resources
5374  *
5375  *      @devlink: devlink
5376  */
5377 void devlink_free(struct devlink *devlink)
5378 {
5379         mutex_destroy(&devlink->reporters_lock);
5380         mutex_destroy(&devlink->lock);
5381         WARN_ON(!list_empty(&devlink->reporter_list));
5382         WARN_ON(!list_empty(&devlink->region_list));
5383         WARN_ON(!list_empty(&devlink->param_list));
5384         WARN_ON(!list_empty(&devlink->resource_list));
5385         WARN_ON(!list_empty(&devlink->dpipe_table_list));
5386         WARN_ON(!list_empty(&devlink->sb_list));
5387         WARN_ON(!list_empty(&devlink->port_list));
5388
5389         kfree(devlink);
5390 }
5391 EXPORT_SYMBOL_GPL(devlink_free);
5392
5393 /**
5394  *      devlink_port_register - Register devlink port
5395  *
5396  *      @devlink: devlink
5397  *      @devlink_port: devlink port
5398  *      @port_index: driver-specific numerical identifier of the port
5399  *
5400  *      Register devlink port with provided port index. User can use
5401  *      any indexing, even hw-related one. devlink_port structure
5402  *      is convenient to be embedded inside user driver private structure.
5403  *      Note that the caller should take care of zeroing the devlink_port
5404  *      structure.
5405  */
5406 int devlink_port_register(struct devlink *devlink,
5407                           struct devlink_port *devlink_port,
5408                           unsigned int port_index)
5409 {
5410         mutex_lock(&devlink->lock);
5411         if (devlink_port_index_exists(devlink, port_index)) {
5412                 mutex_unlock(&devlink->lock);
5413                 return -EEXIST;
5414         }
5415         devlink_port->devlink = devlink;
5416         devlink_port->index = port_index;
5417         devlink_port->registered = true;
5418         spin_lock_init(&devlink_port->type_lock);
5419         list_add_tail(&devlink_port->list, &devlink->port_list);
5420         INIT_LIST_HEAD(&devlink_port->param_list);
5421         mutex_unlock(&devlink->lock);
5422         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
5423         return 0;
5424 }
5425 EXPORT_SYMBOL_GPL(devlink_port_register);
5426
5427 /**
5428  *      devlink_port_unregister - Unregister devlink port
5429  *
5430  *      @devlink_port: devlink port
5431  */
5432 void devlink_port_unregister(struct devlink_port *devlink_port)
5433 {
5434         struct devlink *devlink = devlink_port->devlink;
5435
5436         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
5437         mutex_lock(&devlink->lock);
5438         list_del(&devlink_port->list);
5439         mutex_unlock(&devlink->lock);
5440 }
5441 EXPORT_SYMBOL_GPL(devlink_port_unregister);
5442
5443 static void __devlink_port_type_set(struct devlink_port *devlink_port,
5444                                     enum devlink_port_type type,
5445                                     void *type_dev)
5446 {
5447         if (WARN_ON(!devlink_port->registered))
5448                 return;
5449         spin_lock(&devlink_port->type_lock);
5450         devlink_port->type = type;
5451         devlink_port->type_dev = type_dev;
5452         spin_unlock(&devlink_port->type_lock);
5453         devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
5454 }
5455
5456 /**
5457  *      devlink_port_type_eth_set - Set port type to Ethernet
5458  *
5459  *      @devlink_port: devlink port
5460  *      @netdev: related netdevice
5461  */
5462 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
5463                                struct net_device *netdev)
5464 {
5465         const struct net_device_ops *ops = netdev->netdev_ops;
5466
5467         /* If driver registers devlink port, it should set devlink port
5468          * attributes accordingly so the compat functions are called
5469          * and the original ops are not used.
5470          */
5471         if (ops->ndo_get_phys_port_name) {
5472                 /* Some drivers use the same set of ndos for netdevs
5473                  * that have devlink_port registered and also for
5474                  * those who don't. Make sure that ndo_get_phys_port_name
5475                  * returns -EOPNOTSUPP here in case it is defined.
5476                  * Warn if not.
5477                  */
5478                 char name[IFNAMSIZ];
5479                 int err;
5480
5481                 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
5482                 WARN_ON(err != -EOPNOTSUPP);
5483         }
5484         if (ops->ndo_get_port_parent_id) {
5485                 /* Some drivers use the same set of ndos for netdevs
5486                  * that have devlink_port registered and also for
5487                  * those who don't. Make sure that ndo_get_port_parent_id
5488                  * returns -EOPNOTSUPP here in case it is defined.
5489                  * Warn if not.
5490                  */
5491                 struct netdev_phys_item_id ppid;
5492                 int err;
5493
5494                 err = ops->ndo_get_port_parent_id(netdev, &ppid);
5495                 WARN_ON(err != -EOPNOTSUPP);
5496         }
5497         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
5498 }
5499 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
5500
5501 /**
5502  *      devlink_port_type_ib_set - Set port type to InfiniBand
5503  *
5504  *      @devlink_port: devlink port
5505  *      @ibdev: related IB device
5506  */
5507 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
5508                               struct ib_device *ibdev)
5509 {
5510         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
5511 }
5512 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
5513
5514 /**
5515  *      devlink_port_type_clear - Clear port type
5516  *
5517  *      @devlink_port: devlink port
5518  */
5519 void devlink_port_type_clear(struct devlink_port *devlink_port)
5520 {
5521         __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
5522 }
5523 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
5524
5525 /**
5526  *      devlink_port_attrs_set - Set port attributes
5527  *
5528  *      @devlink_port: devlink port
5529  *      @flavour: flavour of the port
5530  *      @port_number: number of the port that is facing user, for example
5531  *                    the front panel port number
5532  *      @split: indicates if this is split port
5533  *      @split_subport_number: if the port is split, this is the number
5534  *                             of subport.
5535  *      @switch_id: if the port is part of switch, this is buffer with ID,
5536  *                  otwerwise this is NULL
5537  *      @switch_id_len: length of the switch_id buffer
5538  */
5539 void devlink_port_attrs_set(struct devlink_port *devlink_port,
5540                             enum devlink_port_flavour flavour,
5541                             u32 port_number, bool split,
5542                             u32 split_subport_number,
5543                             const unsigned char *switch_id,
5544                             unsigned char switch_id_len)
5545 {
5546         struct devlink_port_attrs *attrs = &devlink_port->attrs;
5547
5548         if (WARN_ON(devlink_port->registered))
5549                 return;
5550         attrs->set = true;
5551         attrs->flavour = flavour;
5552         attrs->port_number = port_number;
5553         attrs->split = split;
5554         attrs->split_subport_number = split_subport_number;
5555         if (switch_id) {
5556                 attrs->switch_port = true;
5557                 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
5558                         switch_id_len = MAX_PHYS_ITEM_ID_LEN;
5559                 memcpy(attrs->switch_id.id, switch_id, switch_id_len);
5560                 attrs->switch_id.id_len = switch_id_len;
5561         } else {
5562                 attrs->switch_port = false;
5563         }
5564 }
5565 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
5566
5567 static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
5568                                              char *name, size_t len)
5569 {
5570         struct devlink_port_attrs *attrs = &devlink_port->attrs;
5571         int n = 0;
5572
5573         if (!attrs->set)
5574                 return -EOPNOTSUPP;
5575
5576         switch (attrs->flavour) {
5577         case DEVLINK_PORT_FLAVOUR_PHYSICAL:
5578                 if (!attrs->split)
5579                         n = snprintf(name, len, "p%u", attrs->port_number);
5580                 else
5581                         n = snprintf(name, len, "p%us%u", attrs->port_number,
5582                                      attrs->split_subport_number);
5583                 break;
5584         case DEVLINK_PORT_FLAVOUR_CPU:
5585         case DEVLINK_PORT_FLAVOUR_DSA:
5586                 /* As CPU and DSA ports do not have a netdevice associated
5587                  * case should not ever happen.
5588                  */
5589                 WARN_ON(1);
5590                 return -EINVAL;
5591         }
5592
5593         if (n >= len)
5594                 return -EINVAL;
5595
5596         return 0;
5597 }
5598
5599 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
5600                         u32 size, u16 ingress_pools_count,
5601                         u16 egress_pools_count, u16 ingress_tc_count,
5602                         u16 egress_tc_count)
5603 {
5604         struct devlink_sb *devlink_sb;
5605         int err = 0;
5606
5607         mutex_lock(&devlink->lock);
5608         if (devlink_sb_index_exists(devlink, sb_index)) {
5609                 err = -EEXIST;
5610                 goto unlock;
5611         }
5612
5613         devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
5614         if (!devlink_sb) {
5615                 err = -ENOMEM;
5616                 goto unlock;
5617         }
5618         devlink_sb->index = sb_index;
5619         devlink_sb->size = size;
5620         devlink_sb->ingress_pools_count = ingress_pools_count;
5621         devlink_sb->egress_pools_count = egress_pools_count;
5622         devlink_sb->ingress_tc_count = ingress_tc_count;
5623         devlink_sb->egress_tc_count = egress_tc_count;
5624         list_add_tail(&devlink_sb->list, &devlink->sb_list);
5625 unlock:
5626         mutex_unlock(&devlink->lock);
5627         return err;
5628 }
5629 EXPORT_SYMBOL_GPL(devlink_sb_register);
5630
5631 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
5632 {
5633         struct devlink_sb *devlink_sb;
5634
5635         mutex_lock(&devlink->lock);
5636         devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
5637         WARN_ON(!devlink_sb);
5638         list_del(&devlink_sb->list);
5639         mutex_unlock(&devlink->lock);
5640         kfree(devlink_sb);
5641 }
5642 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
5643
5644 /**
5645  *      devlink_dpipe_headers_register - register dpipe headers
5646  *
5647  *      @devlink: devlink
5648  *      @dpipe_headers: dpipe header array
5649  *
5650  *      Register the headers supported by hardware.
5651  */
5652 int devlink_dpipe_headers_register(struct devlink *devlink,
5653                                    struct devlink_dpipe_headers *dpipe_headers)
5654 {
5655         mutex_lock(&devlink->lock);
5656         devlink->dpipe_headers = dpipe_headers;
5657         mutex_unlock(&devlink->lock);
5658         return 0;
5659 }
5660 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
5661
5662 /**
5663  *      devlink_dpipe_headers_unregister - unregister dpipe headers
5664  *
5665  *      @devlink: devlink
5666  *
5667  *      Unregister the headers supported by hardware.
5668  */
5669 void devlink_dpipe_headers_unregister(struct devlink *devlink)
5670 {
5671         mutex_lock(&devlink->lock);
5672         devlink->dpipe_headers = NULL;
5673         mutex_unlock(&devlink->lock);
5674 }
5675 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
5676
5677 /**
5678  *      devlink_dpipe_table_counter_enabled - check if counter allocation
5679  *                                            required
5680  *      @devlink: devlink
5681  *      @table_name: tables name
5682  *
5683  *      Used by driver to check if counter allocation is required.
5684  *      After counter allocation is turned on the table entries
5685  *      are updated to include counter statistics.
5686  *
5687  *      After that point on the driver must respect the counter
5688  *      state so that each entry added to the table is added
5689  *      with a counter.
5690  */
5691 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
5692                                          const char *table_name)
5693 {
5694         struct devlink_dpipe_table *table;
5695         bool enabled;
5696
5697         rcu_read_lock();
5698         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
5699                                          table_name);
5700         enabled = false;
5701         if (table)
5702                 enabled = table->counters_enabled;
5703         rcu_read_unlock();
5704         return enabled;
5705 }
5706 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
5707
5708 /**
5709  *      devlink_dpipe_table_register - register dpipe table
5710  *
5711  *      @devlink: devlink
5712  *      @table_name: table name
5713  *      @table_ops: table ops
5714  *      @priv: priv
5715  *      @counter_control_extern: external control for counters
5716  */
5717 int devlink_dpipe_table_register(struct devlink *devlink,
5718                                  const char *table_name,
5719                                  struct devlink_dpipe_table_ops *table_ops,
5720                                  void *priv, bool counter_control_extern)
5721 {
5722         struct devlink_dpipe_table *table;
5723
5724         if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
5725                 return -EEXIST;
5726
5727         if (WARN_ON(!table_ops->size_get))
5728                 return -EINVAL;
5729
5730         table = kzalloc(sizeof(*table), GFP_KERNEL);
5731         if (!table)
5732                 return -ENOMEM;
5733
5734         table->name = table_name;
5735         table->table_ops = table_ops;
5736         table->priv = priv;
5737         table->counter_control_extern = counter_control_extern;
5738
5739         mutex_lock(&devlink->lock);
5740         list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
5741         mutex_unlock(&devlink->lock);
5742         return 0;
5743 }
5744 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
5745
5746 /**
5747  *      devlink_dpipe_table_unregister - unregister dpipe table
5748  *
5749  *      @devlink: devlink
5750  *      @table_name: table name
5751  */
5752 void devlink_dpipe_table_unregister(struct devlink *devlink,
5753                                     const char *table_name)
5754 {
5755         struct devlink_dpipe_table *table;
5756
5757         mutex_lock(&devlink->lock);
5758         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
5759                                          table_name);
5760         if (!table)
5761                 goto unlock;
5762         list_del_rcu(&table->list);
5763         mutex_unlock(&devlink->lock);
5764         kfree_rcu(table, rcu);
5765         return;
5766 unlock:
5767         mutex_unlock(&devlink->lock);
5768 }
5769 EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
5770
5771 /**
5772  *      devlink_resource_register - devlink resource register
5773  *
5774  *      @devlink: devlink
5775  *      @resource_name: resource's name
5776  *      @resource_size: resource's size
5777  *      @resource_id: resource's id
5778  *      @parent_resource_id: resource's parent id
5779  *      @size_params: size parameters
5780  */
5781 int devlink_resource_register(struct devlink *devlink,
5782                               const char *resource_name,
5783                               u64 resource_size,
5784                               u64 resource_id,
5785                               u64 parent_resource_id,
5786                               const struct devlink_resource_size_params *size_params)
5787 {
5788         struct devlink_resource *resource;
5789         struct list_head *resource_list;
5790         bool top_hierarchy;
5791         int err = 0;
5792
5793         top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
5794
5795         mutex_lock(&devlink->lock);
5796         resource = devlink_resource_find(devlink, NULL, resource_id);
5797         if (resource) {
5798                 err = -EINVAL;
5799                 goto out;
5800         }
5801
5802         resource = kzalloc(sizeof(*resource), GFP_KERNEL);
5803         if (!resource) {
5804                 err = -ENOMEM;
5805                 goto out;
5806         }
5807
5808         if (top_hierarchy) {
5809                 resource_list = &devlink->resource_list;
5810         } else {
5811                 struct devlink_resource *parent_resource;
5812
5813                 parent_resource = devlink_resource_find(devlink, NULL,
5814                                                         parent_resource_id);
5815                 if (parent_resource) {
5816                         resource_list = &parent_resource->resource_list;
5817                         resource->parent = parent_resource;
5818                 } else {
5819                         kfree(resource);
5820                         err = -EINVAL;
5821                         goto out;
5822                 }
5823         }
5824
5825         resource->name = resource_name;
5826         resource->size = resource_size;
5827         resource->size_new = resource_size;
5828         resource->id = resource_id;
5829         resource->size_valid = true;
5830         memcpy(&resource->size_params, size_params,
5831                sizeof(resource->size_params));
5832         INIT_LIST_HEAD(&resource->resource_list);
5833         list_add_tail(&resource->list, resource_list);
5834 out:
5835         mutex_unlock(&devlink->lock);
5836         return err;
5837 }
5838 EXPORT_SYMBOL_GPL(devlink_resource_register);
5839
5840 /**
5841  *      devlink_resources_unregister - free all resources
5842  *
5843  *      @devlink: devlink
5844  *      @resource: resource
5845  */
5846 void devlink_resources_unregister(struct devlink *devlink,
5847                                   struct devlink_resource *resource)
5848 {
5849         struct devlink_resource *tmp, *child_resource;
5850         struct list_head *resource_list;
5851
5852         if (resource)
5853                 resource_list = &resource->resource_list;
5854         else
5855                 resource_list = &devlink->resource_list;
5856
5857         if (!resource)
5858                 mutex_lock(&devlink->lock);
5859
5860         list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
5861                 devlink_resources_unregister(devlink, child_resource);
5862                 list_del(&child_resource->list);
5863                 kfree(child_resource);
5864         }
5865
5866         if (!resource)
5867                 mutex_unlock(&devlink->lock);
5868 }
5869 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
5870
5871 /**
5872  *      devlink_resource_size_get - get and update size
5873  *
5874  *      @devlink: devlink
5875  *      @resource_id: the requested resource id
5876  *      @p_resource_size: ptr to update
5877  */
5878 int devlink_resource_size_get(struct devlink *devlink,
5879                               u64 resource_id,
5880                               u64 *p_resource_size)
5881 {
5882         struct devlink_resource *resource;
5883         int err = 0;
5884
5885         mutex_lock(&devlink->lock);
5886         resource = devlink_resource_find(devlink, NULL, resource_id);
5887         if (!resource) {
5888                 err = -EINVAL;
5889                 goto out;
5890         }
5891         *p_resource_size = resource->size_new;
5892         resource->size = resource->size_new;
5893 out:
5894         mutex_unlock(&devlink->lock);
5895         return err;
5896 }
5897 EXPORT_SYMBOL_GPL(devlink_resource_size_get);
5898
5899 /**
5900  *      devlink_dpipe_table_resource_set - set the resource id
5901  *
5902  *      @devlink: devlink
5903  *      @table_name: table name
5904  *      @resource_id: resource id
5905  *      @resource_units: number of resource's units consumed per table's entry
5906  */
5907 int devlink_dpipe_table_resource_set(struct devlink *devlink,
5908                                      const char *table_name, u64 resource_id,
5909                                      u64 resource_units)
5910 {
5911         struct devlink_dpipe_table *table;
5912         int err = 0;
5913
5914         mutex_lock(&devlink->lock);
5915         table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
5916                                          table_name);
5917         if (!table) {
5918                 err = -EINVAL;
5919                 goto out;
5920         }
5921         table->resource_id = resource_id;
5922         table->resource_units = resource_units;
5923         table->resource_valid = true;
5924 out:
5925         mutex_unlock(&devlink->lock);
5926         return err;
5927 }
5928 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
5929
5930 /**
5931  *      devlink_resource_occ_get_register - register occupancy getter
5932  *
5933  *      @devlink: devlink
5934  *      @resource_id: resource id
5935  *      @occ_get: occupancy getter callback
5936  *      @occ_get_priv: occupancy getter callback priv
5937  */
5938 void devlink_resource_occ_get_register(struct devlink *devlink,
5939                                        u64 resource_id,
5940                                        devlink_resource_occ_get_t *occ_get,
5941                                        void *occ_get_priv)
5942 {
5943         struct devlink_resource *resource;
5944
5945         mutex_lock(&devlink->lock);
5946         resource = devlink_resource_find(devlink, NULL, resource_id);
5947         if (WARN_ON(!resource))
5948                 goto out;
5949         WARN_ON(resource->occ_get);
5950
5951         resource->occ_get = occ_get;
5952         resource->occ_get_priv = occ_get_priv;
5953 out:
5954         mutex_unlock(&devlink->lock);
5955 }
5956 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
5957
5958 /**
5959  *      devlink_resource_occ_get_unregister - unregister occupancy getter
5960  *
5961  *      @devlink: devlink
5962  *      @resource_id: resource id
5963  */
5964 void devlink_resource_occ_get_unregister(struct devlink *devlink,
5965                                          u64 resource_id)
5966 {
5967         struct devlink_resource *resource;
5968
5969         mutex_lock(&devlink->lock);
5970         resource = devlink_resource_find(devlink, NULL, resource_id);
5971         if (WARN_ON(!resource))
5972                 goto out;
5973         WARN_ON(!resource->occ_get);
5974
5975         resource->occ_get = NULL;
5976         resource->occ_get_priv = NULL;
5977 out:
5978         mutex_unlock(&devlink->lock);
5979 }
5980 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
5981
5982 static int devlink_param_verify(const struct devlink_param *param)
5983 {
5984         if (!param || !param->name || !param->supported_cmodes)
5985                 return -EINVAL;
5986         if (param->generic)
5987                 return devlink_param_generic_verify(param);
5988         else
5989                 return devlink_param_driver_verify(param);
5990 }
5991
5992 static int __devlink_params_register(struct devlink *devlink,
5993                                      unsigned int port_index,
5994                                      struct list_head *param_list,
5995                                      const struct devlink_param *params,
5996                                      size_t params_count,
5997                                      enum devlink_command reg_cmd,
5998                                      enum devlink_command unreg_cmd)
5999 {
6000         const struct devlink_param *param = params;
6001         int i;
6002         int err;
6003
6004         mutex_lock(&devlink->lock);
6005         for (i = 0; i < params_count; i++, param++) {
6006                 err = devlink_param_verify(param);
6007                 if (err)
6008                         goto rollback;
6009
6010                 err = devlink_param_register_one(devlink, port_index,
6011                                                  param_list, param, reg_cmd);
6012                 if (err)
6013                         goto rollback;
6014         }
6015
6016         mutex_unlock(&devlink->lock);
6017         return 0;
6018
6019 rollback:
6020         if (!i)
6021                 goto unlock;
6022         for (param--; i > 0; i--, param--)
6023                 devlink_param_unregister_one(devlink, port_index, param_list,
6024                                              param, unreg_cmd);
6025 unlock:
6026         mutex_unlock(&devlink->lock);
6027         return err;
6028 }
6029
6030 static void __devlink_params_unregister(struct devlink *devlink,
6031                                         unsigned int port_index,
6032                                         struct list_head *param_list,
6033                                         const struct devlink_param *params,
6034                                         size_t params_count,
6035                                         enum devlink_command cmd)
6036 {
6037         const struct devlink_param *param = params;
6038         int i;
6039
6040         mutex_lock(&devlink->lock);
6041         for (i = 0; i < params_count; i++, param++)
6042                 devlink_param_unregister_one(devlink, 0, param_list, param,
6043                                              cmd);
6044         mutex_unlock(&devlink->lock);
6045 }
6046
6047 /**
6048  *      devlink_params_register - register configuration parameters
6049  *
6050  *      @devlink: devlink
6051  *      @params: configuration parameters array
6052  *      @params_count: number of parameters provided
6053  *
6054  *      Register the configuration parameters supported by the driver.
6055  */
6056 int devlink_params_register(struct devlink *devlink,
6057                             const struct devlink_param *params,
6058                             size_t params_count)
6059 {
6060         return __devlink_params_register(devlink, 0, &devlink->param_list,
6061                                          params, params_count,
6062                                          DEVLINK_CMD_PARAM_NEW,
6063                                          DEVLINK_CMD_PARAM_DEL);
6064 }
6065 EXPORT_SYMBOL_GPL(devlink_params_register);
6066
6067 /**
6068  *      devlink_params_unregister - unregister configuration parameters
6069  *      @devlink: devlink
6070  *      @params: configuration parameters to unregister
6071  *      @params_count: number of parameters provided
6072  */
6073 void devlink_params_unregister(struct devlink *devlink,
6074                                const struct devlink_param *params,
6075                                size_t params_count)
6076 {
6077         return __devlink_params_unregister(devlink, 0, &devlink->param_list,
6078                                            params, params_count,
6079                                            DEVLINK_CMD_PARAM_DEL);
6080 }
6081 EXPORT_SYMBOL_GPL(devlink_params_unregister);
6082
6083 /**
6084  *      devlink_params_publish - publish configuration parameters
6085  *
6086  *      @devlink: devlink
6087  *
6088  *      Publish previously registered configuration parameters.
6089  */
6090 void devlink_params_publish(struct devlink *devlink)
6091 {
6092         struct devlink_param_item *param_item;
6093
6094         list_for_each_entry(param_item, &devlink->param_list, list) {
6095                 if (param_item->published)
6096                         continue;
6097                 param_item->published = true;
6098                 devlink_param_notify(devlink, 0, param_item,
6099                                      DEVLINK_CMD_PARAM_NEW);
6100         }
6101 }
6102 EXPORT_SYMBOL_GPL(devlink_params_publish);
6103
6104 /**
6105  *      devlink_params_unpublish - unpublish configuration parameters
6106  *
6107  *      @devlink: devlink
6108  *
6109  *      Unpublish previously registered configuration parameters.
6110  */
6111 void devlink_params_unpublish(struct devlink *devlink)
6112 {
6113         struct devlink_param_item *param_item;
6114
6115         list_for_each_entry(param_item, &devlink->param_list, list) {
6116                 if (!param_item->published)
6117                         continue;
6118                 param_item->published = false;
6119                 devlink_param_notify(devlink, 0, param_item,
6120                                      DEVLINK_CMD_PARAM_DEL);
6121         }
6122 }
6123 EXPORT_SYMBOL_GPL(devlink_params_unpublish);
6124
6125 /**
6126  *      devlink_port_params_register - register port configuration parameters
6127  *
6128  *      @devlink_port: devlink port
6129  *      @params: configuration parameters array
6130  *      @params_count: number of parameters provided
6131  *
6132  *      Register the configuration parameters supported by the port.
6133  */
6134 int devlink_port_params_register(struct devlink_port *devlink_port,
6135                                  const struct devlink_param *params,
6136                                  size_t params_count)
6137 {
6138         return __devlink_params_register(devlink_port->devlink,
6139                                          devlink_port->index,
6140                                          &devlink_port->param_list, params,
6141                                          params_count,
6142                                          DEVLINK_CMD_PORT_PARAM_NEW,
6143                                          DEVLINK_CMD_PORT_PARAM_DEL);
6144 }
6145 EXPORT_SYMBOL_GPL(devlink_port_params_register);
6146
6147 /**
6148  *      devlink_port_params_unregister - unregister port configuration
6149  *      parameters
6150  *
6151  *      @devlink_port: devlink port
6152  *      @params: configuration parameters array
6153  *      @params_count: number of parameters provided
6154  */
6155 void devlink_port_params_unregister(struct devlink_port *devlink_port,
6156                                     const struct devlink_param *params,
6157                                     size_t params_count)
6158 {
6159         return __devlink_params_unregister(devlink_port->devlink,
6160                                            devlink_port->index,
6161                                            &devlink_port->param_list,
6162                                            params, params_count,
6163                                            DEVLINK_CMD_PORT_PARAM_DEL);
6164 }
6165 EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
6166
6167 static int
6168 __devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
6169                                      union devlink_param_value *init_val)
6170 {
6171         struct devlink_param_item *param_item;
6172
6173         param_item = devlink_param_find_by_id(param_list, param_id);
6174         if (!param_item)
6175                 return -EINVAL;
6176
6177         if (!param_item->driverinit_value_valid ||
6178             !devlink_param_cmode_is_supported(param_item->param,
6179                                               DEVLINK_PARAM_CMODE_DRIVERINIT))
6180                 return -EOPNOTSUPP;
6181
6182         if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
6183                 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
6184         else
6185                 *init_val = param_item->driverinit_value;
6186
6187         return 0;
6188 }
6189
6190 static int
6191 __devlink_param_driverinit_value_set(struct devlink *devlink,
6192                                      unsigned int port_index,
6193                                      struct list_head *param_list, u32 param_id,
6194                                      union devlink_param_value init_val,
6195                                      enum devlink_command cmd)
6196 {
6197         struct devlink_param_item *param_item;
6198
6199         param_item = devlink_param_find_by_id(param_list, param_id);
6200         if (!param_item)
6201                 return -EINVAL;
6202
6203         if (!devlink_param_cmode_is_supported(param_item->param,
6204                                               DEVLINK_PARAM_CMODE_DRIVERINIT))
6205                 return -EOPNOTSUPP;
6206
6207         if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
6208                 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
6209         else
6210                 param_item->driverinit_value = init_val;
6211         param_item->driverinit_value_valid = true;
6212
6213         devlink_param_notify(devlink, port_index, param_item, cmd);
6214         return 0;
6215 }
6216
6217 /**
6218  *      devlink_param_driverinit_value_get - get configuration parameter
6219  *                                           value for driver initializing
6220  *
6221  *      @devlink: devlink
6222  *      @param_id: parameter ID
6223  *      @init_val: value of parameter in driverinit configuration mode
6224  *
6225  *      This function should be used by the driver to get driverinit
6226  *      configuration for initialization after reload command.
6227  */
6228 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
6229                                        union devlink_param_value *init_val)
6230 {
6231         if (!devlink->ops->reload)
6232                 return -EOPNOTSUPP;
6233
6234         return __devlink_param_driverinit_value_get(&devlink->param_list,
6235                                                     param_id, init_val);
6236 }
6237 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
6238
6239 /**
6240  *      devlink_param_driverinit_value_set - set value of configuration
6241  *                                           parameter for driverinit
6242  *                                           configuration mode
6243  *
6244  *      @devlink: devlink
6245  *      @param_id: parameter ID
6246  *      @init_val: value of parameter to set for driverinit configuration mode
6247  *
6248  *      This function should be used by the driver to set driverinit
6249  *      configuration mode default value.
6250  */
6251 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
6252                                        union devlink_param_value init_val)
6253 {
6254         return __devlink_param_driverinit_value_set(devlink, 0,
6255                                                     &devlink->param_list,
6256                                                     param_id, init_val,
6257                                                     DEVLINK_CMD_PARAM_NEW);
6258 }
6259 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
6260
6261 /**
6262  *      devlink_port_param_driverinit_value_get - get configuration parameter
6263  *                                              value for driver initializing
6264  *
6265  *      @devlink_port: devlink_port
6266  *      @param_id: parameter ID
6267  *      @init_val: value of parameter in driverinit configuration mode
6268  *
6269  *      This function should be used by the driver to get driverinit
6270  *      configuration for initialization after reload command.
6271  */
6272 int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
6273                                             u32 param_id,
6274                                             union devlink_param_value *init_val)
6275 {
6276         struct devlink *devlink = devlink_port->devlink;
6277
6278         if (!devlink->ops->reload)
6279                 return -EOPNOTSUPP;
6280
6281         return __devlink_param_driverinit_value_get(&devlink_port->param_list,
6282                                                     param_id, init_val);
6283 }
6284 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
6285
6286 /**
6287  *     devlink_port_param_driverinit_value_set - set value of configuration
6288  *                                               parameter for driverinit
6289  *                                               configuration mode
6290  *
6291  *     @devlink_port: devlink_port
6292  *     @param_id: parameter ID
6293  *     @init_val: value of parameter to set for driverinit configuration mode
6294  *
6295  *     This function should be used by the driver to set driverinit
6296  *     configuration mode default value.
6297  */
6298 int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
6299                                             u32 param_id,
6300                                             union devlink_param_value init_val)
6301 {
6302         return __devlink_param_driverinit_value_set(devlink_port->devlink,
6303                                                     devlink_port->index,
6304                                                     &devlink_port->param_list,
6305                                                     param_id, init_val,
6306                                                     DEVLINK_CMD_PORT_PARAM_NEW);
6307 }
6308 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
6309
6310 /**
6311  *      devlink_param_value_changed - notify devlink on a parameter's value
6312  *                                    change. Should be called by the driver
6313  *                                    right after the change.
6314  *
6315  *      @devlink: devlink
6316  *      @param_id: parameter ID
6317  *
6318  *      This function should be used by the driver to notify devlink on value
6319  *      change, excluding driverinit configuration mode.
6320  *      For driverinit configuration mode driver should use the function
6321  */
6322 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
6323 {
6324         struct devlink_param_item *param_item;
6325
6326         param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
6327         WARN_ON(!param_item);
6328
6329         devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
6330 }
6331 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
6332
6333 /**
6334  *     devlink_port_param_value_changed - notify devlink on a parameter's value
6335  *                                      change. Should be called by the driver
6336  *                                      right after the change.
6337  *
6338  *     @devlink_port: devlink_port
6339  *     @param_id: parameter ID
6340  *
6341  *     This function should be used by the driver to notify devlink on value
6342  *     change, excluding driverinit configuration mode.
6343  *     For driverinit configuration mode driver should use the function
6344  *     devlink_port_param_driverinit_value_set() instead.
6345  */
6346 void devlink_port_param_value_changed(struct devlink_port *devlink_port,
6347                                       u32 param_id)
6348 {
6349         struct devlink_param_item *param_item;
6350
6351         param_item = devlink_param_find_by_id(&devlink_port->param_list,
6352                                               param_id);
6353         WARN_ON(!param_item);
6354
6355         devlink_param_notify(devlink_port->devlink, devlink_port->index,
6356                              param_item, DEVLINK_CMD_PORT_PARAM_NEW);
6357 }
6358 EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
6359
6360 /**
6361  *      devlink_param_value_str_fill - Safely fill-up the string preventing
6362  *                                     from overflow of the preallocated buffer
6363  *
6364  *      @dst_val: destination devlink_param_value
6365  *      @src: source buffer
6366  */
6367 void devlink_param_value_str_fill(union devlink_param_value *dst_val,
6368                                   const char *src)
6369 {
6370         size_t len;
6371
6372         len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
6373         WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
6374 }
6375 EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
6376
6377 /**
6378  *      devlink_region_create - create a new address region
6379  *
6380  *      @devlink: devlink
6381  *      @region_name: region name
6382  *      @region_max_snapshots: Maximum supported number of snapshots for region
6383  *      @region_size: size of region
6384  */
6385 struct devlink_region *devlink_region_create(struct devlink *devlink,
6386                                              const char *region_name,
6387                                              u32 region_max_snapshots,
6388                                              u64 region_size)
6389 {
6390         struct devlink_region *region;
6391         int err = 0;
6392
6393         mutex_lock(&devlink->lock);
6394
6395         if (devlink_region_get_by_name(devlink, region_name)) {
6396                 err = -EEXIST;
6397                 goto unlock;
6398         }
6399
6400         region = kzalloc(sizeof(*region), GFP_KERNEL);
6401         if (!region) {
6402                 err = -ENOMEM;
6403                 goto unlock;
6404         }
6405
6406         region->devlink = devlink;
6407         region->max_snapshots = region_max_snapshots;
6408         region->name = region_name;
6409         region->size = region_size;
6410         INIT_LIST_HEAD(&region->snapshot_list);
6411         list_add_tail(&region->list, &devlink->region_list);
6412         devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
6413
6414         mutex_unlock(&devlink->lock);
6415         return region;
6416
6417 unlock:
6418         mutex_unlock(&devlink->lock);
6419         return ERR_PTR(err);
6420 }
6421 EXPORT_SYMBOL_GPL(devlink_region_create);
6422
6423 /**
6424  *      devlink_region_destroy - destroy address region
6425  *
6426  *      @region: devlink region to destroy
6427  */
6428 void devlink_region_destroy(struct devlink_region *region)
6429 {
6430         struct devlink *devlink = region->devlink;
6431         struct devlink_snapshot *snapshot, *ts;
6432
6433         mutex_lock(&devlink->lock);
6434
6435         /* Free all snapshots of region */
6436         list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
6437                 devlink_region_snapshot_del(snapshot);
6438
6439         list_del(&region->list);
6440
6441         devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
6442         mutex_unlock(&devlink->lock);
6443         kfree(region);
6444 }
6445 EXPORT_SYMBOL_GPL(devlink_region_destroy);
6446
6447 /**
6448  *      devlink_region_shapshot_id_get - get snapshot ID
6449  *
6450  *      This callback should be called when adding a new snapshot,
6451  *      Driver should use the same id for multiple snapshots taken
6452  *      on multiple regions at the same time/by the same trigger.
6453  *
6454  *      @devlink: devlink
6455  */
6456 u32 devlink_region_shapshot_id_get(struct devlink *devlink)
6457 {
6458         u32 id;
6459
6460         mutex_lock(&devlink->lock);
6461         id = ++devlink->snapshot_id;
6462         mutex_unlock(&devlink->lock);
6463
6464         return id;
6465 }
6466 EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
6467
6468 /**
6469  *      devlink_region_snapshot_create - create a new snapshot
6470  *      This will add a new snapshot of a region. The snapshot
6471  *      will be stored on the region struct and can be accessed
6472  *      from devlink. This is useful for future analyses of snapshots.
6473  *      Multiple snapshots can be created on a region.
6474  *      The @snapshot_id should be obtained using the getter function.
6475  *
6476  *      @region: devlink region of the snapshot
6477  *      @data_len: size of snapshot data
6478  *      @data: snapshot data
6479  *      @snapshot_id: snapshot id to be created
6480  *      @data_destructor: pointer to destructor function to free data
6481  */
6482 int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
6483                                    u8 *data, u32 snapshot_id,
6484                                    devlink_snapshot_data_dest_t *data_destructor)
6485 {
6486         struct devlink *devlink = region->devlink;
6487         struct devlink_snapshot *snapshot;
6488         int err;
6489
6490         mutex_lock(&devlink->lock);
6491
6492         /* check if region can hold one more snapshot */
6493         if (region->cur_snapshots == region->max_snapshots) {
6494                 err = -ENOMEM;
6495                 goto unlock;
6496         }
6497
6498         if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
6499                 err = -EEXIST;
6500                 goto unlock;
6501         }
6502
6503         snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
6504         if (!snapshot) {
6505                 err = -ENOMEM;
6506                 goto unlock;
6507         }
6508
6509         snapshot->id = snapshot_id;
6510         snapshot->region = region;
6511         snapshot->data = data;
6512         snapshot->data_len = data_len;
6513         snapshot->data_destructor = data_destructor;
6514
6515         list_add_tail(&snapshot->list, &region->snapshot_list);
6516
6517         region->cur_snapshots++;
6518
6519         devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
6520         mutex_unlock(&devlink->lock);
6521         return 0;
6522
6523 unlock:
6524         mutex_unlock(&devlink->lock);
6525         return err;
6526 }
6527 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
6528
6529 static void __devlink_compat_running_version(struct devlink *devlink,
6530                                              char *buf, size_t len)
6531 {
6532         const struct nlattr *nlattr;
6533         struct devlink_info_req req;
6534         struct sk_buff *msg;
6535         int rem, err;
6536
6537         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6538         if (!msg)
6539                 return;
6540
6541         req.msg = msg;
6542         err = devlink->ops->info_get(devlink, &req, NULL);
6543         if (err)
6544                 goto free_msg;
6545
6546         nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
6547                 const struct nlattr *kv;
6548                 int rem_kv;
6549
6550                 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
6551                         continue;
6552
6553                 nla_for_each_nested(kv, nlattr, rem_kv) {
6554                         if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
6555                                 continue;
6556
6557                         strlcat(buf, nla_data(kv), len);
6558                         strlcat(buf, " ", len);
6559                 }
6560         }
6561 free_msg:
6562         nlmsg_free(msg);
6563 }
6564
6565 void devlink_compat_running_version(struct net_device *dev,
6566                                     char *buf, size_t len)
6567 {
6568         struct devlink *devlink;
6569
6570         dev_hold(dev);
6571         rtnl_unlock();
6572
6573         devlink = netdev_to_devlink(dev);
6574         if (!devlink || !devlink->ops->info_get)
6575                 goto out;
6576
6577         mutex_lock(&devlink->lock);
6578         __devlink_compat_running_version(devlink, buf, len);
6579         mutex_unlock(&devlink->lock);
6580
6581 out:
6582         rtnl_lock();
6583         dev_put(dev);
6584 }
6585
6586 int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
6587 {
6588         struct devlink *devlink;
6589         int ret;
6590
6591         dev_hold(dev);
6592         rtnl_unlock();
6593
6594         devlink = netdev_to_devlink(dev);
6595         if (!devlink || !devlink->ops->flash_update) {
6596                 ret = -EOPNOTSUPP;
6597                 goto out;
6598         }
6599
6600         mutex_lock(&devlink->lock);
6601         ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
6602         mutex_unlock(&devlink->lock);
6603
6604 out:
6605         rtnl_lock();
6606         dev_put(dev);
6607
6608         return ret;
6609 }
6610
6611 int devlink_compat_phys_port_name_get(struct net_device *dev,
6612                                       char *name, size_t len)
6613 {
6614         struct devlink_port *devlink_port;
6615
6616         /* RTNL mutex is held here which ensures that devlink_port
6617          * instance cannot disappear in the middle. No need to take
6618          * any devlink lock as only permanent values are accessed.
6619          */
6620         ASSERT_RTNL();
6621
6622         devlink_port = netdev_to_devlink_port(dev);
6623         if (!devlink_port)
6624                 return -EOPNOTSUPP;
6625
6626         return __devlink_port_phys_port_name_get(devlink_port, name, len);
6627 }
6628
6629 int devlink_compat_switch_id_get(struct net_device *dev,
6630                                  struct netdev_phys_item_id *ppid)
6631 {
6632         struct devlink_port *devlink_port;
6633
6634         /* RTNL mutex is held here which ensures that devlink_port
6635          * instance cannot disappear in the middle. No need to take
6636          * any devlink lock as only permanent values are accessed.
6637          */
6638         ASSERT_RTNL();
6639         devlink_port = netdev_to_devlink_port(dev);
6640         if (!devlink_port || !devlink_port->attrs.switch_port)
6641                 return -EOPNOTSUPP;
6642
6643         memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
6644
6645         return 0;
6646 }
6647
6648 static int __init devlink_init(void)
6649 {
6650         return genl_register_family(&devlink_nl_family);
6651 }
6652
6653 subsys_initcall(devlink_init);
This page took 0.420292 seconds and 4 git commands to generate.