dsa2.c 18.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7 8 9 10 11
/*
 * net/dsa/dsa2.c - Hardware switch handling, binding version 2
 * Copyright (c) 2008-2009 Marvell Semiconductor
 * Copyright (c) 2013 Florian Fainelli <florian@openwrt.org>
 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
 */

#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
12
#include <linux/netdevice.h>
13 14 15 16
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/of.h>
#include <linux/of_net.h>
17
#include <net/devlink.h>
18

19 20
#include "dsa_priv.h"

21
static LIST_HEAD(dsa_tree_list);
22 23
static DEFINE_MUTEX(dsa2_mutex);

24 25 26
static const struct devlink_ops dsa_devlink_ops = {
};

27
static struct dsa_switch_tree *dsa_tree_find(int index)
28 29 30
{
	struct dsa_switch_tree *dst;

31
	list_for_each_entry(dst, &dsa_tree_list, list)
32
		if (dst->index == index)
33
			return dst;
34

35 36 37
	return NULL;
}

38
static struct dsa_switch_tree *dsa_tree_alloc(int index)
39 40 41 42 43 44
{
	struct dsa_switch_tree *dst;

	dst = kzalloc(sizeof(*dst), GFP_KERNEL);
	if (!dst)
		return NULL;
45

46
	dst->index = index;
47

48 49
	INIT_LIST_HEAD(&dst->ports);

50
	INIT_LIST_HEAD(&dst->list);
V
Vivien Didelot 已提交
51
	list_add_tail(&dst->list, &dsa_tree_list);
52

53 54 55 56 57
	kref_init(&dst->refcount);

	return dst;
}

58 59 60 61 62 63
static void dsa_tree_free(struct dsa_switch_tree *dst)
{
	list_del(&dst->list);
	kfree(dst);
}

64
static struct dsa_switch_tree *dsa_tree_get(struct dsa_switch_tree *dst)
65
{
66 67
	if (dst)
		kref_get(&dst->refcount);
68 69 70 71

	return dst;
}

72
static struct dsa_switch_tree *dsa_tree_touch(int index)
73
{
74 75 76 77 78 79 80
	struct dsa_switch_tree *dst;

	dst = dsa_tree_find(index);
	if (dst)
		return dsa_tree_get(dst);
	else
		return dsa_tree_alloc(index);
81 82 83 84 85 86 87 88 89 90 91 92 93
}

static void dsa_tree_release(struct kref *ref)
{
	struct dsa_switch_tree *dst;

	dst = container_of(ref, struct dsa_switch_tree, refcount);

	dsa_tree_free(dst);
}

static void dsa_tree_put(struct dsa_switch_tree *dst)
{
94 95
	if (dst)
		kref_put(&dst->refcount, dsa_tree_release);
96 97
}

98
static bool dsa_port_is_dsa(struct dsa_port *port)
99
{
100
	return port->type == DSA_PORT_TYPE_DSA;
101 102 103 104
}

static bool dsa_port_is_cpu(struct dsa_port *port)
{
105
	return port->type == DSA_PORT_TYPE_CPU;
106 107
}

108 109 110 111 112
static bool dsa_port_is_user(struct dsa_port *dp)
{
	return dp->type == DSA_PORT_TYPE_USER;
}

113 114
static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
						   struct device_node *dn)
115 116
{
	struct dsa_switch *ds;
117 118
	struct dsa_port *dp;
	int device, port;
119

120 121
	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
122 123 124
		if (!ds)
			continue;

125 126 127 128 129 130
		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			if (dp->dn == dn)
				return dp;
		}
131 132 133 134 135
	}

	return NULL;
}

