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