Linux Audio

Check our new training course

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