V
Vivien Didelot 已提交
136
static bool dsa_port_setup_routing_table(struct dsa_port *dp)
137
{
V
Vivien Didelot 已提交
138 139 140
	struct dsa_switch *ds = dp->ds;
	struct dsa_switch_tree *dst = ds->dst;
	struct device_node *dn = dp->dn;
V
Vivien Didelot 已提交
141
	struct of_phandle_iterator it;
142
	struct dsa_port *link_dp;
V
Vivien Didelot 已提交
143
	int err;
144

V
Vivien Didelot 已提交
145 146 147 148
	of_for_each_phandle(&it, err, dn, "link", NULL, 0) {
		link_dp = dsa_tree_find_port_by_node(dst, it.node);
		if (!link_dp) {
			of_node_put(it.node);
V
Vivien Didelot 已提交
149
			return false;
V
Vivien Didelot 已提交
150
		}
151

V
Vivien Didelot 已提交
152
		ds->rtable[link_dp->ds->index] = dp->index;
153 154
	}

V
Vivien Didelot 已提交
155
	return true;
156 157
}

V
Vivien Didelot 已提交
158
static bool dsa_switch_setup_routing_table(struct dsa_switch *ds)
159
{
V
Vivien Didelot 已提交
160 161 162
	bool complete = true;
	struct dsa_port *dp;
	int i;
163

V
Vivien Didelot 已提交
164 165
	for (i = 0; i < DSA_MAX_SWITCHES; i++)
		ds->rtable[i] = DSA_RTABLE_NONE;
166

V
Vivien Didelot 已提交
167 168
	for (i = 0; i < ds->num_ports; i++) {
		dp = &ds->ports[i];
169

V
Vivien Didelot 已提交
170 171 172 173 174
		if (dsa_port_is_dsa(dp)) {
			complete = dsa_port_setup_routing_table(dp);
			if (!complete)
				break;
		}
175 176
	}

V
Vivien Didelot 已提交
177
	return complete;
178 179
}

V
Vivien Didelot 已提交
180
static bool dsa_tree_setup_routing_table(struct dsa_switch_tree *dst)
181 182
{
	struct dsa_switch *ds;
V
Vivien Didelot 已提交
183 184
	bool complete = true;
	int device;
185

V
Vivien Didelot 已提交
186 187
	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
188 189 190
		if (!ds)
			continue;

V
Vivien Didelot 已提交
191 192 193
		complete = dsa_switch_setup_routing_table(ds);
		if (!complete)
			break;
194 195
	}

V
Vivien Didelot 已提交
196
	return complete;
197 198
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
	struct dsa_port *dp;
	int device, port;

	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
		if (!ds)
			continue;

		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			if (dsa_port_is_cpu(dp))
				return dp;
		}
	}

	return NULL;
}

static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
	struct dsa_port *dp;
	int device, port;

	/* DSA currently only supports a single CPU port */
	dst->cpu_dp = dsa_tree_find_first_cpu(dst);
	if (!dst->cpu_dp) {
		pr_warn("Tree has no master device\n");
		return -EINVAL;
	}

	/* Assign the default CPU port to all ports of the fabric */
	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
		if (!ds)
			continue;

		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

243
			if (dsa_port_is_user(dp) || dsa_port_is_dsa(dp))
244 245 246 247 248 249 250 251 252 253 254 255 256
				dp->cpu_dp = dst->cpu_dp;
		}
	}

	return 0;
}

static void dsa_tree_teardown_default_cpu(struct dsa_switch_tree *dst)
{
	/* DSA currently only supports a single CPU port */
	dst->cpu_dp = NULL;
}

