xref: /openbmc/linux/net/devlink/devl_internal.h (revision 71179ac5)
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 <jiri@mellanox.com>
4687125b5SJakub Kicinski  */
5687125b5SJakub Kicinski 
6eec1e5eaSJiri Pirko #include <linux/etherdevice.h>
7687125b5SJakub Kicinski #include <linux/mutex.h>
8687125b5SJakub Kicinski #include <linux/netdevice.h>
9687125b5SJakub Kicinski #include <linux/notifier.h>
10687125b5SJakub Kicinski #include <linux/types.h>
1193e71edfSJakub Kicinski #include <linux/workqueue.h>
12687125b5SJakub Kicinski #include <linux/xarray.h>
13687125b5SJakub Kicinski #include <net/devlink.h>
14687125b5SJakub Kicinski #include <net/net_namespace.h>
15eec1e5eaSJiri Pirko #include <net/rtnetlink.h>
16eec1e5eaSJiri Pirko #include <rdma/ib_verbs.h>
17687125b5SJakub Kicinski 
18b2551b15SJiri Pirko #include "netlink_gen.h"
19b2551b15SJiri Pirko 
20687125b5SJakub Kicinski #define DEVLINK_REGISTERED XA_MARK_1
21687125b5SJakub Kicinski 
22687125b5SJakub Kicinski #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
23687125b5SJakub Kicinski 	(__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
24687125b5SJakub Kicinski 
25687125b5SJakub Kicinski struct devlink_dev_stats {
26687125b5SJakub Kicinski 	u32 reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
27687125b5SJakub Kicinski 	u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
28687125b5SJakub Kicinski };
29687125b5SJakub Kicinski 
30687125b5SJakub Kicinski struct devlink {
31687125b5SJakub Kicinski 	u32 index;
32687125b5SJakub Kicinski 	struct xarray ports;
33687125b5SJakub Kicinski 	struct list_head rate_list;
34687125b5SJakub Kicinski 	struct list_head sb_list;
35687125b5SJakub Kicinski 	struct list_head dpipe_table_list;
36687125b5SJakub Kicinski 	struct list_head resource_list;
37a72e17b4SJiri Pirko 	struct xarray params;
38687125b5SJakub Kicinski 	struct list_head region_list;
39687125b5SJakub Kicinski 	struct list_head reporter_list;
40687125b5SJakub Kicinski 	struct devlink_dpipe_headers *dpipe_headers;
41687125b5SJakub Kicinski 	struct list_head trap_list;
42687125b5SJakub Kicinski 	struct list_head trap_group_list;
43687125b5SJakub Kicinski 	struct list_head trap_policer_list;
44687125b5SJakub Kicinski 	struct list_head linecard_list;
45687125b5SJakub Kicinski 	const struct devlink_ops *ops;
46687125b5SJakub Kicinski 	struct xarray snapshot_ids;
47687125b5SJakub Kicinski 	struct devlink_dev_stats stats;
48687125b5SJakub Kicinski 	struct device *dev;
49687125b5SJakub Kicinski 	possible_net_t _net;
50687125b5SJakub Kicinski 	/* Serializes access to devlink instance specific objects such as
51687125b5SJakub Kicinski 	 * port, sb, dpipe, resource, params, region, traps and more.
52687125b5SJakub Kicinski 	 */
53687125b5SJakub Kicinski 	struct mutex lock;
54687125b5SJakub Kicinski 	struct lock_class_key lock_key;
55687125b5SJakub Kicinski 	u8 reload_failed:1;
56687125b5SJakub Kicinski 	refcount_t refcount;
5793e71edfSJakub Kicinski 	struct rcu_work rwork;
58687125b5SJakub Kicinski 	char priv[] __aligned(NETDEV_ALIGN);
59687125b5SJakub Kicinski };
60687125b5SJakub Kicinski 
61687125b5SJakub Kicinski extern struct xarray devlinks;
62687125b5SJakub Kicinski extern struct genl_family devlink_nl_family;
63687125b5SJakub Kicinski 
64687125b5SJakub Kicinski /* devlink instances are open to the access from the user space after
65687125b5SJakub Kicinski  * devlink_register() call. Such logical barrier allows us to have certain
66687125b5SJakub Kicinski  * expectations related to locking.
67687125b5SJakub Kicinski  *
68687125b5SJakub Kicinski  * Before *_register() - we are in initialization stage and no parallel
69687125b5SJakub Kicinski  * access possible to the devlink instance. All drivers perform that phase
70687125b5SJakub Kicinski  * by implicitly holding device_lock.
71687125b5SJakub Kicinski  *
72687125b5SJakub Kicinski  * After *_register() - users and driver can access devlink instance at
73687125b5SJakub Kicinski  * the same time.
74687125b5SJakub Kicinski  */
75687125b5SJakub Kicinski #define ASSERT_DEVLINK_REGISTERED(d)                                           \
76687125b5SJakub Kicinski 	WARN_ON_ONCE(!xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
77687125b5SJakub Kicinski #define ASSERT_DEVLINK_NOT_REGISTERED(d)                                       \
78687125b5SJakub Kicinski 	WARN_ON_ONCE(xa_get_mark(&devlinks, (d)->index, DEVLINK_REGISTERED))
79687125b5SJakub Kicinski 
80687125b5SJakub Kicinski /* Iterate over devlink pointers which were possible to get reference to.
81687125b5SJakub Kicinski  * devlink_put() needs to be called for each iterated devlink pointer
82687125b5SJakub Kicinski  * in loop body in order to release the reference.
83687125b5SJakub Kicinski  */
84687125b5SJakub Kicinski #define devlinks_xa_for_each_registered_get(net, index, devlink)	\
85d7727819SJakub Kicinski 	for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
86687125b5SJakub Kicinski 
87d7727819SJakub Kicinski struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
88687125b5SJakub Kicinski 
devl_is_registered(struct devlink * devlink)89ed539ba6SJakub Kicinski static inline bool devl_is_registered(struct devlink *devlink)
90ed539ba6SJakub Kicinski {
9163ba54a5SJiri Pirko 	devl_assert_locked(devlink);
92ed539ba6SJakub Kicinski 	return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
93ed539ba6SJakub Kicinski }
94ed539ba6SJakub Kicinski 
95687125b5SJakub Kicinski /* Netlink */
96623cd13bSJakub Kicinski #define DEVLINK_NL_FLAG_NEED_PORT		BIT(0)
97623cd13bSJakub Kicinski #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT	BIT(1)
98623cd13bSJakub Kicinski 
99623cd13bSJakub Kicinski enum devlink_multicast_groups {
100623cd13bSJakub Kicinski 	DEVLINK_MCGRP_CONFIG,
101623cd13bSJakub Kicinski };
102623cd13bSJakub Kicinski 
1033015f822SJakub Kicinski /* state held across netlink dumps */
1043015f822SJakub Kicinski struct devlink_nl_dump_state {
105731d69a6SJakub Kicinski 	unsigned long instance;
1063015f822SJakub Kicinski 	int idx;
1073015f822SJakub Kicinski 	union {
1083015f822SJakub Kicinski 		/* DEVLINK_CMD_REGION_READ */
1093015f822SJakub Kicinski 		struct {
1103015f822SJakub Kicinski 			u64 start_offset;
1113015f822SJakub Kicinski 		};
1123015f822SJakub Kicinski 		/* DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET */
1133015f822SJakub Kicinski 		struct {
1143015f822SJakub Kicinski 			u64 dump_ts;
1153015f822SJakub Kicinski 		};
1163015f822SJakub Kicinski 	};
1173015f822SJakub Kicinski };
1183015f822SJakub Kicinski 
119491a2487SJiri Pirko typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg,
120491a2487SJiri Pirko 				       struct devlink *devlink,
1217d3c6fecSJiri Pirko 				       struct netlink_callback *cb,
1227d3c6fecSJiri Pirko 				       int flags);
123491a2487SJiri Pirko 
124870c7ad4SJakub Kicinski struct devlink *
125870c7ad4SJakub Kicinski devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs);
126623cd13bSJakub Kicinski 
127491a2487SJiri Pirko int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
128491a2487SJiri Pirko 		      devlink_nl_dump_one_func_t *dump_one);
12907f3af66SJakub Kicinski 
1303015f822SJakub Kicinski static inline struct devlink_nl_dump_state *
devlink_dump_state(struct netlink_callback * cb)1313015f822SJakub Kicinski devlink_dump_state(struct netlink_callback *cb)
1323015f822SJakub Kicinski {
133ec8f7d49SJakub Kicinski 	NL_ASSERT_DUMP_CTX_FITS(struct devlink_nl_dump_state);
1343015f822SJakub Kicinski 
1353015f822SJakub Kicinski 	return (struct devlink_nl_dump_state *)cb->ctx;
1363015f822SJakub Kicinski }
1373015f822SJakub Kicinski 
138dbeeca81SMoshe Shemesh static inline int
devlink_nl_put_handle(struct sk_buff * msg,struct devlink * devlink)139dbeeca81SMoshe Shemesh devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
140dbeeca81SMoshe Shemesh {
141dbeeca81SMoshe Shemesh 	if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
142dbeeca81SMoshe Shemesh 		return -EMSGSIZE;
143dbeeca81SMoshe Shemesh 	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
144dbeeca81SMoshe Shemesh 		return -EMSGSIZE;
145dbeeca81SMoshe Shemesh 	return 0;
146dbeeca81SMoshe Shemesh }
147dbeeca81SMoshe Shemesh 
1482475ed15SJiri Pirko int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info);
1492475ed15SJiri Pirko 
150dbeeca81SMoshe Shemesh /* Notify */
151*71179ac5SJiri Pirko void devlink_notify_register(struct devlink *devlink);
152*71179ac5SJiri Pirko void devlink_notify_unregister(struct devlink *devlink);
153eec1e5eaSJiri Pirko void devlink_ports_notify_register(struct devlink *devlink);
154eec1e5eaSJiri Pirko void devlink_ports_notify_unregister(struct devlink *devlink);
155830c41e1SJiri Pirko void devlink_params_notify_register(struct devlink *devlink);
156830c41e1SJiri Pirko void devlink_params_notify_unregister(struct devlink *devlink);
1571aa47ca1SJiri Pirko void devlink_regions_notify_register(struct devlink *devlink);
1581aa47ca1SJiri Pirko void devlink_regions_notify_unregister(struct devlink *devlink);
1594bbdec80SJiri Pirko void devlink_trap_policers_notify_register(struct devlink *devlink);
1604bbdec80SJiri Pirko void devlink_trap_policers_notify_unregister(struct devlink *devlink);
1614bbdec80SJiri Pirko void devlink_trap_groups_notify_register(struct devlink *devlink);
1624bbdec80SJiri Pirko void devlink_trap_groups_notify_unregister(struct devlink *devlink);
1634bbdec80SJiri Pirko void devlink_traps_notify_register(struct devlink *devlink);
1644bbdec80SJiri Pirko void devlink_traps_notify_unregister(struct devlink *devlink);
1657cc7194eSJiri Pirko void devlink_rates_notify_register(struct devlink *devlink);
1667cc7194eSJiri Pirko void devlink_rates_notify_unregister(struct devlink *devlink);
1679edbe6f3SJiri Pirko void devlink_linecards_notify_register(struct devlink *devlink);
1689edbe6f3SJiri Pirko void devlink_linecards_notify_unregister(struct devlink *devlink);
169dbeeca81SMoshe Shemesh 
170687125b5SJakub Kicinski /* Ports */
171eec1e5eaSJiri Pirko #define ASSERT_DEVLINK_PORT_INITIALIZED(devlink_port)				\
172eec1e5eaSJiri Pirko 	WARN_ON_ONCE(!(devlink_port)->initialized)
173eec1e5eaSJiri Pirko 
174eec1e5eaSJiri Pirko struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
175eec1e5eaSJiri Pirko 					       unsigned int port_index);
176687125b5SJakub Kicinski int devlink_port_netdevice_event(struct notifier_block *nb,
177687125b5SJakub Kicinski 				 unsigned long event, void *ptr);
178623cd13bSJakub Kicinski struct devlink_port *
179623cd13bSJakub Kicinski devlink_port_get_from_info(struct devlink *devlink, struct genl_info *info);
180db6b5f3eSMoshe Shemesh struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
181db6b5f3eSMoshe Shemesh 						 struct nlattr **attrs);
182623cd13bSJakub Kicinski 
183687125b5SJakub Kicinski /* Reload */
184687125b5SJakub Kicinski bool devlink_reload_actions_valid(const struct devlink_ops *ops);
185687125b5SJakub Kicinski int devlink_reload(struct devlink *devlink, struct net *dest_net,
186687125b5SJakub Kicinski 		   enum devlink_reload_action action,
187687125b5SJakub Kicinski 		   enum devlink_reload_limit limit,
188687125b5SJakub Kicinski 		   u32 *actions_performed, struct netlink_ext_ack *extack);
189687125b5SJakub Kicinski 
devlink_reload_supported(const struct devlink_ops * ops)190687125b5SJakub Kicinski static inline bool devlink_reload_supported(const struct devlink_ops *ops)
191687125b5SJakub Kicinski {
192687125b5SJakub Kicinski 	return ops->reload_down && ops->reload_up;
193687125b5SJakub Kicinski }
194623cd13bSJakub Kicinski 
195afd888c3SJiri Pirko /* Params */
196afd888c3SJiri Pirko void devlink_params_driverinit_load_new(struct devlink *devlink);
197afd888c3SJiri Pirko 
198c6ed7d6eSMoshe Shemesh /* Resources */
199c6ed7d6eSMoshe Shemesh struct devlink_resource;
200c6ed7d6eSMoshe Shemesh int devlink_resources_validate(struct devlink *devlink,
201c6ed7d6eSMoshe Shemesh 			       struct devlink_resource *resource,
202c6ed7d6eSMoshe Shemesh 			       struct genl_info *info);
203c6ed7d6eSMoshe Shemesh 
204623cd13bSJakub Kicinski /* Rates */
205af2f8c1fSMoshe Shemesh int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
206af2f8c1fSMoshe Shemesh 			     struct netlink_ext_ack *extack);
20741a1d4d1SJiri Pirko 
2089edbe6f3SJiri Pirko /* Linecards */
2099edbe6f3SJiri Pirko struct devlink_linecard {
2109edbe6f3SJiri Pirko 	struct list_head list;
2119edbe6f3SJiri Pirko 	struct devlink *devlink;
2129edbe6f3SJiri Pirko 	unsigned int index;
2139edbe6f3SJiri Pirko 	const struct devlink_linecard_ops *ops;
2149edbe6f3SJiri Pirko 	void *priv;
2159edbe6f3SJiri Pirko 	enum devlink_linecard_state state;
2169edbe6f3SJiri Pirko 	struct mutex state_lock; /* Protects state */
2179edbe6f3SJiri Pirko 	const char *type;
2189edbe6f3SJiri Pirko 	struct devlink_linecard_type *types;
2199edbe6f3SJiri Pirko 	unsigned int types_count;
2209edbe6f3SJiri Pirko 	struct devlink *nested_devlink;
2219edbe6f3SJiri Pirko };
2229edbe6f3SJiri Pirko 
223dbeeca81SMoshe Shemesh /* Devlink nl cmds */
224c6ed7d6eSMoshe Shemesh int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info);
225af2f8c1fSMoshe Shemesh int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, struct genl_info *info);
226af2f8c1fSMoshe Shemesh int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info);
227a13aab66SMoshe Shemesh int devlink_nl_cmd_flash_update(struct sk_buff *skb, struct genl_info *info);
2287c976c7cSMoshe Shemesh int devlink_nl_cmd_selftests_run(struct sk_buff *skb, struct genl_info *info);
229eec1e5eaSJiri Pirko int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, struct genl_info *info);
230eec1e5eaSJiri Pirko int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, struct genl_info *info);
231eec1e5eaSJiri Pirko int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
232eec1e5eaSJiri Pirko 				     struct genl_info *info);
233eec1e5eaSJiri Pirko int devlink_nl_cmd_port_new_doit(struct sk_buff *skb, struct genl_info *info);
234eec1e5eaSJiri Pirko int devlink_nl_cmd_port_del_doit(struct sk_buff *skb, struct genl_info *info);
2352b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info);
2362b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
2372b4d8bb0SJiri Pirko 					 struct genl_info *info);
2382b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
2392b4d8bb0SJiri Pirko 					    struct genl_info *info);
2402b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
2412b4d8bb0SJiri Pirko 					struct genl_info *info);
2422b4d8bb0SJiri Pirko int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
2432b4d8bb0SJiri Pirko 					 struct genl_info *info);
244a9fd44b1SJiri Pirko int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, struct genl_info *info);
245a9fd44b1SJiri Pirko int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
246a9fd44b1SJiri Pirko 				     struct genl_info *info);
247a9fd44b1SJiri Pirko int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
248a9fd44b1SJiri Pirko 				     struct genl_info *info);
249a9fd44b1SJiri Pirko int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
250a9fd44b1SJiri Pirko 					    struct genl_info *info);
251a9f96007SJiri Pirko int devlink_nl_cmd_resource_set(struct sk_buff *skb, struct genl_info *info);
252a9f96007SJiri Pirko int devlink_nl_cmd_resource_dump(struct sk_buff *skb, struct genl_info *info);
253830c41e1SJiri Pirko int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, struct genl_info *info);
254830c41e1SJiri Pirko int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
255830c41e1SJiri Pirko 					 struct netlink_callback *cb);
256830c41e1SJiri Pirko int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
257830c41e1SJiri Pirko 				       struct genl_info *info);
258830c41e1SJiri Pirko int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
259830c41e1SJiri Pirko 				       struct genl_info *info);
2601aa47ca1SJiri Pirko int devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info);
2611aa47ca1SJiri Pirko int devlink_nl_cmd_region_del(struct sk_buff *skb, struct genl_info *info);
2621aa47ca1SJiri Pirko int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
2631aa47ca1SJiri Pirko 				      struct netlink_callback *cb);
264db6b5f3eSMoshe Shemesh int devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
265db6b5f3eSMoshe Shemesh 					    struct genl_info *info);
26655b9b249SMoshe Shemesh int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
26755b9b249SMoshe Shemesh 						struct genl_info *info);
268a929df7fSMoshe Shemesh int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
269a929df7fSMoshe Shemesh 						 struct genl_info *info);
2707004c6c4SMoshe Shemesh int devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
2717004c6c4SMoshe Shemesh 						   struct netlink_callback *cb);
2727004c6c4SMoshe Shemesh int devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
2737004c6c4SMoshe Shemesh 						   struct genl_info *info);
274c9311ee1SMoshe Shemesh int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
275c9311ee1SMoshe Shemesh 					     struct genl_info *info);
2764bbdec80SJiri Pirko int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb, struct genl_info *info);
2774bbdec80SJiri Pirko int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
2784bbdec80SJiri Pirko 				       struct genl_info *info);
2794bbdec80SJiri Pirko int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
2804bbdec80SJiri Pirko 					 struct genl_info *info);
2817cc7194eSJiri Pirko int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb, struct genl_info *info);
2827cc7194eSJiri Pirko int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb, struct genl_info *info);
2837cc7194eSJiri Pirko int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb, struct genl_info *info);
2849edbe6f3SJiri Pirko int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb,
2859edbe6f3SJiri Pirko 				     struct genl_info *info);
286