dsa2.c 16.9 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
	INIT_LIST_HEAD(&dst->list);
49
	list_add_tail(&dsa_tree_list, &dst->list);
50

51 52 53 54 55
	kref_init(&dst->refcount);

	return dst;
}

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

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

	return dst;
}

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

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

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)
{
92 93
	if (dst)
		kref_put(&dst->refcount, dsa_tree_release);
94 95
}

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

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

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

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

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

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

			if (dp->dn == dn)
				return dp;
		}
129 130 131 132 133
	}

	return NULL;
}

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

V
Vivien Didelot 已提交
143 144 145 146
	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 已提交
147
			return false;
V
Vivien Didelot 已提交
148
		}
149

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

V
Vivien Didelot 已提交
153
	return true;
154 155
}

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

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

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

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

V
Vivien Didelot 已提交
175
	return complete;
176 177
}

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

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

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

V
Vivien Didelot 已提交
194
	return complete;
195 196
}

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
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];

241
			if (dsa_port_is_user(dp) || dsa_port_is_dsa(dp))
242 243 244 245 246 247 248 249 250 251 252 253 254
				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;
}

255
static int dsa_port_setup(struct dsa_port *dp)
256
{
257
	struct dsa_switch *ds = dp->ds;
258
	struct dsa_switch_tree *dst = ds->dst;
259 260 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;
	struct devlink *dl = ds->devlink;
	int err;
264

265 266
	switch (dp->type) {
	case DSA_PORT_TYPE_UNUSED:
267
		dsa_port_disable(dp);
268 269
		break;
	case DSA_PORT_TYPE_CPU:
270 271 272 273 274 275 276
		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)
			return err;

277
		err = dsa_port_link_register_of(dp);
278 279 280 281
		if (err)
			return err;

		err = dsa_port_enable(dp, NULL);
282
		if (err)
283
			return err;
284
		break;
285
	case DSA_PORT_TYPE_DSA:
286 287 288 289 290 291 292
		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)
			return err;

293
		err = dsa_port_link_register_of(dp);
294 295 296 297
		if (err)
			return err;

		err = dsa_port_enable(dp, NULL);
298
		if (err)
299
			return err;
300 301
		break;
	case DSA_PORT_TYPE_USER:
302 303 304 305 306 307 308 309
		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)
			return err;

		dp->mac = of_get_mac_address(dp->dn);
310 311
		err = dsa_slave_create(dp);
		if (err)
312 313 314
			return err;

		devlink_port_type_eth_set(dlp, dp->slave);
315
		break;
316 317
	}

318
	return 0;
319 320
}

321
static void dsa_port_teardown(struct dsa_port *dp)
322
{
323
	struct devlink_port *dlp = &dp->devlink_port;
324 325 326 327 328

	switch (dp->type) {
	case DSA_PORT_TYPE_UNUSED:
		break;
	case DSA_PORT_TYPE_CPU:
329
		dsa_port_disable(dp);
330
		dsa_tag_driver_put(dp->tag_ops);
331 332 333
		devlink_port_unregister(dlp);
		dsa_port_link_unregister_of(dp);
		break;
334
	case DSA_PORT_TYPE_DSA:
335
		dsa_port_disable(dp);
336
		devlink_port_unregister(dlp);
337
		dsa_port_link_unregister_of(dp);
338 339
		break;
	case DSA_PORT_TYPE_USER:
340
		devlink_port_unregister(dlp);
341 342 343 344 345
		if (dp->slave) {
			dsa_slave_destroy(dp->slave);
			dp->slave = NULL;
		}
		break;
346 347 348
	}
}

