| From 4054955f0da08c81d42220cb445820d474f1ac92 Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Sat, 14 Sep 2019 14:21:22 +0100 |
| Subject: [PATCH 614/660] 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> |
| --- |
| drivers/net/phy/phylink.c | 21 ++++--------- |
| drivers/net/phy/sfp-bus.c | 65 +++++++++++++++++++++++++-------------- |
| include/linux/sfp.h | 10 +++--- |
| 3 files changed, 53 insertions(+), 43 deletions(-) |
| |
| --- a/drivers/net/phy/phylink.c |
| +++ b/drivers/net/phy/phylink.c |
| @@ -565,31 +565,17 @@ static const struct sfp_upstream_ops sfp |
| 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; |
| } |
| |
| - if (!fwnode_device_is_available(ref.fwnode)) { |
| - fwnode_handle_put(ref.fwnode); |
| - return 0; |
| - } |
| - |
| - pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl, &sfp_phylink_ops); |
| - if (!pl->sfp_bus) |
| - return -ENOMEM; |
| + pl->sfp_bus = bus; |
| |
| return 0; |
| } |
| --- 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> |
| |
| @@ -520,45 +521,68 @@ static void sfp_upstream_clear(struct sf |
| } |
| |
| /** |
| - * 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 *bus = sfp_bus_get(fwnode); |
| - int ret = 0; |
| - |
| - if (bus) { |
| - rtnl_lock(); |
| - bus->upstream_ops = ops; |
| - bus->upstream = upstream; |
| +struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode, |
| + void *upstream, |
| + const struct sfp_upstream_ops *ops) |
| +{ |
| + struct fwnode_reference_args ref; |
| + struct sfp_bus *bus; |
| + int ret; |
| |
| - if (bus->sfp) { |
| - ret = sfp_register_bus(bus); |
| - if (ret) |
| - sfp_upstream_clear(bus); |
| - } |
| - rtnl_unlock(); |
| + 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 (!fwnode_device_is_available(ref.fwnode)) { |
| + fwnode_handle_put(ref.fwnode); |
| + return NULL; |
| + } |
| + |
| + 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 |
| --- a/include/linux/sfp.h |
| +++ b/include/linux/sfp.h |
| @@ -508,9 +508,9 @@ int sfp_get_module_eeprom(struct sfp_bus |
| 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(str |
| { |
| } |
| |
| -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) |