257
static int dsa_port_setup(struct dsa_port *dp)
258
{
259
	struct dsa_switch *ds = dp->ds;
260
	struct dsa_switch_tree *dst = ds->dst;
261 262 263
	const unsigned char *id = (const unsigned char *)&dst->index;
	const unsigned char len = sizeof(dst->index);
	struct devlink_port *dlp = &dp->devlink_port;
264 265
	bool dsa_port_link_registered = false;
	bool devlink_port_registered = false;
266
	struct devlink *dl = ds->devlink;
267 268
	bool dsa_port_enabled = false;
	int err = 0;
269

270 271
	switch (dp->type) {
	case DSA_PORT_TYPE_UNUSED:
272
		dsa_port_disable(dp);
273 274
		break;
	case DSA_PORT_TYPE_CPU:
275 276 277 278 279
		memset(dlp, 0, sizeof(*dlp));
		devlink_port_attrs_set(dlp, DEVLINK_PORT_FLAVOUR_CPU,
				       dp->index, false, 0, id, len);
		err = devlink_port_register(dl, dlp, dp->index);
		if (err)
280 281
			break;
		devlink_port_registered = true;
282

283
		err = dsa_port_link_register_of(dp);
284
		if (err)
285 286
			break;
		dsa_port_link_registered = true;
287 288

		err = dsa_port_enable(dp, NULL);
289
		if (err)
290 291 292
			break;
		dsa_port_enabled = true;

293
		break;
294
	case DSA_PORT_TYPE_DSA:
295 296 297 298 299
		memset(dlp, 0, sizeof(*dlp));
		devlink_port_attrs_set(dlp, DEVLINK_PORT_FLAVOUR_DSA,
				       dp->index, false, 0, id, len);
		err = devlink_port_register(dl, dlp, dp->index);
		if (err)
300 301
			break;
		devlink_port_registered = true;
302

303
		err = dsa_port_link_register_of(dp);
304
		if (err)
305 306
			break;
		dsa_port_link_registered = true;
307 308

		err = dsa_port_enable(dp, NULL);
309
		if (err)
310 311 312
			break;
		dsa_port_enabled = true;

313 314
		break;
	case DSA_PORT_TYPE_USER:
315 316 317 318 319
		memset(dlp, 0, sizeof(*dlp));
		devlink_port_attrs_set(dlp, DEVLINK_PORT_FLAVOUR_PHYSICAL,
				       dp->index, false, 0, id, len);
		err = devlink_port_register(dl, dlp, dp->index);
		if (err)
320 321
			break;
		devlink_port_registered = true;
322 323

		dp->mac = of_get_mac_address(dp->dn);
324 325
		err = dsa_slave_create(dp);
		if (err)
326
			break;
327 328

		devlink_port_type_eth_set(dlp, dp->slave);
329
		break;
330 331
	}

332 333 334 335 336 337 338 339
	if (err && dsa_port_enabled)
		dsa_port_disable(dp);
	if (err && dsa_port_link_registered)
		dsa_port_link_unregister_of(dp);
	if (err && devlink_port_registered)
		devlink_port_unregister(dlp);

	return err;
340 341
}

342
static void dsa_port_teardown(struct dsa_port *dp)
343
{
344
	struct devlink_port *dlp = &dp->devlink_port;
345 346 347 348 349

	switch (dp->type) {
	case DSA_PORT_TYPE_UNUSED:
		break;
	case DSA_PORT_TYPE_CPU:
350
		dsa_port_disable(dp);
351
		dsa_tag_driver_put(dp->tag_ops);
352 353 354
		devlink_port_unregister(dlp);
		dsa_port_link_unregister_of(dp);
		break;
355
	case DSA_PORT_TYPE_DSA:
356
		dsa_port_disable(dp);
357
		devlink_port_unregister(dlp);
358
		dsa_port_link_unregister_of(dp);
359 360
		break;
	case DSA_PORT_TYPE_USER:
361
		devlink_port_unregister(dlp);
362 363 364 365 366
		if (dp->slave) {
			dsa_slave_destroy(dp->slave);
			dp->slave = NULL;
		}
		break;
367 368 369
	}
}