349
static int dsa_switch_setup(struct dsa_switch *ds)
350
{
351
	int err = 0;
352

353
	/* Initialize ds->phys_mii_mask before registering the slave MDIO bus
354
	 * driver and before ops->setup() has run, since the switch drivers and
355 356 357
	 * the slave MDIO bus driver rely on these values for probing PHY
	 * devices or not
	 */
358
	ds->phys_mii_mask |= dsa_user_ports(ds);
359

360 361 362 363 364 365 366 367 368
	/* 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)
369
		goto free_devlink;
370

V
Vivien Didelot 已提交
371 372
	err = dsa_switch_register_notifier(ds);
	if (err)
373
		goto unregister_devlink;
V
Vivien Didelot 已提交
374

375 376
	err = ds->ops->setup(ds);
	if (err < 0)
377
		goto unregister_notifier;
378

379
	if (!ds->slave_mii_bus && ds->ops->phy_read) {
380
		ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
381 382 383 384
		if (!ds->slave_mii_bus) {
			err = -ENOMEM;
			goto unregister_notifier;
		}
385 386 387 388 389

		dsa_slave_mii_bus_init(ds);

		err = mdiobus_register(ds->slave_mii_bus);
		if (err < 0)
390
			goto unregister_notifier;
391 392
	}

393
	return 0;
394 395 396 397 398 399 400 401 402 403

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

	return err;
404 405
}

406
static void dsa_switch_teardown(struct dsa_switch *ds)
407
{
408
	if (ds->slave_mii_bus && ds->ops->phy_read)
409
		mdiobus_unregister(ds->slave_mii_bus);
V
Vivien Didelot 已提交
410 411

	dsa_switch_unregister_notifier(ds);
412

413 414 415
	if (ds->ops->teardown)
		ds->ops->teardown(ds);

416 417 418 419 420 421
	if (ds->devlink) {
		devlink_unregister(ds->devlink);
		devlink_free(ds->devlink);
		ds->devlink = NULL;
	}

422 423
}

424 425 426
static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
427
	struct dsa_port *dp;
428 429
	int device, port, i;
	int err = 0;
430 431 432 433 434 435 436 437

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

		err = dsa_switch_setup(ds);
		if (err)
438
			goto switch_teardown;
439 440 441 442 443 444

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

			err = dsa_port_setup(dp);
			if (err)
445
				goto ports_teardown;
446
		}
447 448 449
	}

	return 0;
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472

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;
473 474 475 476 477
}

static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst)
{
	struct dsa_switch *ds;
478 479
	struct dsa_port *dp;
	int device, port;
480 481 482 483 484 485

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

486 487 488 489 490 491
		for (port = 0; port < ds->num_ports; port++) {
			dp = &ds->ports[port];

			dsa_port_teardown(dp);
		}

492 493 494 495
		dsa_switch_teardown(ds);
	}
}

496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
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 已提交
513
static int dsa_tree_setup(struct dsa_switch_tree *dst)
514
{
V
Vivien Didelot 已提交
515
	bool complete;
516 517
	int err;

V
Vivien Didelot 已提交
518 519 520 521 522 523
	if (dst->setup) {
		pr_err("DSA: tree %d already setup! Disjoint trees?\n",
		       dst->index);
		return -EEXIST;
	}

V
Vivien Didelot 已提交
524 525 526 527
	complete = dsa_tree_setup_routing_table(dst);
	if (!complete)
		return 0;

528 529 530 531
	err = dsa_tree_setup_default_cpu(dst);
	if (err)
		return err;

532 533
	err = dsa_tree_setup_switches(dst);
	if (err)
534
		goto teardown_default_cpu;
535

536
	err = dsa_tree_setup_master(dst);
537
	if (err)
538
		goto teardown_switches;
539

V
Vivien Didelot 已提交
540 541 542
	dst->setup = true;

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

	return 0;
545 546 547 548 549 550 551

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

	return err;
552 553
}

V
Vivien Didelot 已提交
554
static void dsa_tree_teardown(struct dsa_switch_tree *dst)
555
{
V
Vivien Didelot 已提交
556
	if (!dst->setup)
557 558
		return;

559
	dsa_tree_teardown_master(dst);
560

561
	dsa_tree_teardown_switches(dst);
562

563
	dsa_tree_teardown_default_cpu(dst);
564

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

	dst->setup = false;
568 569
}

570 571 572
static void dsa_tree_remove_switch(struct dsa_switch_tree *dst,
				   unsigned int index)
{
573 574
	dsa_tree_teardown(dst);

575 576 577 578 579 580 581 582
	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;
583
	int err;
584 585 586 587 588 589 590

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

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

591
	err = dsa_tree_setup(dst);
592 593 594 595
	if (err) {
		dst->ds[index] = NULL;
		dsa_tree_put(dst);
	}
596 597

	return err;
598 599
}

600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
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)
{
620 621 622 623 624
	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;

625
	tag_protocol = ds->ops->get_tag_protocol(ds, dp->index);
626
	tag_ops = dsa_tag_driver_get(tag_protocol);
627 628 629 630 631
	if (IS_ERR(tag_ops)) {
		dev_warn(ds->dev, "No tagger for this switch\n");
		return PTR_ERR(tag_ops);
	}

632
	dp->type = DSA_PORT_TYPE_CPU;
633
	dp->filter = tag_ops->filter;
634 635
	dp->rcv = tag_ops->rcv;
	dp->tag_ops = tag_ops;
636
	dp->master = master;
637
	dp->dst = dst;
638 639 640 641

	return 0;
}

642 643
static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
{
644
	struct device_node *ethernet = of_parse_phandle(dn, "ethernet", 0);
645
	const char *name = of_get_property(dn, "label", NULL);
646
	bool link = of_property_read_bool(dn, "link");
647

648 649
	dp->dn = dn;

650
	if (ethernet) {
651 652 653 654 655 656
		struct net_device *master;

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

657
		return dsa_port_parse_cpu(dp, master);
658 659
	}

660 661
	if (link)
		return dsa_port_parse_dsa(dp);
662

663
	return dsa_port_parse_user(dp, name);
664 665
}

V
Vivien Didelot 已提交
666 667
static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
				     struct device_node *dn)
668
{
669
	struct device_node *ports, *port;
670
	struct dsa_port *dp;
671
	int err = 0;
672
	u32 reg;
673 674 675 676 677 678

	ports = of_get_child_by_name(dn, "ports");
	if (!ports) {
		dev_err(ds->dev, "no ports child node found\n");
		return -EINVAL;
	}
679 680 681 682

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

685 686 687 688
		if (reg >= ds->num_ports) {
			err = -EINVAL;
			goto out_put_node;
		}
689

690 691 692 693
		dp = &ds->ports[reg];

		err = dsa_port_parse_of(dp, port);
		if (err)
694
			goto out_put_node;
695 696
	}

697 698 699
out_put_node:
	of_node_put(ports);
	return err;
700 701
}

V
Vivien Didelot 已提交
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
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;
}

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;

	return dsa_switch_parse_ports_of(ds, dn);
}

735 736 737
static int dsa_port_parse(struct dsa_port *dp, const char *name,
			  struct device *dev)
{
738
	if (!strcmp(name, "cpu")) {
739 740 741 742 743 744 745 746
		struct net_device *master;

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

		dev_put(master);

747
		return dsa_port_parse_cpu(dp, master);
748 749
	}

750 751
	if (!strcmp(name, "dsa"))
		return dsa_port_parse_dsa(dp);
752

753
	return dsa_port_parse_user(dp, name);
754 755
}

V
Vivien Didelot 已提交
756 757
static int dsa_switch_parse_ports(struct dsa_switch *ds,
				  struct dsa_chip_data *cd)
758 759
{
	bool valid_name_found = false;
760 761 762
	struct dsa_port *dp;
	struct device *dev;
	const char *name;
763
	unsigned int i;
764
	int err;
765 766

	for (i = 0; i < DSA_MAX_PORTS; i++) {
767 768 769 770 771
		name = cd->port_names[i];
		dev = cd->netdev[i];
		dp = &ds->ports[i];

		if (!name)
772 773
			continue;

774 775 776 777
		err = dsa_port_parse(dp, name, dev);
		if (err)
			return err;

778 779 780 781 782 783 784 785 786
		valid_name_found = true;
	}

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

	return 0;
}

V
Vivien Didelot 已提交
787
static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
788
{
V
Vivien Didelot 已提交
789
	ds->cd = cd;
790

V
Vivien Didelot 已提交
791 792 793 794 795 796 797
	/* 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;
798

V
Vivien Didelot 已提交
799
	return dsa_switch_parse_ports(ds, cd);
800 801
}

802 803 804 805 806 807 808
static int dsa_switch_add(struct dsa_switch *ds)
{
	struct dsa_switch_tree *dst = ds->dst;

	return dsa_tree_add_switch(dst, ds);
}

809
static int dsa_switch_probe(struct dsa_switch *ds)
810
{
811 812
	struct dsa_chip_data *pdata = ds->dev->platform_data;
	struct device_node *np = ds->dev->of_node;
V
Vivien Didelot 已提交
813
	int err;
814

V
Vivien Didelot 已提交
815 816 817 818 819 820
	if (np)
		err = dsa_switch_parse_of(ds, np);
	else if (pdata)
		err = dsa_switch_parse(ds, pdata);
	else
		err = -ENODEV;
821

V
Vivien Didelot 已提交
822 823
	if (err)
		return err;
824

825
	return dsa_switch_add(ds);
826 827
}

828 829 830
struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n)
{
	struct dsa_switch *ds;
831
	int i;
832

833
	ds = devm_kzalloc(dev, struct_size(ds, ports, n), GFP_KERNEL);
834 835 836 837 838 839
	if (!ds)
		return NULL;

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

840 841 842 843 844
	for (i = 0; i < ds->num_ports; ++i) {
		ds->ports[i].index = i;
		ds->ports[i].ds = ds;
	}

845 846 847 848
	return ds;
}
EXPORT_SYMBOL_GPL(dsa_switch_alloc);

849
int dsa_register_switch(struct dsa_switch *ds)
850 851 852 853
{
	int err;

	mutex_lock(&dsa2_mutex);
854
	err = dsa_switch_probe(ds);
855
	dsa_tree_put(ds->dst);
856 857 858 859 860 861
	mutex_unlock(&dsa2_mutex);

	return err;
}
EXPORT_SYMBOL_GPL(dsa_register_switch);

862
static void dsa_switch_remove(struct dsa_switch *ds)
863 864
{
	struct dsa_switch_tree *dst = ds->dst;
865
	unsigned int index = ds->index;
866

867
	dsa_tree_remove_switch(dst, index);
868 869 870 871 872
}

void dsa_unregister_switch(struct dsa_switch *ds)
{
	mutex_lock(&dsa2_mutex);
873
	dsa_switch_remove(ds);
874 875 876
	mutex_unlock(&dsa2_mutex);
}
EXPORT_SYMBOL_GPL(dsa_unregister_switch);