diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2019-10-15 11:38:39 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-10-16 14:31:59 -0400 |
commit | 2203cbf2c8b58a1e3bef98c47531d431d11639a0 (patch) | |
tree | 8544a418bac77532ba981c965c76f11349847aa8 | |
parent | 9370f2d05a2a150b0aa719a3070b26d478180df3 (diff) | |
download | linux-2203cbf2c8b58a1e3bef98c47531d431d11639a0.tar.bz2 |
net: sfp: move fwnode parsing into sfp-bus layer
Rather than parsing the sfp firmware node in phylink, parse it in the
sfp-bus code, so we can re-use this code for PHYs without having to
duplicate the parsing.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/phylink.c | 21 | ||||
-rw-r--r-- | drivers/net/phy/sfp-bus.c | 65 | ||||
-rw-r--r-- | include/linux/sfp.h | 10 |
3 files changed, 53 insertions, 43 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 8e53ed90da3c..4c5e8b4f8d80 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -548,26 +548,17 @@ static const struct sfp_upstream_ops sfp_phylink_ops; static int phylink_register_sfp(struct phylink *pl, struct fwnode_handle *fwnode) { - struct fwnode_reference_args ref; + struct sfp_bus *bus; int ret; - if (!fwnode) - return 0; - - ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL, - 0, 0, &ref); - if (ret < 0) { - if (ret == -ENOENT) - return 0; - - phylink_err(pl, "unable to parse \"sfp\" node: %d\n", - ret); + bus = sfp_register_upstream_node(fwnode, pl, &sfp_phylink_ops); + if (IS_ERR(bus)) { + ret = PTR_ERR(bus); + phylink_err(pl, "unable to attach SFP bus: %d\n", ret); return ret; } - pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl, &sfp_phylink_ops); - if (!pl->sfp_bus) - return -ENOMEM; + pl->sfp_bus = bus; return 0; } diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index b23fc41896ef..d037aab6a71d 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -4,6 +4,7 @@ #include <linux/list.h> #include <linux/mutex.h> #include <linux/phylink.h> +#include <linux/property.h> #include <linux/rtnetlink.h> #include <linux/slab.h> @@ -445,45 +446,63 @@ static void sfp_upstream_clear(struct sfp_bus *bus) } /** - * sfp_register_upstream() - Register the neighbouring device - * @fwnode: firmware node for the SFP bus + * sfp_register_upstream_node() - parse and register the neighbouring device + * @fwnode: firmware node for the parent device (MAC or PHY) * @upstream: the upstream private data * @ops: the upstream's &struct sfp_upstream_ops * - * Register the upstream device (eg, PHY) with the SFP bus. MAC drivers - * should use phylink, which will call this function for them. Returns - * a pointer to the allocated &struct sfp_bus. + * Parse the parent device's firmware node for a SFP bus, and register the + * SFP bus using sfp_register_upstream(). * - * On error, returns %NULL. + * Returns: on success, a pointer to the sfp_bus structure, + * %NULL if no SFP is specified, + * on failure, an error pointer value: + * corresponding to the errors detailed for + * fwnode_property_get_reference_args(). + * %-ENOMEM if we failed to allocate the bus. + * an error from the upstream's connect_phy() method. */ -struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode, - void *upstream, - const struct sfp_upstream_ops *ops) +struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode, + void *upstream, + const struct sfp_upstream_ops *ops) { - struct sfp_bus *bus = sfp_bus_get(fwnode); - int ret = 0; + struct fwnode_reference_args ref; + struct sfp_bus *bus; + int ret; - if (bus) { - rtnl_lock(); - bus->upstream_ops = ops; - bus->upstream = upstream; + ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL, + 0, 0, &ref); + if (ret == -ENOENT) + return NULL; + else if (ret < 0) + return ERR_PTR(ret); - if (bus->sfp) { - ret = sfp_register_bus(bus); - if (ret) - sfp_upstream_clear(bus); - } - rtnl_unlock(); + bus = sfp_bus_get(ref.fwnode); + fwnode_handle_put(ref.fwnode); + if (!bus) + return ERR_PTR(-ENOMEM); + + rtnl_lock(); + bus->upstream_ops = ops; + bus->upstream = upstream; + + if (bus->sfp) { + ret = sfp_register_bus(bus); + if (ret) + sfp_upstream_clear(bus); + } else { + ret = 0; } + rtnl_unlock(); if (ret) { sfp_bus_put(bus); - bus = NULL; + bus = ERR_PTR(ret); } return bus; } -EXPORT_SYMBOL_GPL(sfp_register_upstream); +EXPORT_SYMBOL_GPL(sfp_register_upstream_node); /** * sfp_unregister_upstream() - Unregister sfp bus diff --git a/include/linux/sfp.h b/include/linux/sfp.h index 1c35428e98bc..355a08a76fd4 100644 --- a/include/linux/sfp.h +++ b/include/linux/sfp.h @@ -508,9 +508,9 @@ int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, u8 *data); void sfp_upstream_start(struct sfp_bus *bus); void sfp_upstream_stop(struct sfp_bus *bus); -struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode, - void *upstream, - const struct sfp_upstream_ops *ops); +struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode, + void *upstream, + const struct sfp_upstream_ops *ops); void sfp_unregister_upstream(struct sfp_bus *bus); #else static inline int sfp_parse_port(struct sfp_bus *bus, @@ -553,11 +553,11 @@ static inline void sfp_upstream_stop(struct sfp_bus *bus) { } -static inline struct sfp_bus *sfp_register_upstream( +static inline struct sfp_bus *sfp_register_upstream_node( struct fwnode_handle *fwnode, void *upstream, const struct sfp_upstream_ops *ops) { - return (struct sfp_bus *)-1; + return NULL; } static inline void sfp_unregister_upstream(struct sfp_bus *bus) |