370
static int dsa_switch_setup(struct dsa_switch *ds)
371
{
372
	int err = 0;
373

374
	/* Initialize ds->phys_mii_mask before registering the slave MDIO bus
375
	 * driver and before ops->setup() has run, since the switch drivers and
376 377 378
	 * the slave MDIO bus driver rely on these values for probing PHY
	 * devices or not
	 */
379
	ds->phys_mii_mask |= dsa_user_ports(ds);
380

381 382 383 384 385 386 387 388 389
	/* Add the switch to devlink before calling setup, so that setup can
	 * add dpipe tables
	 */
	ds->devlink = devlink_alloc(&dsa_devlink_ops, 0);
	if (!ds->devlink)
		return -ENOMEM;

	err = devlink_register(ds->devlink, ds->dev);
	if (err)
390
		goto free_devlink;
391

V
Vivien Didelot 已提交
392 393
	err = dsa_switch_register_notifier(ds);
	if (err)
394
		goto unregister_devlink;
V
Vivien Didelot 已提交
395

396 397
	err = ds->ops->setup(ds);
	if (err < 0)
398
		goto unregister_notifier;
399

400
	if (!ds->slave_mii_bus && ds->ops->phy_read) {
401
		ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
402 403 404 405
		if (!ds->slave_mii_bus) {
			err = -ENOMEM;
			goto unregister_notifier;
		}
406 407 408 409 410

		dsa_slave_mii_bus_init(ds);

		err = mdiobus_register(ds->slave_mii_bus);
		if (err < 0)
411
			goto unregister_notifier;
412 413
	}

414
	return 0;
415 416 417 418 419 420 421 422 423 424

unregister_notifier:
	dsa_switch_unregister_notifier(ds);
unregister_devlink:
	devlink_unregister(ds->devlink);
free_devlink:
	devlink_free(ds->devlink);
	ds->devlink = NULL;

	return err;
425 426
}

427
static void dsa_switch_teardown(struct dsa_switch *ds)
428
{
429
	if (ds->slave_mii_bus && ds->ops->phy_read)
430
		mdiobus_unregister(ds->slave_mii_bus);
V
Vivien Didelot 已提交
431 432

	dsa_switch_unregister_notifier(ds);
433

434 435 436
	if (ds->ops->teardown)
		ds->ops->teardown(ds);

437 438 439 440 441 442
	if (ds->devlink) {
		devlink_unregister(ds->devlink);
		devlink_free(ds->devlink);
		ds->devlink = NULL;
	}

443 444
}

445 446 447
static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
448
	struct dsa_port *dp;
449 450
	int device, port, i;
	int err = 0;
451 452 453 454 455 456 457 458

	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
		if (!ds)
			continue;

		err = dsa_switch_setup(ds);
		if (err)
459
			goto switch_teardown;
460 461 462 463 464 465

		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			err = dsa_port_setup(dp);
			if (err)
466
				goto ports_teardown;
467
		}
468 469 470
	}

	return 0;
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493

ports_teardown:
	for (i = 0; i < port; i++)
		dsa_port_teardown(&ds->ports[i]);

	dsa_switch_teardown(ds);

switch_teardown:
	for (i = 0; i < device; i++) {
		ds = dst->ds[i];
		if (!ds)
			continue;

		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			dsa_port_teardown(dp);
		}

		dsa_switch_teardown(ds);
	}

	return err;
494 495 496 497 498
}

static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
499 500
	struct dsa_port *dp;
	int device, port;
501 502 503 504 505 506

	for (device = 0; device < DSA_MAX_SWITCHES; device++) {
		ds = dst->ds[device];
		if (!ds)
			continue;

507 508 509 510 511 512
		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			dsa_port_teardown(dp);
		}

513 514 515 516
		dsa_switch_teardown(ds);
	}
}

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
{
	struct dsa_port *cpu_dp = dst->cpu_dp;
	struct net_device *master = cpu_dp->master;

	/* DSA currently supports a single pair of CPU port and master device */
	return dsa_master_setup(master, cpu_dp);
}

static void dsa_tree_teardown_master(struct dsa_switch_tree *dst)
{
	struct dsa_port *cpu_dp = dst->cpu_dp;
	struct net_device *master = cpu_dp->master;

	return dsa_master_teardown(master);
}

