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