|
4 | 4 | #include <linux/list.h> |
5 | 5 | #include <linux/mutex.h> |
6 | 6 | #include <linux/phylink.h> |
| 7 | +#include <linux/property.h> |
7 | 8 | #include <linux/rtnetlink.h> |
8 | 9 | #include <linux/slab.h> |
9 | 10 |
|
@@ -445,45 +446,63 @@ static void sfp_upstream_clear(struct sfp_bus *bus) |
445 | 446 | } |
446 | 447 |
|
447 | 448 | /** |
448 | | - * sfp_register_upstream() - Register the neighbouring device |
449 | | - * @fwnode: firmware node for the SFP bus |
| 449 | + * sfp_register_upstream_node() - parse and register the neighbouring device |
| 450 | + * @fwnode: firmware node for the parent device (MAC or PHY) |
450 | 451 | * @upstream: the upstream private data |
451 | 452 | * @ops: the upstream's &struct sfp_upstream_ops |
452 | 453 | * |
453 | | - * Register the upstream device (eg, PHY) with the SFP bus. MAC drivers |
454 | | - * should use phylink, which will call this function for them. Returns |
455 | | - * a pointer to the allocated &struct sfp_bus. |
| 454 | + * Parse the parent device's firmware node for a SFP bus, and register the |
| 455 | + * SFP bus using sfp_register_upstream(). |
456 | 456 | * |
457 | | - * On error, returns %NULL. |
| 457 | + * Returns: on success, a pointer to the sfp_bus structure, |
| 458 | + * %NULL if no SFP is specified, |
| 459 | + * on failure, an error pointer value: |
| 460 | + * corresponding to the errors detailed for |
| 461 | + * fwnode_property_get_reference_args(). |
| 462 | + * %-ENOMEM if we failed to allocate the bus. |
| 463 | + * an error from the upstream's connect_phy() method. |
458 | 464 | */ |
459 | | -struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode, |
460 | | - void *upstream, |
461 | | - const struct sfp_upstream_ops *ops) |
| 465 | +struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode, |
| 466 | + void *upstream, |
| 467 | + const struct sfp_upstream_ops *ops) |
462 | 468 | { |
463 | | - struct sfp_bus *bus = sfp_bus_get(fwnode); |
464 | | - int ret = 0; |
| 469 | + struct fwnode_reference_args ref; |
| 470 | + struct sfp_bus *bus; |
| 471 | + int ret; |
465 | 472 |
|
466 | | - if (bus) { |
467 | | - rtnl_lock(); |
468 | | - bus->upstream_ops = ops; |
469 | | - bus->upstream = upstream; |
| 473 | + ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL, |
| 474 | + 0, 0, &ref); |
| 475 | + if (ret == -ENOENT) |
| 476 | + return NULL; |
| 477 | + else if (ret < 0) |
| 478 | + return ERR_PTR(ret); |
470 | 479 |
|
471 | | - if (bus->sfp) { |
472 | | - ret = sfp_register_bus(bus); |
473 | | - if (ret) |
474 | | - sfp_upstream_clear(bus); |
475 | | - } |
476 | | - rtnl_unlock(); |
| 480 | + bus = sfp_bus_get(ref.fwnode); |
| 481 | + fwnode_handle_put(ref.fwnode); |
| 482 | + if (!bus) |
| 483 | + return ERR_PTR(-ENOMEM); |
| 484 | + |
| 485 | + rtnl_lock(); |
| 486 | + bus->upstream_ops = ops; |
| 487 | + bus->upstream = upstream; |
| 488 | + |
| 489 | + if (bus->sfp) { |
| 490 | + ret = sfp_register_bus(bus); |
| 491 | + if (ret) |
| 492 | + sfp_upstream_clear(bus); |
| 493 | + } else { |
| 494 | + ret = 0; |
477 | 495 | } |
| 496 | + rtnl_unlock(); |
478 | 497 |
|
479 | 498 | if (ret) { |
480 | 499 | sfp_bus_put(bus); |
481 | | - bus = NULL; |
| 500 | + bus = ERR_PTR(ret); |
482 | 501 | } |
483 | 502 |
|
484 | 503 | return bus; |
485 | 504 | } |
486 | | -EXPORT_SYMBOL_GPL(sfp_register_upstream); |
| 505 | +EXPORT_SYMBOL_GPL(sfp_register_upstream_node); |
487 | 506 |
|
488 | 507 | /** |
489 | 508 | * sfp_unregister_upstream() - Unregister sfp bus |
|
0 commit comments