V
Vivien Didelot 已提交
534
static int dsa_tree_setup(struct dsa_switch_tree *dst)
535
{
V
Vivien Didelot 已提交
536
	bool complete;
537 538
	int err;

V
Vivien Didelot 已提交
539 540 541 542 543 544
	if (dst->setup) {
		pr_err("DSA: tree %d already setup! Disjoint trees?\n",
		       dst->index);
		return -EEXIST;
	}

V
Vivien Didelot 已提交
545 546 547 548
	complete = dsa_tree_setup_routing_table(dst);
	if (!complete)
		return 0;

549 550 551 552
	err = dsa_tree_setup_default_cpu(dst);
	if (err)
		return err;

553 554
	err = dsa_tree_setup_switches(dst);
	if (err)
555
		goto teardown_default_cpu;
556

557
	err = dsa_tree_setup_master(dst);
558
	if (err)
559
		goto teardown_switches;
560

V
Vivien Didelot 已提交
561 562 563
	dst->setup = true;

	pr_info("DSA: tree %d setup\n", dst->index);
564 565

	return 0;
566 567 568 569 570 571 572

teardown_switches:
	dsa_tree_teardown_switches(dst);
teardown_default_cpu:
	dsa_tree_teardown_default_cpu(dst);

	return err;
573 574
}

V
Vivien Didelot 已提交
575
static void dsa_tree_teardown(struct dsa_switch_tree *dst)
576
{
V
Vivien Didelot 已提交
577
	if (!dst->setup)
578 579
		return;

580
	dsa_tree_teardown_master(dst);
581

582
	dsa_tree_teardown_switches(dst);
583

584
	dsa_tree_teardown_default_cpu(dst);
585

V
Vivien Didelot 已提交
586 587 588
	pr_info("DSA: tree %d torn down\n", dst->index);

	dst->setup = false;
589 590
}

591 592 593
static void dsa_tree_remove_switch(struct dsa_switch_tree *dst,
				   unsigned int index)
{
594 595
	dsa_tree_teardown(dst);

596 597 598 599 600 601 602 603
	dst->ds[index] = NULL;
	dsa_tree_put(dst);
}

static int dsa_tree_add_switch(struct dsa_switch_tree *dst,
			       struct dsa_switch *ds)
{
	unsigned int index = ds->index;
604
	int err;
605 606 607 608 609 610 611

	if (dst->ds[index])
		return -EBUSY;

	dsa_tree_get(dst);
	dst->ds[index] = ds;

612
	err = dsa_tree_setup(dst);
613 614 615 616
	if (err) {
		dst->ds[index] = NULL;
		dsa_tree_put(dst);
	}
617 618

	return err;
619 620
}

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index)
{
	struct dsa_switch_tree *dst = ds->dst;
	struct dsa_port *dp;

	dp = &ds->ports[index];

	dp->ds = ds;
	dp->index = index;

	INIT_LIST_HEAD(&dp->list);
	list_add_tail(&dp->list, &dst->ports);

	return dp;
}

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
static int dsa_port_parse_user(struct dsa_port *dp, const char *name)
{
	if (!name)
		name = "eth%d";

	dp->type = DSA_PORT_TYPE_USER;
	dp->name = name;

	return 0;
}

static int dsa_port_parse_dsa(struct dsa_port *dp)
{
	dp->type = DSA_PORT_TYPE_DSA;

	return 0;
}

static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master)
{
657 658 659 660 661
	struct dsa_switch *ds = dp->ds;
	struct dsa_switch_tree *dst = ds->dst;
	const struct dsa_device_ops *tag_ops;
	enum dsa_tag_protocol tag_protocol;

662
	tag_protocol = ds->ops->get_tag_protocol(ds, dp->index);
663
	tag_ops = dsa_tag_driver_get(tag_protocol);
664
	if (IS_ERR(tag_ops)) {
665 666
		if (PTR_ERR(tag_ops) == -ENOPROTOOPT)
			return -EPROBE_DEFER;
667 668 669 670
		dev_warn(ds->dev, "No tagger for this switch\n");
		return PTR_ERR(tag_ops);
	}

671
	dp->type = DSA_PORT_TYPE_CPU;
672
	dp->filter = tag_ops->filter;
673 674
	dp->rcv = tag_ops->rcv;
	dp->tag_ops = tag_ops;
675
	dp->master = master;
676
	dp->dst = dst;
677 678 679 680

	return 0;
}

