xref: /linux-6.15/net/devlink/devl_internal.h (revision da3ee3cd)
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