| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /* SPDX-License-Identifier: GPL-2.0-or-later */
- /* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
- */
- #include <linux/device.h>
- #include <linux/etherdevice.h>
- #include <linux/mutex.h>
- #include <linux/netdevice.h>
- #include <linux/notifier.h>
- #include <linux/types.h>
- #include <linux/workqueue.h>
- #include <linux/xarray.h>
- #include <net/devlink.h>
- #include <net/net_namespace.h>
- #include <net/rtnetlink.h>
- #include <rdma/ib_verbs.h>
- #include "netlink_gen.h"
- struct devlink_rel;
- #define DEVLINK_REGISTERED XA_MARK_1
- #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
- (__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
- struct devlink_dev_stats {
- u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
- u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
- };
- struct devlink {
- u32 index;
- struct xarray ports;
- struct list_head rate_list;
- struct list_head sb_list;
- struct list_head dpipe_table_list;
- struct list_head resource_list;
- struct xarray params;
- struct list_head region_list;
- struct list_head reporter_list;
- struct devlink_dpipe_headers *dpipe_headers;
- struct list_head trap_list;
- struct list_head trap_group_list;
- struct list_head trap_policer_list;
- struct list_head linecard_list;
- const struct devlink_ops *ops;
- struct xarray snapshot_ids;
- struct devlink_dev_stats stats;
- struct device *dev;
- possible_net_t _net;
- /* Serializes access to devlink instance specific objects such as
- * port, sb, dpipe, resource, params, region, traps and more.
- */
- struct mutex lock;
- struct lock_class_key lock_key;
- u8 reload_failed:1;
- refcount_t refcount;
- struct rcu_work rwork;
- struct devlink_rel *rel;
- struct xarray nested_rels;
- char priv[] __aligned(NETDEV_ALIGN);
- };
- extern struct xarray devlinks;
- extern struct genl_family devlink_nl_family;
- /* devlink instances are open to the access from the user space after
- * devlink_register() call. Such logical barrier allows us to have certain
- * expectations related to locking.
- *
- * Before *_register() - we are in initialization stage and no parallel
- * access possible to the devlink instance. All drivers perform that phase
- * by implicitly holding device_lock.
- *
- * After *_register() - users and driver can access devlink instance at
- * the same time.
- */
- #define ASSERT_DEVLINK_REGISTERED(d) \
- WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
- #define ASSERT_DEVLINK_NOT_REGISTERED(d) \
- WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
- /* Iterate over devlink pointers which were possible to get reference to.
- * devlink_put() needs to be called for each iterated devlink pointer
- * in loop body in order to release the reference.
- */
- #define devlinks_xa_for_each_registered_get(net, index, devlink) \
- for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
- struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
- static inline bool __devl_is_registered(struct devlink *devlink)
- {
- return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
- }
- static inline bool devl_is_registered(struct devlink *devlink)
- {
- devl_assert_locked(devlink);
- return __devl_is_registered(devlink);
- }
- static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
- {
- if (dev_lock)
- device_lock(devlink->dev);
- devl_lock(devlink);
- }
- static inline void devl_dev_unlock(struct devlink *devlink, bool dev_lock)
- {
- devl_unlock(devlink);
- if (dev_lock)
- device_unlock(devlink->dev);
- }
- typedef void devlink_rel_notify_cb_t(struct devlink *devlink, u32 obj_index);
- typedef void devlink_rel_cleanup_cb_t(struct devlink *devlink, u32 obj_index,
- u32 rel_index);
- void devlink_rel_nested_in_clear(u32 rel_index);
- int devlink_rel_nested_in_add(u32 *rel_index, u32 devlink_index,
- u32 obj_index, devlink_rel_notify_cb_t *notify_cb,
- devlink_rel_cleanup_cb_t *cleanup_cb,
- struct devlink *devlink);
- void devlink_rel_nested_in_notify(struct devlink *devlink);
- int devlink_rel_devlink_handle_put(struct sk_buff *msg, struct devlink *devlink,
- u32 rel_index, int attrtype,
- bool *msg_updated);
- /* Netlink */
- enum devlink_multicast_groups {
- DEVLINK_MCGRP_CONFIG,
- };
- /* state held across netlink dumps */
- struct devlink_nl_dump_state {
- unsigned long instance;
- int idx;
- union {
- /* DEVLINK_CMD_REGION_READ */
- struct {
- u64 start_offset;
- };
- /* DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET */
- struct {
- u64 dump_ts;
- };
- };
- };
- typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg,
- struct devlink *devlink,
- struct netlink_callback *cb,
- int flags);
- struct devlink *
- devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
- bool dev_lock);
- int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
- devlink_nl_dump_one_func_t *dump_one);
- static inline struct devlink_nl_dump_state *
- devlink_dump_state(struct netlink_callback *cb)
- {
- NL_ASSERT_DUMP_CTX_FITS(struct devlink_nl_dump_state);
- return (struct devlink_nl_dump_state *)cb->ctx;
- }
- static inline int
- devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
- {
- if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
- return -EMSGSIZE;
- if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
- return -EMSGSIZE;
- return 0;
- }
- int devlink_nl_put_nested_handle(struct sk_buff *msg, struct net *net,
- struct devlink *devlink, int attrtype);
- int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info);
- static inline bool devlink_nl_notify_need(struct devlink *devlink)
- {
- return genl_has_listeners(&devlink_nl_family, devlink_net(devlink),
- DEVLINK_MCGRP_CONFIG);
- }
- struct devlink_obj_desc {
- struct rcu_head rcu;
- const char *bus_name;
- const char *dev_name;
- unsigned int port_index;
- bool port_index_valid;
- long data[];
- };
- static inline void devlink_nl_obj_desc_init(struct devlink_obj_desc *desc,
- struct devlink *devlink)
- {
- memset(desc, 0, sizeof(*desc));
- desc->bus_name = devlink->dev->bus->name;
- desc->dev_name = dev_name(devlink->dev);
- }
- static inline void devlink_nl_obj_desc_port_set(struct devlink_obj_desc *desc,
- struct devlink_port *devlink_port)
- {
- desc->port_index = devlink_port->index;
- desc->port_index_valid = true;
- }
- int devlink_nl_notify_filter(struct sock *dsk, struct sk_buff *skb, void *data);
- static inline void devlink_nl_notify_send_desc(struct devlink *devlink,
- struct sk_buff *msg,
- struct devlink_obj_desc *desc)
- {
- genlmsg_multicast_netns_filtered(&devlink_nl_family,
- devlink_net(devlink),
- msg, 0, DEVLINK_MCGRP_CONFIG,
- GFP_KERNEL,
- devlink_nl_notify_filter, desc);
- }
- static inline void devlink_nl_notify_send(struct devlink *devlink,
- struct sk_buff *msg)
- {
- struct devlink_obj_desc desc;
- devlink_nl_obj_desc_init(&desc, devlink);
- devlink_nl_notify_send_desc(devlink, msg, &desc);
- }
- /* Notify */
- void devlink_notify_register(struct devlink *devlink);
- void devlink_notify_unregister(struct devlink *devlink);
- void devlink_ports_notify_register(struct devlink *devlink);
- void devlink_ports_notify_unregister(struct devlink *devlink);
- void devlink_params_notify_register(struct devlink *devlink);
- void devlink_params_notify_unregister(struct devlink *devlink);
- void devlink_regions_notify_register(struct devlink *devlink);
- void devlink_regions_notify_unregister(struct devlink *devlink);
- void devlink_trap_policers_notify_register(struct devlink *devlink);
- void devlink_trap_policers_notify_unregister(struct devlink *devlink);
- void devlink_trap_groups_notify_register(struct devlink *devlink);
- void devlink_trap_groups_notify_unregister(struct devlink *devlink);
- void devlink_traps_notify_register(struct devlink *devlink);
- void devlink_traps_notify_unregister(struct devlink *devlink);
- void devlink_rates_notify_register(struct devlink *devlink);
- void devlink_rates_notify_unregister(struct devlink *devlink);
- void devlink_linecards_notify_register(struct devlink *devlink);
- void devlink_linecards_notify_unregister(struct devlink *devlink);
- /* Ports */
- #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port) \
- WARN_ON_ONCE(!(devlink_port)->initialized)
- struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
- unsigned int port_index);
- int devlink_port_netdevice_event(struct notifier_block *nb,
- unsigned long event, void *ptr);
- struct devlink_port *
- devlink_port_get_from_info(struct devlink *devlink, struct genl_info *info);
- struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
- struct nlattr **attrs);
- /* Reload */
- bool devlink_reload_actions_valid(const struct devlink_ops *ops);
- int devlink_reload(struct devlink *devlink, struct net *dest_net,
- enum devlink_reload_action action,
- enum devlink_reload_limit limit,
- u32 *actions_performed, struct netlink_ext_ack *extack);
- static inline bool devlink_reload_supported(const struct devlink_ops *ops)
- {
- return ops->reload_down && ops->reload_up;
- }
- /* Params */
- void devlink_params_driverinit_load_new(struct devlink *devlink);
- /* Resources */
- struct devlink_resource;
- int devlink_resources_validate(struct devlink *devlink,
- struct devlink_resource *resource,
- struct genl_info *info);
- /* Rates */
- int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
- struct netlink_ext_ack *extack);
- /* Linecards */
- unsigned int devlink_linecard_index(struct devlink_linecard *linecard);
|