681 682
static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
{
683
	struct device_node *ethernet = of_parse_phandle(dn, "ethernet", 0);
684
	const char *name = of_get_property(dn, "label", NULL);
685
	bool link = of_property_read_bool(dn, "link");
686

687 688
	dp->dn = dn;

689
	if (ethernet) {
690 691 692 693 694 695
		struct net_device *master;

		master = of_find_net_device_by_node(ethernet);
		if (!master)
			return -EPROBE_DEFER;

696
		return dsa_port_parse_cpu(dp, master);
697 698
	}

699 700
	if (link)
		return dsa_port_parse_dsa(dp);
701

702
	return dsa_port_parse_user(dp, name);
703 704
}

V
Vivien Didelot 已提交
705 706
static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
				     struct device_node *dn)
707
{
708
	struct device_node *ports, *port;
709
	struct dsa_port *dp;
710
	int err = 0;
711
	u32 reg;
712 713 714 715 716 717

	ports = of_get_child_by_name(dn, "ports");
	if (!ports) {
		dev_err(ds->dev, "no ports child node found\n");
		return -EINVAL;
	}
718 719 720 721

	for_each_available_child_of_node(ports, port) {
		err = of_property_read_u32(port, "reg", &reg);
		if (err)
722
			goto out_put_node;
723

724 725 726 727
		if (reg >= ds->num_ports) {
			err = -EINVAL;
			goto out_put_node;
		}
728

729
		dp = dsa_to_port(ds, reg);
730 731 732

		err = dsa_port_parse_of(dp, port);
		if (err)
733
			goto out_put_node;
734 735
	}

736 737 738
out_put_node:
	of_node_put(ports);
	return err;
739 740
}

V
Vivien Didelot 已提交
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
static int dsa_switch_parse_member_of(struct dsa_switch *ds,
				      struct device_node *dn)
{
	u32 m[2] = { 0, 0 };
	int sz;

	/* Don't error out if this optional property isn't found */
	sz = of_property_read_variable_u32_array(dn, "dsa,member", m, 2, 2);
	if (sz < 0 && sz != -EINVAL)
		return sz;

	ds->index = m[1];
	if (ds->index >= DSA_MAX_SWITCHES)
		return -EINVAL;

	ds->dst = dsa_tree_touch(m[0]);
	if (!ds->dst)
		return -ENOMEM;

	return 0;
}

763 764 765 766 767 768 769 770 771 772 773 774 775 776
static int dsa_switch_touch_ports(struct dsa_switch *ds)
{
	struct dsa_port *dp;
	int port;

	for (port = 0; port < ds->num_ports; port++) {
		dp = dsa_port_touch(ds, port);
		if (!dp)
			return -ENOMEM;
	}

	return 0;
}

V
Vivien Didelot 已提交
777 778 779 780 781 782 783 784
static int dsa_switch_parse_of(struct dsa_switch *ds, struct device_node *dn)
{
	int err;

	err = dsa_switch_parse_member_of(ds, dn);
	if (err)
		return err;

785 786 787 788
	err = dsa_switch_touch_ports(ds);
	if (err)
		return err;

V
Vivien Didelot 已提交
789 790 791
	return dsa_switch_parse_ports_of(ds, dn);
}

792 793 794
static int dsa_port_parse(struct dsa_port *dp, const char *name,
			  struct device *dev)
{
795
	if (!strcmp(name, "cpu")) {
796 797 798 799 800 801 802 803
		struct net_device *master;

		master = dsa_dev_to_net_device(dev);
		if (!master)
			return -EPROBE_DEFER;

		dev_put(master);

804
		return dsa_port_parse_cpu(dp, master);
805 806
	}

807 808
	if (!strcmp(name, "dsa"))
		return dsa_port_parse_dsa(dp);
809

810
	return dsa_port_parse_user(dp, name);
811 812
}

