diff options
-rw-r--r-- | net/dsa/dsa2.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 3b5f434cad3f..b70befe8a3c8 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c | |||
@@ -261,7 +261,7 @@ static int dsa_port_setup(struct dsa_port *dp) | |||
261 | enum devlink_port_flavour flavour; | 261 | enum devlink_port_flavour flavour; |
262 | struct dsa_switch *ds = dp->ds; | 262 | struct dsa_switch *ds = dp->ds; |
263 | struct dsa_switch_tree *dst = ds->dst; | 263 | struct dsa_switch_tree *dst = ds->dst; |
264 | int err; | 264 | int err = 0; |
265 | 265 | ||
266 | if (dp->type == DSA_PORT_TYPE_UNUSED) | 266 | if (dp->type == DSA_PORT_TYPE_UNUSED) |
267 | return 0; | 267 | return 0; |
@@ -299,19 +299,15 @@ static int dsa_port_setup(struct dsa_port *dp) | |||
299 | break; | 299 | break; |
300 | case DSA_PORT_TYPE_CPU: | 300 | case DSA_PORT_TYPE_CPU: |
301 | err = dsa_port_link_register_of(dp); | 301 | err = dsa_port_link_register_of(dp); |
302 | if (err) { | 302 | if (err) |
303 | dev_err(ds->dev, "failed to setup link for port %d.%d\n", | 303 | dev_err(ds->dev, "failed to setup link for port %d.%d\n", |
304 | ds->index, dp->index); | 304 | ds->index, dp->index); |
305 | return err; | ||
306 | } | ||
307 | break; | 305 | break; |
308 | case DSA_PORT_TYPE_DSA: | 306 | case DSA_PORT_TYPE_DSA: |
309 | err = dsa_port_link_register_of(dp); | 307 | err = dsa_port_link_register_of(dp); |
310 | if (err) { | 308 | if (err) |
311 | dev_err(ds->dev, "failed to setup link for port %d.%d\n", | 309 | dev_err(ds->dev, "failed to setup link for port %d.%d\n", |
312 | ds->index, dp->index); | 310 | ds->index, dp->index); |
313 | return err; | ||
314 | } | ||
315 | break; | 311 | break; |
316 | case DSA_PORT_TYPE_USER: | 312 | case DSA_PORT_TYPE_USER: |
317 | err = dsa_slave_create(dp); | 313 | err = dsa_slave_create(dp); |
@@ -323,7 +319,10 @@ static int dsa_port_setup(struct dsa_port *dp) | |||
323 | break; | 319 | break; |
324 | } | 320 | } |
325 | 321 | ||
326 | return 0; | 322 | if (err) |
323 | devlink_port_unregister(&dp->devlink_port); | ||
324 | |||
325 | return err; | ||
327 | } | 326 | } |
328 | 327 | ||
329 | static void dsa_port_teardown(struct dsa_port *dp) | 328 | static void dsa_port_teardown(struct dsa_port *dp) |
@@ -351,7 +350,7 @@ static void dsa_port_teardown(struct dsa_port *dp) | |||
351 | 350 | ||
352 | static int dsa_switch_setup(struct dsa_switch *ds) | 351 | static int dsa_switch_setup(struct dsa_switch *ds) |
353 | { | 352 | { |
354 | int err; | 353 | int err = 0; |
355 | 354 | ||
356 | /* Initialize ds->phys_mii_mask before registering the slave MDIO bus | 355 | /* Initialize ds->phys_mii_mask before registering the slave MDIO bus |
357 | * driver and before ops->setup() has run, since the switch drivers and | 356 | * driver and before ops->setup() has run, since the switch drivers and |
@@ -369,29 +368,41 @@ static int dsa_switch_setup(struct dsa_switch *ds) | |||
369 | 368 | ||
370 | err = devlink_register(ds->devlink, ds->dev); | 369 | err = devlink_register(ds->devlink, ds->dev); |
371 | if (err) | 370 | if (err) |
372 | return err; | 371 | goto free_devlink; |
373 | 372 | ||
374 | err = dsa_switch_register_notifier(ds); | 373 | err = dsa_switch_register_notifier(ds); |
375 | if (err) | 374 | if (err) |
376 | return err; | 375 | goto unregister_devlink; |
377 | 376 | ||
378 | err = ds->ops->setup(ds); | 377 | err = ds->ops->setup(ds); |
379 | if (err < 0) | 378 | if (err < 0) |
380 | return err; | 379 | goto unregister_notifier; |
381 | 380 | ||
382 | if (!ds->slave_mii_bus && ds->ops->phy_read) { | 381 | if (!ds->slave_mii_bus && ds->ops->phy_read) { |
383 | ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); | 382 | ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); |
384 | if (!ds->slave_mii_bus) | 383 | if (!ds->slave_mii_bus) { |
385 | return -ENOMEM; | 384 | err = -ENOMEM; |
385 | goto unregister_notifier; | ||
386 | } | ||
386 | 387 | ||
387 | dsa_slave_mii_bus_init(ds); | 388 | dsa_slave_mii_bus_init(ds); |
388 | 389 | ||
389 | err = mdiobus_register(ds->slave_mii_bus); | 390 | err = mdiobus_register(ds->slave_mii_bus); |
390 | if (err < 0) | 391 | if (err < 0) |
391 | return err; | 392 | goto unregister_notifier; |
392 | } | 393 | } |
393 | 394 | ||
394 | return 0; | 395 | return 0; |
396 | |||
397 | unregister_notifier: | ||
398 | dsa_switch_unregister_notifier(ds); | ||
399 | unregister_devlink: | ||
400 | devlink_unregister(ds->devlink); | ||
401 | free_devlink: | ||
402 | devlink_free(ds->devlink); | ||
403 | ds->devlink = NULL; | ||
404 | |||
405 | return err; | ||
395 | } | 406 | } |
396 | 407 | ||
397 | static void dsa_switch_teardown(struct dsa_switch *ds) | 408 | static void dsa_switch_teardown(struct dsa_switch *ds) |
@@ -413,8 +424,8 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) | |||
413 | { | 424 | { |
414 | struct dsa_switch *ds; | 425 | struct dsa_switch *ds; |
415 | struct dsa_port *dp; | 426 | struct dsa_port *dp; |
416 | int device, port; | 427 | int device, port, i; |
417 | int err; | 428 | int err = 0; |
418 | 429 | ||
419 | for (device = 0; device < DSA_MAX_SWITCHES; device++) { | 430 | for (device = 0; device < DSA_MAX_SWITCHES; device++) { |
420 | ds = dst->ds[device]; | 431 | ds = dst->ds[device]; |
@@ -423,18 +434,41 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) | |||
423 | 434 | ||
424 | err = dsa_switch_setup(ds); | 435 | err = dsa_switch_setup(ds); |
425 | if (err) | 436 | if (err) |
426 | return err; | 437 | goto switch_teardown; |
427 | 438 | ||
428 | for (port = 0; port < ds->num_ports; port++) { | 439 | for (port = 0; port < ds->num_ports; port++) { |
429 | dp = &ds->ports[port]; | 440 | dp = &ds->ports[port]; |
430 | 441 | ||
431 | err = dsa_port_setup(dp); | 442 | err = dsa_port_setup(dp); |
432 | if (err) | 443 | if (err) |
433 | return err; | 444 | goto ports_teardown; |
434 | } | 445 | } |
435 | } | 446 | } |
436 | 447 | ||
437 | return 0; | 448 | return 0; |
449 | |||
450 | ports_teardown: | ||
451 | for (i = 0; i < port; i++) | ||
452 | dsa_port_teardown(&ds->ports[i]); | ||
453 | |||
454 | dsa_switch_teardown(ds); | ||
455 | |||
456 | switch_teardown: | ||
457 | for (i = 0; i < device; i++) { | ||
458 | ds = dst->ds[i]; | ||
459 | if (!ds) | ||
460 | continue; | ||
461 | |||
462 | for (port = 0; port < ds->num_ports; port++) { | ||
463 | dp = &ds->ports[port]; | ||
464 | |||
465 | dsa_port_teardown(dp); | ||
466 | } | ||
467 | |||
468 | dsa_switch_teardown(ds); | ||
469 | } | ||
470 | |||
471 | return err; | ||
438 | } | 472 | } |
439 | 473 | ||
440 | static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst) | 474 | static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst) |
@@ -496,17 +530,24 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) | |||
496 | 530 | ||
497 | err = dsa_tree_setup_switches(dst); | 531 | err = dsa_tree_setup_switches(dst); |
498 | if (err) | 532 | if (err) |
499 | return err; | 533 | goto teardown_default_cpu; |
500 | 534 | ||
501 | err = dsa_tree_setup_master(dst); | 535 | err = dsa_tree_setup_master(dst); |
502 | if (err) | 536 | if (err) |
503 | return err; | 537 | goto teardown_switches; |
504 | 538 | ||
505 | dst->setup = true; | 539 | dst->setup = true; |
506 | 540 | ||
507 | pr_info("DSA: tree %d setup\n", dst->index); | 541 | pr_info("DSA: tree %d setup\n", dst->index); |
508 | 542 | ||
509 | return 0; | 543 | return 0; |
544 | |||
545 | teardown_switches: | ||
546 | dsa_tree_teardown_switches(dst); | ||
547 | teardown_default_cpu: | ||
548 | dsa_tree_teardown_default_cpu(dst); | ||
549 | |||
550 | return err; | ||
510 | } | 551 | } |
511 | 552 | ||
512 | static void dsa_tree_teardown(struct dsa_switch_tree *dst) | 553 | static void dsa_tree_teardown(struct dsa_switch_tree *dst) |
@@ -547,8 +588,10 @@ static int dsa_tree_add_switch(struct dsa_switch_tree *dst, | |||
547 | dst->ds[index] = ds; | 588 | dst->ds[index] = ds; |
548 | 589 | ||
549 | err = dsa_tree_setup(dst); | 590 | err = dsa_tree_setup(dst); |
550 | if (err) | 591 | if (err) { |
551 | dsa_tree_remove_switch(dst, index); | 592 | dst->ds[index] = NULL; |
593 | dsa_tree_put(dst); | ||
594 | } | ||
552 | 595 | ||
553 | return err; | 596 | return err; |
554 | } | 597 | } |