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