V
Vivien Didelot 已提交
813 814
static int dsa_switch_parse_ports(struct dsa_switch *ds,
				  struct dsa_chip_data *cd)
815 816
{
	bool valid_name_found = false;
817 818 819
	struct dsa_port *dp;
	struct device *dev;
	const char *name;
820
	unsigned int i;
821
	int err;
822 823

	for (i = 0; i < DSA_MAX_PORTS; i++) {
824 825
		name = cd->port_names[i];
		dev = cd->netdev[i];
826
		dp = dsa_to_port(ds, i);
827 828

		if (!name)
829 830
			continue;

831 832 833 834
		err = dsa_port_parse(dp, name, dev);
		if (err)
			return err;

835 836 837 838 839 840 841 842 843
		valid_name_found = true;
	}

	if (!valid_name_found && i == DSA_MAX_PORTS)
		return -EINVAL;

	return 0;
}

V
Vivien Didelot 已提交
844
static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
845
{
846 847
	int err;

V
Vivien Didelot 已提交
848
	ds->cd = cd;
849

V
Vivien Didelot 已提交
850 851 852 853 854 855 856
	/* We don't support interconnected switches nor multiple trees via
	 * platform data, so this is the unique switch of the tree.
	 */
	ds->index = 0;
	ds->dst = dsa_tree_touch(0);
	if (!ds->dst)
		return -ENOMEM;
857

858 859 860 861
	err = dsa_switch_touch_ports(ds);
	if (err)
		return err;

V
Vivien Didelot 已提交
862
	return dsa_switch_parse_ports(ds, cd);
863 864
}

865 866 867 868 869 870 871
static int dsa_switch_add(struct dsa_switch *ds)
{
	struct dsa_switch_tree *dst = ds->dst;

	return dsa_tree_add_switch(dst, ds);
}

872
static int dsa_switch_probe(struct dsa_switch *ds)
873
{
874 875
	struct dsa_chip_data *pdata = ds->dev->platform_data;
	struct device_node *np = ds->dev->of_node;
V
Vivien Didelot 已提交
876
	int err;
877

V
Vivien Didelot 已提交
878 879 880 881 882 883
	if (np)
		err = dsa_switch_parse_of(ds, np);
	else if (pdata)
		err = dsa_switch_parse(ds, pdata);
	else
		err = -ENODEV;
884

V
Vivien Didelot 已提交
885 886
	if (err)
		return err;
887

888
	return dsa_switch_add(ds);
889 890
}

891 892 893 894
struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n)
{
	struct dsa_switch *ds;

895
	ds = devm_kzalloc(dev, struct_size(ds, ports, n), GFP_KERNEL);
896 897 898 899 900 901 902 903 904 905
	if (!ds)
		return NULL;

	ds->dev = dev;
	ds->num_ports = n;

	return ds;
}
EXPORT_SYMBOL_GPL(dsa_switch_alloc);

906
int dsa_register_switch(struct dsa_switch *ds)
907 908 909 910
{
	int err;

	mutex_lock(&dsa2_mutex);
911
	err = dsa_switch_probe(ds);
912
	dsa_tree_put(ds->dst);
913 914 915 916 917 918
	mutex_unlock(&dsa2_mutex);

	return err;
}
EXPORT_SYMBOL_GPL(dsa_register_switch);

919
static void dsa_switch_remove(struct dsa_switch *ds)
920 921
{
	struct dsa_switch_tree *dst = ds->dst;
922
	unsigned int index = ds->index;
923

924
	dsa_tree_remove_switch(dst, index);
925 926 927 928 929
}

void dsa_unregister_switch(struct dsa_switch *ds)
{
	mutex_lock(&dsa2_mutex);
930
	dsa_switch_remove(ds);
931 932 933
	mutex_unlock(&dsa2_mutex);
}
EXPORT_SYMBOL_GPL(dsa_unregister_switch);