Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
   4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
   5 */
   6
   7#include "devl_internal.h"
   8
   9struct devlink_region {
  10	struct devlink *devlink;
  11	struct devlink_port *port;
  12	struct list_head list;
  13	union {
  14		const struct devlink_region_ops *ops;
  15		const struct devlink_port_region_ops *port_ops;
  16	};
  17	struct mutex snapshot_lock; /* protects snapshot_list,
  18				     * max_snapshots and cur_snapshots
  19				     * consistency.
  20				     */
  21	struct list_head snapshot_list;
  22	u32 max_snapshots;
  23	u32 cur_snapshots;
  24	u64 size;
  25};
  26
  27struct devlink_snapshot {
  28	struct list_head list;
  29	struct devlink_region *region;
  30	u8 *data;
  31	u32 id;
  32};
  33
  34static struct devlink_region *
  35devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
  36{
  37	struct devlink_region *region;
  38
  39	list_for_each_entry(region, &devlink->region_list, list)
  40		if (!strcmp(region->ops->name, region_name))
  41			return region;
  42
  43	return NULL;
  44}
  45
  46static struct devlink_region *
  47devlink_port_region_get_by_name(struct devlink_port *port,
  48				const char *region_name)
  49{
  50	struct devlink_region *region;
  51
  52	list_for_each_entry(region, &port->region_list, list)
  53		if (!strcmp(region->ops->name, region_name))
  54			return region;
  55
  56	return NULL;
  57}
  58
  59static struct devlink_snapshot *
  60devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
  61{
  62	struct devlink_snapshot *snapshot;
  63
  64	list_for_each_entry(snapshot, &region->snapshot_list, list)
  65		if (snapshot->id == id)
  66			return snapshot;
  67
  68	return NULL;
  69}
  70
  71static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
  72					     struct devlink *devlink,
  73					     struct devlink_snapshot *snapshot)
  74{
  75	struct nlattr *snap_attr;
  76	int err;
  77
  78	snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
  79	if (!snap_attr)
  80		return -EINVAL;
  81
  82	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
  83	if (err)
  84		goto nla_put_failure;
  85
  86	nla_nest_end(msg, snap_attr);
  87	return 0;
  88
  89nla_put_failure:
  90	nla_nest_cancel(msg, snap_attr);
  91	return err;
  92}
  93
  94static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
  95					      struct devlink *devlink,
  96					      struct devlink_region *region)
  97{
  98	struct devlink_snapshot *snapshot;
  99	struct nlattr *snapshots_attr;
 100	int err;
 101
 102	snapshots_attr = nla_nest_start_noflag(msg,
 103					       DEVLINK_ATTR_REGION_SNAPSHOTS);
 104	if (!snapshots_attr)
 105		return -EINVAL;
 106
 107	list_for_each_entry(snapshot, &region->snapshot_list, list) {
 108		err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
 109		if (err)
 110			goto nla_put_failure;
 111	}
 112
 113	nla_nest_end(msg, snapshots_attr);
 114	return 0;
 115
 116nla_put_failure:
 117	nla_nest_cancel(msg, snapshots_attr);
 118	return err;
 119}
 120
 121static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
 122				  enum devlink_command cmd, u32 portid,
 123				  u32 seq, int flags,
 124				  struct devlink_region *region)
 125{
 126	void *hdr;
 127	int err;
 128
 129	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
 130	if (!hdr)
 131		return -EMSGSIZE;
 132
 133	err = devlink_nl_put_handle(msg, devlink);
 134	if (err)
 135		goto nla_put_failure;
 136
 137	if (region->port) {
 138		err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
 139				  region->port->index);
 140		if (err)
 141			goto nla_put_failure;
 142	}
 143
 144	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
 145	if (err)
 146		goto nla_put_failure;
 147
 148	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
 149				region->size,
 150				DEVLINK_ATTR_PAD);
 151	if (err)
 152		goto nla_put_failure;
 153
 154	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
 155			  region->max_snapshots);
 156	if (err)
 157		goto nla_put_failure;
 158
 159	err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
 160	if (err)
 161		goto nla_put_failure;
 162
 163	genlmsg_end(msg, hdr);
 164	return 0;
 165
 166nla_put_failure:
 167	genlmsg_cancel(msg, hdr);
 168	return err;
 169}
 170
 171static struct sk_buff *
 172devlink_nl_region_notify_build(struct devlink_region *region,
 173			       struct devlink_snapshot *snapshot,
 174			       enum devlink_command cmd, u32 portid, u32 seq)
 175{
 176	struct devlink *devlink = region->devlink;
 177	struct sk_buff *msg;
 178	void *hdr;
 179	int err;
 180
 181	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 182	if (!msg)
 183		return ERR_PTR(-ENOMEM);
 184
 185	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
 186	if (!hdr) {
 187		err = -EMSGSIZE;
 188		goto out_free_msg;
 189	}
 190
 191	err = devlink_nl_put_handle(msg, devlink);
 192	if (err)
 193		goto out_cancel_msg;
 194
 195	if (region->port) {
 196		err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
 197				  region->port->index);
 198		if (err)
 199			goto out_cancel_msg;
 200	}
 201
 202	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
 203			     region->ops->name);
 204	if (err)
 205		goto out_cancel_msg;
 206
 207	if (snapshot) {
 208		err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
 209				  snapshot->id);
 210		if (err)
 211			goto out_cancel_msg;
 212	} else {
 213		err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
 214					region->size, DEVLINK_ATTR_PAD);
 215		if (err)
 216			goto out_cancel_msg;
 217	}
 218	genlmsg_end(msg, hdr);
 219
 220	return msg;
 221
 222out_cancel_msg:
 223	genlmsg_cancel(msg, hdr);
 224out_free_msg:
 225	nlmsg_free(msg);
 226	return ERR_PTR(err);
 227}
 228
 229static void devlink_nl_region_notify(struct devlink_region *region,
 230				     struct devlink_snapshot *snapshot,
 231				     enum devlink_command cmd)
 232{
 233	struct devlink *devlink = region->devlink;
 234	struct sk_buff *msg;
 235
 236	WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
 237
 238	if (!__devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
 239		return;
 240
 241	msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
 242	if (IS_ERR(msg))
 243		return;
 244
 245	devlink_nl_notify_send(devlink, msg);
 246}
 247
 248void devlink_regions_notify_register(struct devlink *devlink)
 249{
 250	struct devlink_region *region;
 251
 252	list_for_each_entry(region, &devlink->region_list, list)
 253		devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
 254}
 255
 256void devlink_regions_notify_unregister(struct devlink *devlink)
 257{
 258	struct devlink_region *region;
 259
 260	list_for_each_entry_reverse(region, &devlink->region_list, list)
 261		devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
 262}
 263
 264/**
 265 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
 266 *	@devlink: devlink instance
 267 *	@id: the snapshot id
 268 *
 269 *	Track when a new snapshot begins using an id. Load the count for the
 270 *	given id from the snapshot xarray, increment it, and store it back.
 271 *
 272 *	Called when a new snapshot is created with the given id.
 273 *
 274 *	The id *must* have been previously allocated by
 275 *	devlink_region_snapshot_id_get().
 276 *
 277 *	Returns 0 on success, or an error on failure.
 278 */
 279static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
 280{
 281	unsigned long count;
 282	void *p;
 283	int err;
 284
 285	xa_lock(&devlink->snapshot_ids);
 286	p = xa_load(&devlink->snapshot_ids, id);
 287	if (WARN_ON(!p)) {
 288		err = -EINVAL;
 289		goto unlock;
 290	}
 291
 292	if (WARN_ON(!xa_is_value(p))) {
 293		err = -EINVAL;
 294		goto unlock;
 295	}
 296
 297	count = xa_to_value(p);
 298	count++;
 299
 300	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
 301				GFP_ATOMIC));
 302unlock:
 303	xa_unlock(&devlink->snapshot_ids);
 304	return err;
 305}
 306
 307/**
 308 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
 309 *	@devlink: devlink instance
 310 *	@id: the snapshot id
 311 *
 312 *	Track when a snapshot is deleted and stops using an id. Load the count
 313 *	for the given id from the snapshot xarray, decrement it, and store it
 314 *	back.
 315 *
 316 *	If the count reaches zero, erase this id from the xarray, freeing it
 317 *	up for future re-use by devlink_region_snapshot_id_get().
 318 *
 319 *	Called when a snapshot using the given id is deleted, and when the
 320 *	initial allocator of the id is finished using it.
 321 */
 322static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
 323{
 324	unsigned long count;
 325	void *p;
 326
 327	xa_lock(&devlink->snapshot_ids);
 328	p = xa_load(&devlink->snapshot_ids, id);
 329	if (WARN_ON(!p))
 330		goto unlock;
 331
 332	if (WARN_ON(!xa_is_value(p)))
 333		goto unlock;
 334
 335	count = xa_to_value(p);
 336
 337	if (count > 1) {
 338		count--;
 339		__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
 340			   GFP_ATOMIC);
 341	} else {
 342		/* If this was the last user, we can erase this id */
 343		__xa_erase(&devlink->snapshot_ids, id);
 344	}
 345unlock:
 346	xa_unlock(&devlink->snapshot_ids);
 347}
 348
 349/**
 350 *	__devlink_snapshot_id_insert - Insert a specific snapshot ID
 351 *	@devlink: devlink instance
 352 *	@id: the snapshot id
 353 *
 354 *	Mark the given snapshot id as used by inserting a zero value into the
 355 *	snapshot xarray.
 356 *
 357 *	This must be called while holding the devlink instance lock. Unlike
 358 *	devlink_snapshot_id_get, the initial reference count is zero, not one.
 359 *	It is expected that the id will immediately be used before
 360 *	releasing the devlink instance lock.
 361 *
 362 *	Returns zero on success, or an error code if the snapshot id could not
 363 *	be inserted.
 364 */
 365static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
 366{
 367	int err;
 368
 369	xa_lock(&devlink->snapshot_ids);
 370	if (xa_load(&devlink->snapshot_ids, id)) {
 371		xa_unlock(&devlink->snapshot_ids);
 372		return -EEXIST;
 373	}
 374	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
 375				GFP_ATOMIC));
 376	xa_unlock(&devlink->snapshot_ids);
 377	return err;
 378}
 379
 380/**
 381 *	__devlink_region_snapshot_id_get - get snapshot ID
 382 *	@devlink: devlink instance
 383 *	@id: storage to return snapshot id
 384 *
 385 *	Allocates a new snapshot id. Returns zero on success, or a negative
 386 *	error on failure. Must be called while holding the devlink instance
 387 *	lock.
 388 *
 389 *	Snapshot IDs are tracked using an xarray which stores the number of
 390 *	users of the snapshot id.
 391 *
 392 *	Note that the caller of this function counts as a 'user', in order to
 393 *	avoid race conditions. The caller must release its hold on the
 394 *	snapshot by using devlink_region_snapshot_id_put.
 395 */
 396static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
 397{
 398	return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
 399			xa_limit_32b, GFP_KERNEL);
 400}
 401
 402/**
 403 *	__devlink_region_snapshot_create - create a new snapshot
 404 *	This will add a new snapshot of a region. The snapshot
 405 *	will be stored on the region struct and can be accessed
 406 *	from devlink. This is useful for future analyses of snapshots.
 407 *	Multiple snapshots can be created on a region.
 408 *	The @snapshot_id should be obtained using the getter function.
 409 *
 410 *	Must be called only while holding the region snapshot lock.
 411 *
 412 *	@region: devlink region of the snapshot
 413 *	@data: snapshot data
 414 *	@snapshot_id: snapshot id to be created
 415 */
 416static int
 417__devlink_region_snapshot_create(struct devlink_region *region,
 418				 u8 *data, u32 snapshot_id)
 419{
 420	struct devlink *devlink = region->devlink;
 421	struct devlink_snapshot *snapshot;
 422	int err;
 423
 424	lockdep_assert_held(&region->snapshot_lock);
 425
 426	/* check if region can hold one more snapshot */
 427	if (region->cur_snapshots == region->max_snapshots)
 428		return -ENOSPC;
 429
 430	if (devlink_region_snapshot_get_by_id(region, snapshot_id))
 431		return -EEXIST;
 432
 433	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
 434	if (!snapshot)
 435		return -ENOMEM;
 436
 437	err = __devlink_snapshot_id_increment(devlink, snapshot_id);
 438	if (err)
 439		goto err_snapshot_id_increment;
 440
 441	snapshot->id = snapshot_id;
 442	snapshot->region = region;
 443	snapshot->data = data;
 444
 445	list_add_tail(&snapshot->list, &region->snapshot_list);
 446
 447	region->cur_snapshots++;
 448
 449	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
 450	return 0;
 451
 452err_snapshot_id_increment:
 453	kfree(snapshot);
 454	return err;
 455}
 456
 457static void devlink_region_snapshot_del(struct devlink_region *region,
 458					struct devlink_snapshot *snapshot)
 459{
 460	struct devlink *devlink = region->devlink;
 461
 462	lockdep_assert_held(&region->snapshot_lock);
 463
 464	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
 465	region->cur_snapshots--;
 466	list_del(&snapshot->list);
 467	region->ops->destructor(snapshot->data);
 468	__devlink_snapshot_id_decrement(devlink, snapshot->id);
 469	kfree(snapshot);
 470}
 471
 472int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info)
 473{
 474	struct devlink *devlink = info->user_ptr[0];
 475	struct devlink_port *port = NULL;
 476	struct devlink_region *region;
 477	const char *region_name;
 478	struct sk_buff *msg;
 479	unsigned int index;
 480	int err;
 481
 482	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
 483		return -EINVAL;
 484
 485	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
 486		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 487
 488		port = devlink_port_get_by_index(devlink, index);
 489		if (!port)
 490			return -ENODEV;
 491	}
 492
 493	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
 494	if (port)
 495		region = devlink_port_region_get_by_name(port, region_name);
 496	else
 497		region = devlink_region_get_by_name(devlink, region_name);
 498
 499	if (!region)
 500		return -EINVAL;
 501
 502	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 503	if (!msg)
 504		return -ENOMEM;
 505
 506	err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
 507				     info->snd_portid, info->snd_seq, 0,
 508				     region);
 509	if (err) {
 510		nlmsg_free(msg);
 511		return err;
 512	}
 513
 514	return genlmsg_reply(msg, info);
 515}
 516
 517static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
 518						 struct netlink_callback *cb,
 519						 struct devlink_port *port,
 520						 int *idx, int start, int flags)
 521{
 522	struct devlink_region *region;
 523	int err = 0;
 524
 525	list_for_each_entry(region, &port->region_list, list) {
 526		if (*idx < start) {
 527			(*idx)++;
 528			continue;
 529		}
 530		err = devlink_nl_region_fill(msg, port->devlink,
 531					     DEVLINK_CMD_REGION_GET,
 532					     NETLINK_CB(cb->skb).portid,
 533					     cb->nlh->nlmsg_seq,
 534					     flags, region);
 535		if (err)
 536			goto out;
 537		(*idx)++;
 538	}
 539
 540out:
 541	return err;
 542}
 543
 544static int devlink_nl_region_get_dump_one(struct sk_buff *msg,
 545					  struct devlink *devlink,
 546					  struct netlink_callback *cb,
 547					  int flags)
 548{
 549	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
 550	struct devlink_region *region;
 551	struct devlink_port *port;
 552	unsigned long port_index;
 553	int idx = 0;
 554	int err;
 555
 556	list_for_each_entry(region, &devlink->region_list, list) {
 557		if (idx < state->idx) {
 558			idx++;
 559			continue;
 560		}
 561		err = devlink_nl_region_fill(msg, devlink,
 562					     DEVLINK_CMD_REGION_GET,
 563					     NETLINK_CB(cb->skb).portid,
 564					     cb->nlh->nlmsg_seq, flags,
 565					     region);
 566		if (err) {
 567			state->idx = idx;
 568			return err;
 569		}
 570		idx++;
 571	}
 572
 573	xa_for_each(&devlink->ports, port_index, port) {
 574		err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx,
 575							    state->idx, flags);
 576		if (err) {
 577			state->idx = idx;
 578			return err;
 579		}
 580	}
 581
 582	return 0;
 583}
 584
 585int devlink_nl_region_get_dumpit(struct sk_buff *skb,
 586				 struct netlink_callback *cb)
 587{
 588	return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one);
 589}
 590
 591int devlink_nl_region_del_doit(struct sk_buff *skb, struct genl_info *info)
 592{
 593	struct devlink *devlink = info->user_ptr[0];
 594	struct devlink_snapshot *snapshot;
 595	struct devlink_port *port = NULL;
 596	struct devlink_region *region;
 597	const char *region_name;
 598	unsigned int index;
 599	u32 snapshot_id;
 600
 601	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
 602	    GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
 603		return -EINVAL;
 604
 605	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
 606	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
 607
 608	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
 609		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 610
 611		port = devlink_port_get_by_index(devlink, index);
 612		if (!port)
 613			return -ENODEV;
 614	}
 615
 616	if (port)
 617		region = devlink_port_region_get_by_name(port, region_name);
 618	else
 619		region = devlink_region_get_by_name(devlink, region_name);
 620
 621	if (!region)
 622		return -EINVAL;
 623
 624	mutex_lock(&region->snapshot_lock);
 625	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
 626	if (!snapshot) {
 627		mutex_unlock(&region->snapshot_lock);
 628		return -EINVAL;
 629	}
 630
 631	devlink_region_snapshot_del(region, snapshot);
 632	mutex_unlock(&region->snapshot_lock);
 633	return 0;
 634}
 635
 636int devlink_nl_region_new_doit(struct sk_buff *skb, struct genl_info *info)
 637{
 638	struct devlink *devlink = info->user_ptr[0];
 639	struct devlink_snapshot *snapshot;
 640	struct devlink_port *port = NULL;
 641	struct nlattr *snapshot_id_attr;
 642	struct devlink_region *region;
 643	const char *region_name;
 644	unsigned int index;
 645	u32 snapshot_id;
 646	u8 *data;
 647	int err;
 648
 649	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
 650		NL_SET_ERR_MSG(info->extack, "No region name provided");
 651		return -EINVAL;
 652	}
 653
 654	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
 655
 656	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
 657		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 658
 659		port = devlink_port_get_by_index(devlink, index);
 660		if (!port)
 661			return -ENODEV;
 662	}
 663
 664	if (port)
 665		region = devlink_port_region_get_by_name(port, region_name);
 666	else
 667		region = devlink_region_get_by_name(devlink, region_name);
 668
 669	if (!region) {
 670		NL_SET_ERR_MSG(info->extack, "The requested region does not exist");
 671		return -EINVAL;
 672	}
 673
 674	if (!region->ops->snapshot) {
 675		NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot");
 676		return -EOPNOTSUPP;
 677	}
 678
 679	mutex_lock(&region->snapshot_lock);
 680
 681	if (region->cur_snapshots == region->max_snapshots) {
 682		NL_SET_ERR_MSG(info->extack, "The region has reached the maximum number of stored snapshots");
 683		err = -ENOSPC;
 684		goto unlock;
 685	}
 686
 687	snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
 688	if (snapshot_id_attr) {
 689		snapshot_id = nla_get_u32(snapshot_id_attr);
 690
 691		if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
 692			NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use");
 693			err = -EEXIST;
 694			goto unlock;
 695		}
 696
 697		err = __devlink_snapshot_id_insert(devlink, snapshot_id);
 698		if (err)
 699			goto unlock;
 700	} else {
 701		err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
 702		if (err) {
 703			NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id");
 704			goto unlock;
 705		}
 706	}
 707
 708	if (port)
 709		err = region->port_ops->snapshot(port, region->port_ops,
 710						 info->extack, &data);
 711	else
 712		err = region->ops->snapshot(devlink, region->ops,
 713					    info->extack, &data);
 714	if (err)
 715		goto err_snapshot_capture;
 716
 717	err = __devlink_region_snapshot_create(region, data, snapshot_id);
 718	if (err)
 719		goto err_snapshot_create;
 720
 721	if (!snapshot_id_attr) {
 722		struct sk_buff *msg;
 723
 724		snapshot = devlink_region_snapshot_get_by_id(region,
 725							     snapshot_id);
 726		if (WARN_ON(!snapshot)) {
 727			err = -EINVAL;
 728			goto unlock;
 729		}
 730
 731		msg = devlink_nl_region_notify_build(region, snapshot,
 732						     DEVLINK_CMD_REGION_NEW,
 733						     info->snd_portid,
 734						     info->snd_seq);
 735		err = PTR_ERR_OR_ZERO(msg);
 736		if (err)
 737			goto err_notify;
 738
 739		err = genlmsg_reply(msg, info);
 740		if (err)
 741			goto err_notify;
 742	}
 743
 744	mutex_unlock(&region->snapshot_lock);
 745	return 0;
 746
 747err_snapshot_create:
 748	region->ops->destructor(data);
 749err_snapshot_capture:
 750	__devlink_snapshot_id_decrement(devlink, snapshot_id);
 751	mutex_unlock(&region->snapshot_lock);
 752	return err;
 753
 754err_notify:
 755	devlink_region_snapshot_del(region, snapshot);
 756unlock:
 757	mutex_unlock(&region->snapshot_lock);
 758	return err;
 759}
 760
 761static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
 762						 u8 *chunk, u32 chunk_size,
 763						 u64 addr)
 764{
 765	struct nlattr *chunk_attr;
 766	int err;
 767
 768	chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
 769	if (!chunk_attr)
 770		return -EINVAL;
 771
 772	err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
 773	if (err)
 774		goto nla_put_failure;
 775
 776	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
 777				DEVLINK_ATTR_PAD);
 778	if (err)
 779		goto nla_put_failure;
 780
 781	nla_nest_end(msg, chunk_attr);
 782	return 0;
 783
 784nla_put_failure:
 785	nla_nest_cancel(msg, chunk_attr);
 786	return err;
 787}
 788
 789#define DEVLINK_REGION_READ_CHUNK_SIZE 256
 790
 791typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
 792				 u64 curr_offset,
 793				 struct netlink_ext_ack *extack);
 794
 795static int
 796devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb,
 797			    void *cb_priv, u64 start_offset, u64 end_offset,
 798			    u64 *new_offset, struct netlink_ext_ack *extack)
 799{
 800	u64 curr_offset = start_offset;
 801	int err = 0;
 802	u8 *data;
 803
 804	/* Allocate and re-use a single buffer */
 805	data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL);
 806	if (!data)
 807		return -ENOMEM;
 808
 809	*new_offset = start_offset;
 810
 811	while (curr_offset < end_offset) {
 812		u32 data_size;
 813
 814		data_size = min_t(u32, end_offset - curr_offset,
 815				  DEVLINK_REGION_READ_CHUNK_SIZE);
 816
 817		err = cb(cb_priv, data, data_size, curr_offset, extack);
 818		if (err)
 819			break;
 820
 821		err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset);
 822		if (err)
 823			break;
 824
 825		curr_offset += data_size;
 826	}
 827	*new_offset = curr_offset;
 828
 829	kfree(data);
 830
 831	return err;
 832}
 833
 834static int
 835devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
 836			     u64 curr_offset,
 837			     struct netlink_ext_ack __always_unused *extack)
 838{
 839	struct devlink_snapshot *snapshot = cb_priv;
 840
 841	memcpy(chunk, &snapshot->data[curr_offset], chunk_size);
 842
 843	return 0;
 844}
 845
 846static int
 847devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
 848				u64 curr_offset, struct netlink_ext_ack *extack)
 849{
 850	struct devlink_region *region = cb_priv;
 851
 852	return region->port_ops->read(region->port, region->port_ops, extack,
 853				      curr_offset, chunk_size, chunk);
 854}
 855
 856static int
 857devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
 858			   u64 curr_offset, struct netlink_ext_ack *extack)
 859{
 860	struct devlink_region *region = cb_priv;
 861
 862	return region->ops->read(region->devlink, region->ops, extack,
 863				 curr_offset, chunk_size, chunk);
 864}
 865
 866int devlink_nl_region_read_dumpit(struct sk_buff *skb,
 867				  struct netlink_callback *cb)
 868{
 869	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
 870	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
 871	struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
 872	u64 ret_offset, start_offset, end_offset = U64_MAX;
 873	struct nlattr **attrs = info->info.attrs;
 874	struct devlink_port *port = NULL;
 875	devlink_chunk_fill_t *region_cb;
 876	struct devlink_region *region;
 877	const char *region_name;
 878	struct devlink *devlink;
 879	unsigned int index;
 880	void *region_cb_priv;
 881	void *hdr;
 882	int err;
 883
 884	start_offset = state->start_offset;
 885
 886	devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs,
 887					      false);
 888	if (IS_ERR(devlink))
 889		return PTR_ERR(devlink);
 890
 891	if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
 892		NL_SET_ERR_MSG(cb->extack, "No region name provided");
 893		err = -EINVAL;
 894		goto out_unlock;
 895	}
 896
 897	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
 898		index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
 899
 900		port = devlink_port_get_by_index(devlink, index);
 901		if (!port) {
 902			err = -ENODEV;
 903			goto out_unlock;
 904		}
 905	}
 906
 907	region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
 908	region_name = nla_data(region_attr);
 909
 910	if (port)
 911		region = devlink_port_region_get_by_name(port, region_name);
 912	else
 913		region = devlink_region_get_by_name(devlink, region_name);
 914
 915	if (!region) {
 916		NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
 917		err = -EINVAL;
 918		goto out_unlock;
 919	}
 920
 921	snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
 922	if (!snapshot_attr) {
 923		if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
 924			NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
 925			err = -EINVAL;
 926			goto out_unlock;
 927		}
 928
 929		if (!region->ops->read) {
 930			NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
 931			err = -EOPNOTSUPP;
 932			goto out_unlock;
 933		}
 934
 935		if (port)
 936			region_cb = &devlink_region_port_direct_fill;
 937		else
 938			region_cb = &devlink_region_direct_fill;
 939		region_cb_priv = region;
 940	} else {
 941		struct devlink_snapshot *snapshot;
 942		u32 snapshot_id;
 943
 944		if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
 945			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
 946			err = -EINVAL;
 947			goto out_unlock;
 948		}
 949
 950		snapshot_id = nla_get_u32(snapshot_attr);
 951		snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
 952		if (!snapshot) {
 953			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
 954			err = -EINVAL;
 955			goto out_unlock;
 956		}
 957		region_cb = &devlink_region_snapshot_fill;
 958		region_cb_priv = snapshot;
 959	}
 960
 961	if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
 962	    attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
 963		if (!start_offset)
 964			start_offset =
 965				nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
 966
 967		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
 968		end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
 969	}
 970
 971	if (end_offset > region->size)
 972		end_offset = region->size;
 973
 974	/* return 0 if there is no further data to read */
 975	if (start_offset == end_offset) {
 976		err = 0;
 977		goto out_unlock;
 978	}
 979
 980	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
 981			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
 982			  DEVLINK_CMD_REGION_READ);
 983	if (!hdr) {
 984		err = -EMSGSIZE;
 985		goto out_unlock;
 986	}
 987
 988	err = devlink_nl_put_handle(skb, devlink);
 989	if (err)
 990		goto nla_put_failure;
 991
 992	if (region->port) {
 993		err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
 994				  region->port->index);
 995		if (err)
 996			goto nla_put_failure;
 997	}
 998
 999	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
