1687125b5SJakub Kicinski /* SPDX-License-Identifier: GPL-2.0-or-later */
2687125b5SJakub Kicinski /* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
3687125b5SJakub Kicinski * Copyright (c) 2016 Jiri Pirko <[email protected]>
4687125b5SJakub Kicinski */
5687125b5SJakub Kicinski
6e21c52d7SIdo Schimmel #include <linux/device.h>
7eec1e5eaSJiri Pirko #include <linux/etherdevice.h>
8687125b5SJakub Kicinski #include <linux/mutex.h>
9687125b5SJakub Kicinski #include <linux/netdevice.h>
10687125b5SJakub Kicinski #include <linux/notifier.h>
11687125b5SJakub Kicinski #include <linux/types.h>
1293e71edfSJakub Kicinski #include <linux/workqueue.h>
13687125b5SJakub Kicinski #include <linux/xarray.h>
14687125b5SJakub Kicinski #include <net/devlink.h>
15687125b5SJakub Kicinski #include <net/net_namespace.h>
16eec1e5eaSJiri Pirko #include <net/rtnetlink.h>
17eec1e5eaSJiri Pirko #include <rdma/ib_verbs.h>
18687125b5SJakub Kicinski
19b2551b15SJiri Pirko #include "netlink_gen.h"
20b2551b15SJiri Pirko
21c137743bSJiri Pirko struct devlink_rel;
22c137743bSJiri Pirko
23687125b5SJakub Kicinski #define DEVLINK_REGISTERED XA_MARK_1
24687125b5SJakub Kicinski
25687125b5SJakub Kicinski #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
26687125b5SJakub Kicinski (__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
27687125b5SJakub Kicinski
28687125b5SJakub Kicinski struct devlink_dev_stats {
29687125b5SJakub Kicinski u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
30687125b5SJakub Kicinski u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
31687125b5SJakub Kicinski };
32687125b5SJakub Kicinski
33687125b5SJakub Kicinski struct devlink {
34687125b5SJakub Kicinski u32 index;
35687125b5SJakub Kicinski struct xarray ports;
36687125b5SJakub Kicinski struct list_head rate_list;
37687125b5SJakub Kicinski struct list_head sb_list;
38687125b5SJakub Kicinski struct list_head dpipe_table_list;
39687125b5SJakub Kicinski struct list_head resource_list;
40a72e17b4SJiri Pirko struct xarray params;
41687125b5SJakub Kicinski struct list_head region_list;
42687125b5SJakub Kicinski struct list_head reporter_list;
43687125b5SJakub Kicinski struct devlink_dpipe_headers *dpipe_headers;
44687125b5SJakub Kicinski struct list_head trap_list;
45687125b5SJakub Kicinski struct list_head trap_group_list;
46687125b5SJakub Kicinski struct list_head trap_policer_list;
47687125b5SJakub Kicinski struct list_head linecard_list;
48687125b5SJakub Kicinski const struct devlink_ops *ops;
49687125b5SJakub Kicinski struct xarray snapshot_ids;
50687125b5SJakub Kicinski struct devlink_dev_stats stats;
51687125b5SJakub Kicinski struct device *dev;
52687125b5SJakub Kicinski possible_net_t _net;
53687125b5SJakub Kicinski /* Serializes access to devlink instance specific objects such as
54687125b5SJakub Kicinski * port, sb, dpipe, resource, params, region, traps and more.
55687125b5SJakub Kicinski */
56687125b5SJakub Kicinski struct mutex lock;
57687125b5SJakub Kicinski struct lock_class_key lock_key;
58687125b5SJakub Kicinski u8 reload_failed:1;
59687125b5SJakub Kicinski refcount_t refcount;
6093e71edfSJakub Kicinski struct rcu_work rwork;
61c137743bSJiri Pirko struct devlink_rel *rel;
62c5e1bf8aSJiri Pirko struct xarray nested_rels;
63687125b5SJakub Kicinski char priv[] __aligned(NETDEV_ALIGN);
64687125b5SJakub Kicinski };
65687125b5SJakub Kicinski
66687125b5SJakub Kicinski extern struct xarray devlinks;
67687125b5SJakub Kicinski extern struct genl_family devlink_nl_family;
68687125b5SJakub Kicinski
69687125b5SJakub Kicinski /* devlink instances are open to the access from the user space after
70687125b5SJakub Kicinski * devlink_register() call. Such logical barrier allows us to have certain
71687125b5SJakub Kicinski * expectations related to locking.
72687125b5SJakub Kicinski *
73687125b5SJakub Kicinski * Before *_register() - we are in initialization stage and no parallel
74687125b5SJakub Kicinski * access possible to the devlink instance. All drivers perform that phase
75687125b5SJakub Kicinski * by implicitly holding device_lock.
76687125b5SJakub Kicinski *
77687125b5SJakub Kicinski * After *_register() - users and driver can access devlink instance at
78687125b5SJakub Kicinski * the same time.
79687125b5SJakub Kicinski */
80687125b5SJakub Kicinski #define ASSERT_DEVLINK_REGISTERED(d) \
81687125b5SJakub Kicinski WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
82687125b5SJakub Kicinski #define ASSERT_DEVLINK_NOT_REGISTERED(d) \
83687125b5SJakub Kicinski WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
84687125b5SJakub Kicinski
85687125b5SJakub Kicinski /* Iterate over devlink pointers which were possible to get reference to.
86687125b5SJakub Kicinski * devlink_put() needs to be called for each iterated devlink pointer
87687125b5SJakub Kicinski * in loop body in order to release the reference.
88687125b5SJakub Kicinski */
89687125b5SJakub Kicinski #define devlinks_xa_for_each_registered_get(net, index, devlink) \
90d7727819SJakub Kicinski for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
91687125b5SJakub Kicinski
92d7727819SJakub Kicinski struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
93687125b5SJakub Kicinski
__devl_is_registered(struct devlink * devlink)9411280ddeSJiri Pirko static inline bool __devl_is_registered(struct devlink *devlink)
9511280ddeSJiri Pirko {
9611280ddeSJiri Pirko return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
9711280ddeSJiri Pirko }
9811280ddeSJiri Pirko
devl_is_registered(struct devlink * devlink)99ed539ba6SJakub Kicinski static inline bool devl_is_registered(struct devlink *devlink)
100ed539ba6SJakub Kicinski {
10163ba54a5SJiri Pirko devl_assert_locked(devlink);
10211280ddeSJiri Pirko return __devl_is_registered(devlink);
103ed539ba6SJakub Kicinski }
104ed539ba6SJakub Kicinski
devl_dev_lock(struct devlink * devlink,bool dev_lock)105e21c52d7SIdo Schimmel static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
106e21c52d7SIdo Schimmel {
107e21c52d7SIdo Schimmel if (dev_lock)
108e21c52d7SIdo Schimmel device_lock(devlink->dev);
109e21c52d7SIdo Schimmel devl_lock(devlink);
110e21c52d7SIdo Schimmel }
111e21c52d7SIdo Schimmel
devl_dev_unlock(struct devlink * devlink,bool dev_lock)112e21c52d7SIdo Schimmel static inline void devl_dev_unlock(struct devlink *devlink, bool dev_lock)
113e21c52d7SIdo Schimmel {
114e21c52d7SIdo Schimmel devl_unlock(devlink);
115e21c52d7SIdo Schimmel if (dev_lock)
116e21c52d7SIdo Schimmel device_unlock(devlink->dev);
117e21c52d7SIdo Schimmel }
118e21c52d7SIdo Schimmel
119c137743bSJiri Pirko typedef void devlink_rel_notify_cb_t(struct devlink *devlink, u32 obj_index);
120c137743bSJiri Pirko typedef void devlink_rel_cleanup_cb_t(struct devlink *devlink, u32 obj_index,
121c137743bSJiri Pirko u32 rel_index);
122c137743bSJiri Pirko
123c137743bSJiri Pirko void devlink_rel_nested_in_clear(u32 rel_index);
124c137743bSJiri Pirko int devlink_rel_nested_in_add(u32 *rel_index, u32 devlink_index,
125c137743bSJiri Pirko u32 obj_index, devlink_rel_notify_cb_t *notify_cb,
126c137743bSJiri Pirko devlink_rel_cleanup_cb_t *cleanup_cb,
127c137743bSJiri Pirko struct devlink *devlink);
128c137743bSJiri Pirko void devlink_rel_nested_in_notify(struct devlink *devlink);
129c137743bSJiri Pirko int devlink_rel_devlink_handle_put(struct sk_buff *msg, struct devlink *devlink,
130c137743bSJiri Pirko u32 rel_index, int attrtype,
131c137743bSJiri Pirko bool *msg_updated);
132c137743bSJiri Pirko
133687125b5SJakub Kicinski /* Netlink */
134623cd13bSJakub Kicinski enum devlink_multicast_groups {
135623cd13bSJakub Kicinski DEVLINK_MCGRP_CONFIG,
136623cd13bSJakub Kicinski };
137623cd13bSJakub Kicinski
1383015f822SJakub Kicinski /* state held across netlink dumps */
1393015f822SJakub Kicinski struct devlink_nl_dump_state {
140731d69a6SJakub Kicinski unsigned long instance;
1413015f822SJakub Kicinski int idx;
1423015f822SJakub Kicinski union {
1433015f822SJakub Kicinski /* DEVLINK_CMD_REGION_READ */
1443015f822SJakub Kicinski struct {
1453015f822SJakub Kicinski u64 start_offset;
1463015f822SJakub Kicinski };
1473015f822SJakub Kicinski /* DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET */
1483015f822SJakub Kicinski struct {
1493015f822SJakub Kicinski u64 dump_ts;
1503015f822SJakub Kicinski };
1513015f822SJakub Kicinski };
1523015f822SJakub Kicinski };
1533015f822SJakub Kicinski
154491a2487SJiri Pirko typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg,
155491a2487SJiri Pirko struct devlink *devlink,
1567d3c6fecSJiri Pirko struct netlink_callback *cb,
1577d3c6fecSJiri Pirko int flags);
158491a2487SJiri Pirko
159870c7ad4SJakub Kicinski struct devlink *
160d32c3825SIdo Schimmel devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
161d32c3825SIdo Schimmel bool dev_lock);
162623cd13bSJakub Kicinski
163491a2487SJiri Pirko int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
164491a2487SJiri Pirko devlink_nl_dump_one_func_t *dump_one);
16507f3af66SJakub Kicinski
1663015f822SJakub Kicinski static inline struct devlink_nl_dump_state *
devlink_dump_state(struct netlink_callback * cb)1673015f822SJakub Kicinski devlink_dump_state(struct netlink_callback *cb)
1683015f822SJakub Kicinski {
16913d68a16SPaolo Abeni NL_ASSERT_CTX_FITS(struct devlink_nl_dump_state);
1703015f822SJakub Kicinski
1713015f822SJakub Kicinski return (struct devlink_nl_dump_state *)cb->ctx;
1723015f822SJakub Kicinski }
1733015f822SJakub Kicinski
174dbeeca81SMoshe Shemesh static inline int
devlink_nl_put_handle(struct sk_buff * msg,struct devlink * devlink)175dbeeca81SMoshe Shemesh devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
176dbeeca81SMoshe Shemesh {
177dbeeca81SMoshe Shemesh if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
178dbeeca81SMoshe Shemesh return -EMSGSIZE;
179dbeeca81SMoshe Shemesh if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
180dbeeca81SMoshe Shemesh return -EMSGSIZE;
181dbeeca81SMoshe Shemesh return 0;
182dbeeca81SMoshe Shemesh }
183dbeeca81SMoshe Shemesh
devlink_nl_put_u64(struct sk_buff * msg,int attrtype,u64 val)184*da3ee3cdSPrzemek Kitszel static inline int devlink_nl_put_u64(struct sk_buff *msg, int attrtype, u64 val)
185*da3ee3cdSPrzemek Kitszel {
186*da3ee3cdSPrzemek Kitszel return nla_put_u64_64bit(msg, attrtype, val, DEVLINK_ATTR_PAD);
187*da3ee3cdSPrzemek Kitszel }
188*da3ee3cdSPrzemek Kitszel
189af1f1400SJiri Pirko int devlink_nl_put_nested_handle(struct sk_buff *msg, struct net *net,
1901c2197c4SJiri Pirko struct devlink *devlink, int attrtype);
1912475ed15SJiri Pirko int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info);
1922475ed15SJiri Pirko
devlink_nl_notify_need(struct devlink * devlink)193cddbff47SJiri Pirko static inline bool devlink_nl_notify_need(struct devlink *devlink)
194cddbff47SJiri Pirko {
195cddbff47SJiri Pirko return genl_has_listeners(&devlink_nl_family, devlink_net(devlink),
196cddbff47SJiri Pirko DEVLINK_MCGRP_CONFIG);
197cddbff47SJiri Pirko }
198cddbff47SJiri Pirko
19913b127d2SJiri Pirko struct devlink_obj_desc {
20013b127d2SJiri Pirko struct rcu_head rcu;
20113b127d2SJiri Pirko const char *bus_name;
20213b127d2SJiri Pirko const char *dev_name;
203ded6f77cSJiri Pirko unsigned int port_index;
204ded6f77cSJiri Pirko bool port_index_valid;
20513b127d2SJiri Pirko long data[];
20613b127d2SJiri Pirko };
20713b127d2SJiri Pirko
devlink_nl_obj_desc_init(struct devlink_obj_desc * desc,struct devlink * devlink)20813b127d2SJiri Pirko static inline void devlink_nl_obj_desc_init(struct devlink_obj_desc *desc,
20913b127d2SJiri Pirko struct devlink *devlink)
21013b127d2SJiri Pirko {
21113b127d2SJiri Pirko memset(desc, 0, sizeof(*desc));
21213b127d2SJiri Pirko desc->bus_name = devlink->dev->bus->name;
21313b127d2SJiri Pirko desc->dev_name = dev_name(devlink->dev);
21413b127d2SJiri Pirko }
21513b127d2SJiri Pirko
devlink_nl_obj_desc_port_set(struct devlink_obj_desc * desc,struct devlink_port * devlink_port)216ded6f77cSJiri Pirko static inline void devlink_nl_obj_desc_port_set(struct devlink_obj_desc *desc,
217ded6f77cSJiri Pirko struct devlink_port *devlink_port)
218ded6f77cSJiri Pirko {
219ded6f77cSJiri Pirko desc->port_index = devlink_port->index;
220ded6f77cSJiri Pirko desc->port_index_valid = true;
221ded6f77cSJiri Pirko }
222ded6f77cSJiri Pirko
22313b127d2SJiri Pirko int devlink_nl_notify_filter(struct sock *dsk, struct sk_buff *skb, void *data);
22413b127d2SJiri Pirko
devlink_nl_notify_send_desc(struct devlink * devlink,struct sk_buff * msg,struct devlink_obj_desc * desc)22513b127d2SJiri Pirko static inline void devlink_nl_notify_send_desc(struct devlink *devlink,
22613b127d2SJiri Pirko struct sk_buff *msg,
22713b127d2SJiri Pirko struct devlink_obj_desc *desc)
22813b127d2SJiri Pirko {
22913b127d2SJiri Pirko genlmsg_multicast_netns_filtered(&devlink_nl_family,
23013b127d2SJiri Pirko devlink_net(devlink),
23113b127d2SJiri Pirko msg, 0, DEVLINK_MCGRP_CONFIG,
23213b127d2SJiri Pirko GFP_KERNEL,
23313b127d2SJiri Pirko devlink_nl_notify_filter, desc);
23413b127d2SJiri Pirko }
23513b127d2SJiri Pirko
devlink_nl_notify_send(struct devlink * devlink,struct sk_buff * msg)2365648de0bSJiri Pirko static inline void devlink_nl_notify_send(struct devlink *devlink,
2375648de0bSJiri Pirko struct sk_buff *msg)
2385648de0bSJiri Pirko {
23913b127d2SJiri Pirko struct devlink_obj_desc desc;
24013b127d2SJiri Pirko
24113b127d2SJiri Pirko devlink_nl_obj_desc_init(&desc, devlink);
24213b127d2SJiri Pirko devlink_nl_notify_send_desc(devlink, msg, &desc);
2435648de0bSJiri Pirko }
2445648de0bSJiri Pirko
245dbeeca81SMoshe Shemesh /* Notify */
24671179ac5SJiri Pirko void devlink_notify_register(struct devlink *devlink);
24771179ac5SJiri Pirko void devlink_notify_unregister(struct devlink *devlink);
248eec1e5eaSJiri Pirko void devlink_ports_notify_register(struct devlink *devlink);
249eec1e5eaSJiri Pirko void devlink_ports_notify_unregister(struct devlink *devlink);
250830c41e1SJiri Pirko void devlink_params_notify_register(struct devlink *devlink);
251830c41e1SJiri Pirko void devlink_params_notify_unregister(struct devlink *devlink);
2521aa47ca1SJiri Pirko void devlink_regions_notify_register(struct devlink *devlink);
2531aa47ca1SJiri Pirko void devlink_regions_notify_unregister(struct devlink *devlink);
2544bbdec80SJiri Pirko void devlink_trap_policers_notify_register(struct devlink *devlink);
2554bbdec80SJiri Pirko void devlink_trap_policers_notify_unregister(struct devlink *devlink);
2564bbdec80SJiri Pirko void devlink_trap_groups_notify_register(struct devlink *devlink);
2574bbdec80SJiri Pirko void devlink_trap_groups_notify_unregister(struct devlink *devlink);
2584bbdec80SJiri Pirko void devlink_traps_notify_register(struct devlink *devlink);
2594bbdec80SJiri Pirko void devlink_traps_notify_unregister(struct devlink *devlink);
2607cc7194eSJiri Pirko void devlink_rates_notify_register(struct devlink *devlink);
2617cc7194eSJiri Pirko void devlink_rates_notify_unregister(struct devlink *devlink);
2629edbe6f3SJiri Pirko void devlink_linecards_notify_register(struct devlink *devlink);
2639edbe6f3SJiri Pirko void devlink_linecards_notify_unregister(struct devlink *devlink);
264dbeeca81SMoshe Shemesh
265687125b5SJakub Kicinski /* Ports */
266eec1e5eaSJiri Pirko #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port) \
267eec1e5eaSJiri Pirko WARN_ON_ONCE(!(devlink_port)->initialized)
268eec1e5eaSJiri Pirko
269eec1e5eaSJiri Pirko struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
270eec1e5eaSJiri Pirko unsigned int port_index);
271687125b5SJakub Kicinski int devlink_port_netdevice_event(struct notifier_block *nb,
272687125b5SJakub Kicinski unsigned long event, void *ptr);
273623cd13bSJakub Kicinski struct devlink_port *
274623cd13bSJakub Kicinski devlink_port_get_from_info(struct devlink *devlink, struct genl_info *info);
275db6b5f3eSMoshe Shemesh struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
276db6b5f3eSMoshe Shemesh struct nlattr **attrs);
277623cd13bSJakub Kicinski
278687125b5SJakub Kicinski /* Reload */
279687125b5SJakub Kicinski bool devlink_reload_actions_valid(const struct devlink_ops *ops);
280687125b5SJakub Kicinski int devlink_reload(struct devlink *devlink, struct net *dest_net,
281687125b5SJakub Kicinski enum devlink_reload_action action,
282687125b5SJakub Kicinski enum devlink_reload_limit limit,
283687125b5SJakub Kicinski u32 *actions_performed, struct netlink_ext_ack *extack);
284687125b5SJakub Kicinski
devlink_reload_supported(const struct devlink_ops * ops)285687125b5SJakub Kicinski static inline bool devlink_reload_supported(const struct devlink_ops *ops)
286687125b5SJakub Kicinski {
287687125b5SJakub Kicinski return ops->reload_down && ops->reload_up;
288687125b5SJakub Kicinski }
289623cd13bSJakub Kicinski
290afd888c3SJiri Pirko /* Params */
291afd888c3SJiri Pirko void devlink_params_driverinit_load_new(struct devlink *devlink);
292afd888c3SJiri Pirko
293c6ed7d6eSMoshe Shemesh /* Resources */
294c6ed7d6eSMoshe Shemesh struct devlink_resource;
295c6ed7d6eSMoshe Shemesh int devlink_resources_validate(struct devlink *devlink,
296c6ed7d6eSMoshe Shemesh struct devlink_resource *resource,
297c6ed7d6eSMoshe Shemesh struct genl_info *info);
298c6ed7d6eSMoshe Shemesh
299623cd13bSJakub Kicinski /* Rates */
300af2f8c1fSMoshe Shemesh int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
301af2f8c1fSMoshe Shemesh struct netlink_ext_ack *extack);
30241a1d4d1SJiri Pirko
3039edbe6f3SJiri Pirko /* Linecards */
304d0b7e990SJiri Pirko unsigned int devlink_linecard_index(struct devlink_linecard *linecard);
305