1000	if (err)
1001		goto nla_put_failure;
1002
1003	chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
1004	if (!chunks_attr) {
1005		err = -EMSGSIZE;
1006		goto nla_put_failure;
1007	}
1008
1009	err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
1010					  start_offset, end_offset, &ret_offset,
1011					  cb->extack);
1012
1013	if (err && err != -EMSGSIZE)
1014		goto nla_put_failure;
1015
1016	/* Check if there was any progress done to prevent infinite loop */
1017	if (ret_offset == start_offset) {
1018		err = -EINVAL;
1019		goto nla_put_failure;
1020	}
1021
1022	state->start_offset = ret_offset;
1023
1024	nla_nest_end(skb, chunks_attr);
1025	genlmsg_end(skb, hdr);
1026	devl_unlock(devlink);
1027	devlink_put(devlink);
1028	return skb->len;
1029
1030nla_put_failure:
1031	genlmsg_cancel(skb, hdr);
1032out_unlock:
1033	devl_unlock(devlink);
1034	devlink_put(devlink);
1035	return err;
1036}
1037
1038/**
1039 * devl_region_create - create a new address region
1040 *
1041 * @devlink: devlink
1042 * @ops: region operations and name
1043 * @region_max_snapshots: Maximum supported number of snapshots for region
1044 * @region_size: size of region
1045 */
1046struct devlink_region *devl_region_create(struct devlink *devlink,
1047					  const struct devlink_region_ops *ops,
1048					  u32 region_max_snapshots,
1049					  u64 region_size)
1050{
1051	struct devlink_region *region;
1052
1053	devl_assert_locked(devlink);
1054
1055	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1056		return ERR_PTR(-EINVAL);
1057
1058	if (devlink_region_get_by_name(devlink, ops->name))
1059		return ERR_PTR(-EEXIST);
1060
1061	region = kzalloc(sizeof(*region), GFP_KERNEL);
1062	if (!region)
1063		return ERR_PTR(-ENOMEM);
1064
1065	region->devlink = devlink;
1066	region->max_snapshots = region_max_snapshots;
1067	region->ops = ops;
1068	region->size = region_size;
1069	INIT_LIST_HEAD(&region->snapshot_list);
1070	mutex_init(&region->snapshot_lock);
1071	list_add_tail(&region->list, &devlink->region_list);
1072	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1073
1074	return region;
1075}
1076EXPORT_SYMBOL_GPL(devl_region_create);
1077
1078/**
1079 *	devlink_region_create - create a new address region
1080 *
1081 *	@devlink: devlink
1082 *	@ops: region operations and name
1083 *	@region_max_snapshots: Maximum supported number of snapshots for region
1084 *	@region_size: size of region
1085 *
1086 *	Context: Takes and release devlink->lock <mutex>.
1087 */
1088struct devlink_region *
1089devlink_region_create(struct devlink *devlink,
1090		      const struct devlink_region_ops *ops,
1091		      u32 region_max_snapshots, u64 region_size)
1092{
1093	struct devlink_region *region;
1094
1095	devl_lock(devlink);
1096	region = devl_region_create(devlink, ops, region_max_snapshots,
1097				    region_size);
1098	devl_unlock(devlink);
1099	return region;
1100}
1101EXPORT_SYMBOL_GPL(devlink_region_create);
1102
1103/**
1104 *	devlink_port_region_create - create a new address region for a port
1105 *
1106 *	@port: devlink port
1107 *	@ops: region operations and name
1108 *	@region_max_snapshots: Maximum supported number of snapshots for region
1109 *	@region_size: size of region
1110 *
1111 *	Context: Takes and release devlink->lock <mutex>.
1112 */
1113struct devlink_region *
1114devlink_port_region_create(struct devlink_port *port,
1115			   const struct devlink_port_region_ops *ops,
1116			   u32 region_max_snapshots, u64 region_size)
1117{
1118	struct devlink *devlink = port->devlink;
1119	struct devlink_region *region;
1120	int err = 0;
1121
1122	ASSERT_DEVLINK_PORT_INITIALIZED(port);
1123
1124	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1125		return ERR_PTR(-EINVAL);
1126
1127	devl_lock(devlink);
1128
1129	if (devlink_port_region_get_by_name(port, ops->name)) {
1130		err = -EEXIST;
1131		goto unlock;
1132	}
1133
1134	region = kzalloc(sizeof(*region), GFP_KERNEL);
1135	if (!region) {
1136		err = -ENOMEM;
1137		goto unlock;
1138	}
1139
1140	region->devlink = devlink;
1141	region->port = port;
1142	region->max_snapshots = region_max_snapshots;
1143	region->port_ops = ops;
1144	region->size = region_size;
1145	INIT_LIST_HEAD(&region->snapshot_list);
1146	mutex_init(&region->snapshot_lock);
1147	list_add_tail(&region->list, &port->region_list);
1148	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1149
1150	devl_unlock(devlink);
1151	return region;
1152
1153unlock:
1154	devl_unlock(devlink);
1155	return ERR_PTR(err);
1156}
1157EXPORT_SYMBOL_GPL(devlink_port_region_create);
1158
1159/**
1160 * devl_region_destroy - destroy address region
1161 *
1162 * @region: devlink region to destroy
1163 */
1164void devl_region_destroy(struct devlink_region *region)
1165{
1166	struct devlink *devlink = region->devlink;
1167	struct devlink_snapshot *snapshot, *ts;
1168
1169	devl_assert_locked(devlink);
1170
1171	/* Free all snapshots of region */
1172	mutex_lock(&region->snapshot_lock);
1173	list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
1174		devlink_region_snapshot_del(region, snapshot);
1175	mutex_unlock(&region->snapshot_lock);
1176
1177	list_del(&region->list);
1178	mutex_destroy(&region->snapshot_lock);
1179
1180	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1181	kfree(region);
1182}
1183EXPORT_SYMBOL_GPL(devl_region_destroy);
1184
1185/**
1186 *	devlink_region_destroy - destroy address region
1187 *
1188 *	@region: devlink region to destroy
1189 *
1190 *	Context: Takes and release devlink->lock <mutex>.
1191 */
1192void devlink_region_destroy(struct devlink_region *region)
1193{
1194	struct devlink *devlink = region->devlink;
1195
1196	devl_lock(devlink);
1197	devl_region_destroy(region);
1198	devl_unlock(devlink);
1199}
1200EXPORT_SYMBOL_GPL(devlink_region_destroy);
1201
1202/**
1203 *	devlink_region_snapshot_id_get - get snapshot ID
1204 *
1205 *	This callback should be called when adding a new snapshot,
1206 *	Driver should use the same id for multiple snapshots taken
1207 *	on multiple regions at the same time/by the same trigger.
1208 *
1209 *	The caller of this function must use devlink_region_snapshot_id_put
1210 *	when finished creating regions using this id.
1211 *
1212 *	Returns zero on success, or a negative error code on failure.
1213 *
1214 *	@devlink: devlink
1215 *	@id: storage to return id
1216 */
1217int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1218{
1219	return __devlink_region_snapshot_id_get(devlink, id);
1220}
1221EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1222
1223/**
1224 *	devlink_region_snapshot_id_put - put snapshot ID reference
1225 *
1226 *	This should be called by a driver after finishing creating snapshots
1227 *	with an id. Doing so ensures that the ID can later be released in the
1228 *	event that all snapshots using it have been destroyed.
1229 *
1230 *	@devlink: devlink
1231 *	@id: id to release reference on
1232 */
1233void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1234{
1235	__devlink_snapshot_id_decrement(devlink, id);
1236}
1237EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1238
1239/**
1240 *	devlink_region_snapshot_create - create a new snapshot
1241 *	This will add a new snapshot of a region. The snapshot
1242 *	will be stored on the region struct and can be accessed
1243 *	from devlink. This is useful for future analyses of snapshots.
1244 *	Multiple snapshots can be created on a region.
1245 *	The @snapshot_id should be obtained using the getter function.
1246 *
1247 *	@region: devlink region of the snapshot
1248 *	@data: snapshot data
1249 *	@snapshot_id: snapshot id to be created
1250 */
1251int devlink_region_snapshot_create(struct devlink_region *region,
1252				   u8 *data, u32 snapshot_id)
1253{
1254	int err;
1255
1256	mutex_lock(&region->snapshot_lock);
1257	err = __devlink_region_snapshot_create(region, data, snapshot_id);
1258	mutex_unlock(&region->snapshot_lock);
1259	return err;
1260}
1261EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);