Skip to contentSkip to conversation

SFP/phylink fixes

PATCH In review Russell King - ARM Linux 4 participants 28 messages Nov 30, 2017 – Dec 5, 2017

Subsystems (5)
lore
Share & tools
lore

Russell King - ARM Linux

author maintainer
#0 lore raw

cover SFP/phylink fixes

Hi,

Here are four phylink fixes:
- the "options" is a big-endian value, we must test the bits taking the endian-ness into account.
- improve the handling of RX_LOS polarity, taking no RX_LOS polarity bits set to mean there is no RX_LOS functionality provided.
- do not report modules that require the address mode switching as supporting SFF8472.
- ensure that the mac_link_down() function is called when phylink_stop() is called.

 drivers/net/phy/phylink.c |  1 +
 drivers/net/phy/sfp.c     | 41 ++++++++++++++++++++++++++++++-----------
 2 files changed, 31 insertions(+), 11 deletions(-)
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
author maintainer
#1 lore raw

cover SFP/phylink updates

Hi,

This series, which follows on from the fixes posted earlier, improves the phylink/sfp support. Changes included here are:

- Merge 802.3z and SGMII modes into one "in-band" mode, using the PHY_INTERFACE_MODE_xxx definition to determine which should be used. This allows more flexibility as more interface modes become available.

- Allow 2500base-X and 10GBASE-KR to be requested from SFP.

- Remove unused and unnecessary phylink_init_eee()

- Restart 802.3z autonegotiation when starting the network device to ensure that the negotiated parameters are always correct. It has been observed on mvneta that this is not always the case without this change.

- Add kerneldoc documentation for phylink and sfp upstream facing APIs and link it in to the networking documentation.

- Resolve a sparse warning in sfp-bus.c

- Convert phylink/sfp to use fwnode rather than DT so that other firmware systems can take advantage of this - I have received a request for it to be usable with ACPI. The exception to this is our interactions with phylib, as phylib itself does not yet support fwnode.

 Documentation/networking/kapi.rst |  24 +++
 drivers/net/phy/phylink.c         | 341 +++++++++++++++++++++++++++++---------
 drivers/net/phy/sfp-bus.c         | 120 +++++++++++++-
 include/linux/phy.h               |  14 ++
 include/linux/phylink.h           | 196 +++++++++++++++-------
 include/linux/sfp.h               |  57 +++++--
 6 files changed, 591 insertions(+), 161 deletions(-)
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
#2 lore raw

PATCH 1/11 phy: add phy_interface_mode_is_8023z() helper

Add and use phy_interface_mode_is_8023z() helper to identify the interface modes that use 802.3z negotiation. Use it in phylink's phylink_mac_an_restart().

---
 drivers/net/phy/phylink.c |  3 +--
 include/linux/phy.h       | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
drivers/net/phy/phylink.c +1 -2
index 5dc9668dde34..a02d67689d6e 100644
@@ -320,8 +320,7 @@ static void phylink_mac_config(struct phylink *pl,
 static void phylink_mac_an_restart(struct phylink *pl)
 {
 	if (pl->link_config.an_enabled &&
-	    (pl->link_config.interface == PHY_INTERFACE_MODE_1000BASEX ||
-	     pl->link_config.interface == PHY_INTERFACE_MODE_2500BASEX))
+	    phy_interface_mode_is_8023z(pl->link_config.interface))
 		pl->ops->mac_an_restart(pl->netdev);
 }
 
include/linux/phy.h +14 -0
index dc82a07cb4fd..71d777fe6c3d 100644
@@ -763,6 +763,20 @@ static inline bool phy_interface_mode_is_rgmii(phy_interface_t mode)
 };
 
 /**
+ * phy_interface_mode_is_8023z() - does the phy interface mode use 802.3z
+ *   negotiation
+ * @mode: one of &enum phy_interface_t
+ *
+ * Returns true if the phy interface mode uses the 16-bit negotiation
+ * word as defined in 802.3z. (See 802.3-2015 37.2.1 Config_Reg encoding)
+ */
+static inline bool phy_interface_mode_is_8023z(phy_interface_t mode)
+{
+	return mode == PHY_INTERFACE_MODE_1000BASEX ||
+	       mode == PHY_INTERFACE_MODE_2500BASEX;
+}
+
+/**
  * phy_interface_is_rgmii - Convenience function for testing if a PHY interface
  * is RGMII (all variants)
  * @phydev: the phy_device struct
Signature · 1 line
2.7.4
#4 lore raw

PATCH 2/11 phylink: merge SGMII and 802.3z handling

In reply to Russell King - ARM Linux

The code handling SGMII and 802.3z is essentially the same, except that we assume 802.3z has no PHY. Re-organise the code such that these cases are merged, and exclude 802.3z mode from having a PHY attached. This results in the same link handling behaviour as before.

---
 drivers/net/phy/phylink.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/net/phy/phylink.c +9 -7
index a02d67689d6e..d7006fdc8f71 100644
@@ -423,6 +423,7 @@ static void phylink_resolve(struct work_struct *w)
 			break;
 
 		case MLO_AN_SGMII:
+		case MLO_AN_8023Z:
 			phylink_get_mac_state(pl, &link_state);
 			if (pl->phydev) {
 				bool changed = false;
@@ -448,10 +449,6 @@ static void phylink_resolve(struct work_struct *w)
 				}
 			}
 			break;
-
-		case MLO_AN_8023Z:
-			phylink_get_mac_state(pl, &link_state);
-			break;
 		}
 	}
 
@@ -656,6 +653,10 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
 {
 	int ret;
 
+	if (WARN_ON(pl->link_an_mode == MLO_AN_FIXED ||
+		    pl->link_an_mode == MLO_AN_8023Z))
+		return -EINVAL;
+
 	ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface);
 	if (ret)
 		return ret;
@@ -674,8 +675,9 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
 	struct phy_device *phy_dev;
 	int ret;
 
-	/* Fixed links are handled without needing a PHY */
-	if (pl->link_an_mode == MLO_AN_FIXED)
+	/* Fixed links and 802.3z are handled without needing a PHY */
+	if (pl->link_an_mode == MLO_AN_FIXED ||
+	    pl->link_an_mode == MLO_AN_8023Z)
 		return 0;
 
 	phy_node = of_parse_phandle(dn, "phy-handle", 0);
@@ -850,13 +852,13 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
 		break;
 
 	case MLO_AN_SGMII:
+	case MLO_AN_8023Z:
 		/* If there is a phy attached, then use the reported
 		 * settings from the phy with no modification.
 		 */
 		if (pl->phydev)
 			break;
 
-	case MLO_AN_8023Z:
 		phylink_get_mac_state(pl, &link_state);
 
 		/* The MAC is reporting the link results from its own PCS
Signature · 1 line
2.7.4
Reviewed-by on v1 2/11
#5 lore raw

Re: [PATCH 02/11] phylink: merge SGMII and 802.3z handling

Quoted 6 lines · Russell King

The code handling SGMII and 802.3z is essentially the same, except that we assume 802.3z has no PHY. Re-organise the code such that these cases are merged, and exclude 802.3z mode from having a PHY attached. This results in the same link handling behaviour as before.

Signature · 1 line
Florian
#6 lore raw

PATCH 3/11 phylink: get rid of separate Cisco SGMII and 802.3z modes

In reply to Russell King - ARM Linux

Since the handling of SGMII and 802.3z is now the same, combine the MLO_AN_xxx constants into a single MLO_AN_INBAND, and use the PHY interface mode to distinguish between Cisco SGMII and 802.3z.

---
 drivers/net/phy/phylink.c | 39 ++++++++++++++-------------------------
 include/linux/phylink.h   | 19 +++++++------------
 2 files changed, 21 insertions(+), 37 deletions(-)
drivers/net/phy/phylink.c +14 -25
index d7006fdc8f71..34ecdb892f57 100644
@@ -117,8 +117,7 @@ static const char *phylink_an_mode_str(unsigned int mode)
 	static const char *modestr[] = {
 		[MLO_AN_PHY] = "phy",
 		[MLO_AN_FIXED] = "fixed",
-		[MLO_AN_SGMII] = "SGMII",
-		[MLO_AN_8023Z] = "802.3z",
+		[MLO_AN_INBAND] = "inband",
 	};
 
 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
@@ -244,6 +243,7 @@ static int phylink_parse_mode(struct phylink *pl, struct device_node *np)
 		phylink_set(pl->supported, Asym_Pause);
 		phylink_set(pl->supported, Pause);
 		pl->link_config.an_enabled = true;
+		pl->link_an_mode = MLO_AN_INBAND;
 
 		switch (pl->link_config.interface) {
 		case PHY_INTERFACE_MODE_SGMII:
@@ -253,17 +253,14 @@ static int phylink_parse_mode(struct phylink *pl, struct device_node *np)
 			phylink_set(pl->supported, 100baseT_Full);
 			phylink_set(pl->supported, 1000baseT_Half);
 			phylink_set(pl->supported, 1000baseT_Full);
-			pl->link_an_mode = MLO_AN_SGMII;
 			break;
 
 		case PHY_INTERFACE_MODE_1000BASEX:
 			phylink_set(pl->supported, 1000baseX_Full);
-			pl->link_an_mode = MLO_AN_8023Z;
 			break;
 
 		case PHY_INTERFACE_MODE_2500BASEX:
 			phylink_set(pl->supported, 2500baseX_Full);
-			pl->link_an_mode = MLO_AN_8023Z;
 			break;
 
 		case PHY_INTERFACE_MODE_10GKR:
@@ -280,7 +277,6 @@ static int phylink_parse_mode(struct phylink *pl, struct device_node *np)
 			phylink_set(pl->supported, 10000baseLR_Full);
 			phylink_set(pl->supported, 10000baseLRM_Full);
 			phylink_set(pl->supported, 10000baseER_Full);
-			pl->link_an_mode = MLO_AN_SGMII;
 			break;
 
 		default:
@@ -422,8 +418,7 @@ static void phylink_resolve(struct work_struct *w)
 			phylink_mac_config(pl, &link_state);
 			break;
 
-		case MLO_AN_SGMII:
-		case MLO_AN_8023Z:
+		case MLO_AN_INBAND:
 			phylink_get_mac_state(pl, &link_state);
 			if (pl->phydev) {
 				bool changed = false;
@@ -654,7 +649,8 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
 	int ret;
 
 	if (WARN_ON(pl->link_an_mode == MLO_AN_FIXED ||
-		    pl->link_an_mode == MLO_AN_8023Z))
+		    (pl->link_an_mode == MLO_AN_INBAND &&
+		     phy_interface_mode_is_8023z(pl->link_interface))))
 		return -EINVAL;
 
 	ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface);
@@ -677,7 +673,8 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
 
 	/* Fixed links and 802.3z are handled without needing a PHY */
 	if (pl->link_an_mode == MLO_AN_FIXED ||
-	    pl->link_an_mode == MLO_AN_8023Z)
+	    (pl->link_an_mode == MLO_AN_INBAND &&
+	     phy_interface_mode_is_8023z(pl->link_interface)))
 		return 0;
 
 	phy_node = of_parse_phandle(dn, "phy-handle", 0);
@@ -851,8 +848,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
 		phylink_get_ksettings(&link_state, kset);
 		break;
 
-	case MLO_AN_SGMII:
-	case MLO_AN_8023Z:
+	case MLO_AN_INBAND:
 		/* If there is a phy attached, then use the reported
 		 * settings from the phy with no modification.
 		 */
@@ -1029,8 +1025,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
 			phylink_mac_config(pl, config);
 			break;
 
-		case MLO_AN_SGMII:
-		case MLO_AN_8023Z:
+		case MLO_AN_INBAND:
 			phylink_mac_config(pl, config);
 			phylink_mac_an_restart(pl);
 			break;
@@ -1247,9 +1242,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
 	case MLO_AN_PHY:
 		return -EOPNOTSUPP;
 
-	case MLO_AN_SGMII:
-		/* No phy, fall through to 8023z method */
-	case MLO_AN_8023Z:
+	case MLO_AN_INBAND:
 		if (phy_id == 0) {
 			val = phylink_get_mac_state(pl, &state);
 			if (val < 0)
@@ -1274,9 +1267,7 @@ static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
 	case MLO_AN_PHY:
 		return -EOPNOTSUPP;
 
-	case MLO_AN_SGMII:
-		/* No phy, fall through to 8023z method */
-	case MLO_AN_8023Z:
+	case MLO_AN_INBAND:
 		break;
 	}
 
@@ -1291,7 +1282,7 @@ int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd)
 	WARN_ON(!lockdep_rtnl_is_held());
 
 	if (pl->phydev) {
-		/* PHYs only exist for MLO_AN_PHY and MLO_AN_SGMII */
+		/* PHYs only exist for MLO_AN_PHY and SGMII */
 		switch (cmd) {
 		case SIOCGMIIPHY:
 			mii->phy_id = pl->phydev->mdio.addr;
@@ -1360,10 +1351,8 @@ static int phylink_sfp_module_insert(void *upstream,
 
 	switch (iface) {
 	case PHY_INTERFACE_MODE_SGMII:
-		mode = MLO_AN_SGMII;
-		break;
 	case PHY_INTERFACE_MODE_1000BASEX:
-		mode = MLO_AN_8023Z;
+		mode = MLO_AN_INBAND;
 		break;
 	default:
 		return -EINVAL;
@@ -1390,7 +1379,7 @@ static int phylink_sfp_module_insert(void *upstream,
 		   phylink_an_mode_str(mode), phy_modes(config.interface),
 		   __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 
-	if (mode == MLO_AN_8023Z && pl->phydev)
+	if (phy_interface_mode_is_8023z(iface) && pl->phydev)
 		return -EINVAL;
 
 	changed = !bitmap_equal(pl->supported, support,
include/linux/phylink.h +7 -12
index af67edd4ae38..cab22ad3bd6f 100644
@@ -20,13 +20,12 @@ enum {
 
 	MLO_AN_PHY = 0,	/* Conventional PHY */
 	MLO_AN_FIXED,	/* Fixed-link mode */
-	MLO_AN_SGMII,	/* Cisco SGMII protocol */
-	MLO_AN_8023Z,	/* 1000base-X protocol */
+	MLO_AN_INBAND,	/* In-band protocol */
 };
 
 static inline bool phylink_autoneg_inband(unsigned int mode)
 {
-	return mode == MLO_AN_SGMII || mode == MLO_AN_8023Z;
+	return mode == MLO_AN_INBAND;
 }
 
 struct phylink_link_state {
@@ -69,7 +68,7 @@ struct phylink_mac_ops {
 	/**
 	 * mac_config: configure the MAC for the selected mode and state
 	 * @ndev: net_device structure for the MAC
-	 * @mode: one of MLO_AN_FIXED, MLO_AN_PHY, MLO_AN_8023Z, MLO_AN_SGMII
+	 * @mode: one of MLO_AN_FIXED, MLO_AN_PHY, MLO_AN_INBAND
 	 * @state: state structure
 	 *
 	 * The action performed depends on the currently selected mode:
@@ -77,14 +76,10 @@ struct phylink_mac_ops {
 	 * %MLO_AN_FIXED, %MLO_AN_PHY:
 	 *   set the specified speed, duplex, pause mode, and phy interface
 	 *   mode in the provided @state.
-	 * %MLO_AN_8023Z:
-	 *   place the link in 1000base-X mode, advertising the parameters
-	 *   given in advertising in @state.
-	 * %MLO_AN_SGMII:
-	 *   place the link in Cisco SGMII mode - there is no advertisment
-	 *   to make as the PHY communicates the speed and duplex to the
-	 *   MAC over the in-band control word.  Configuration of the pause
-	 *   mode is as per MLO_AN_PHY since this is not included.
+	 * %MLO_AN_INBAND:
+	 *   place the link in an inband negotiation mode (such as
+	 *   1000base-X or Cisco SGMII mode depending on the phy interface
+	 *   mode), advertising the parameters given in advertising in @state.
 	 */
 	void (*mac_config)(struct net_device *ndev, unsigned int mode,
 			   const struct phylink_link_state *state);
Signature · 1 line
2.7.4
Reviewed-by on v1 3/11
#7 lore raw

Re: [PATCH 03/11] phylink: get rid of separate Cisco SGMII and 802.3z modes

Quoted 5 lines · Russell King

Since the handling of SGMII and 802.3z is now the same, combine the MLO_AN_xxx constants into a single MLO_AN_INBAND, and use the PHY interface mode to distinguish between Cisco SGMII and 802.3z.

Signature · 1 line
Florian
#8 lore raw

PATCH 4/11 phylink: add support for 2500baseX and 10GbaseKR

In reply to Russell King - ARM Linux

Add support for handling the faster 2.5G and 10G link modes when used with SFP modules.

---
 drivers/net/phy/phylink.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/phy/phylink.c +2 -0
index 34ecdb892f57..06c6ad0603ac 100644
@@ -1352,6 +1352,8 @@ static int phylink_sfp_module_insert(void *upstream,
 	switch (iface) {
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_1000BASEX:
+	case PHY_INTERFACE_MODE_2500BASEX:
+	case PHY_INTERFACE_MODE_10GKR:
 		mode = MLO_AN_INBAND;
 		break;
 	default:
Signature · 1 line
2.7.4
#10 lore raw

PATCH 5/11 phylink: remove phylink_init_eee()

In reply to Russell King - ARM Linux

phylink_init_eee() serves no purpose, remove it.

---
 drivers/net/phy/phylink.c | 13 -------------
 include/linux/phylink.h   |  1 -
 2 files changed, 14 deletions(-)
drivers/net/phy/phylink.c +0 -13
index 06c6ad0603ac..560486463930 100644
@@ -1064,19 +1064,6 @@ int phylink_ethtool_get_module_eeprom(struct phylink *pl,
 }
 EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom);
 
-int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
-{
-	int ret = -EPROTONOSUPPORT;
-
-	WARN_ON(!lockdep_rtnl_is_held());
-
-	if (pl->phydev)
-		ret = phy_init_eee(pl->phydev, clk_stop_enable);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(phylink_init_eee);
-
 int phylink_get_eee_err(struct phylink *pl)
 {
 	int ret = 0;
include/linux/phylink.h +0 -1
index cab22ad3bd6f..4d0f42da9078 100644
@@ -123,7 +123,6 @@ int phylink_ethtool_set_pauseparam(struct phylink *,
 int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *);
 int phylink_ethtool_get_module_eeprom(struct phylink *,
 				      struct ethtool_eeprom *, u8 *);
-int phylink_init_eee(struct phylink *, bool);
 int phylink_get_eee_err(struct phylink *);
 int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *);
 int phylink_ethtool_set_eee(struct phylink *, struct ethtool_eee *);
Signature · 1 line
2.7.4
#12 lore raw

PATCH 6/11 phylink: restart 802.3z negotiation when starting net device

In reply to Russell King - ARM Linux

Restart 802.3z negotiation when the net device is brought up to ensure that the link partner has our current link modes.

---
 drivers/net/phy/phylink.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/net/phy/phylink.c +6 -0
index 560486463930..40563c8d7352 100644
@@ -751,6 +751,12 @@ void phylink_start(struct phylink *pl)
 	phylink_resolve_flow(pl, &pl->link_config);
 	phylink_mac_config(pl, &pl->link_config);
 
+	/* Restart autonegotiation if using 802.3z to ensure that the link
+	 * parameters are properly negotiated.  This is necessary for DSA
+	 * switches using 802.3z negotiation to ensure they see our modes.
+	 */
+	phylink_mac_an_restart(pl);
+
 	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
 	phylink_run_resolve(pl);
 
Signature · 1 line
2.7.4
#14 lore raw

PATCH 7/11 phylink: add documentation for kernel APIs

In reply to Russell King - ARM Linux

Add kernel-doc documentation for phylink kernel APIs, and link it into the networking kapi documentation under "Network device support".

---
 Documentation/networking/kapi.rst |  12 +++
 drivers/net/phy/phylink.c         | 182 +++++++++++++++++++++++++++++++++++++
 include/linux/phylink.h           | 183 ++++++++++++++++++++++++++++----------
 3 files changed, 329 insertions(+), 48 deletions(-)
Documentation/networking/kapi.rst +12 -0
index 580289f345da..df4141b72f24 100644
@@ -145,3 +145,15 @@ PHY Support
 
 .. kernel-doc:: drivers/net/phy/mdio_bus.c
    :internal:
+
+PHYLINK
+-------
+
+  PHYLINK interfaces traditional network drivers with PHYLIB, fixed-links,
+  and SFF modules (eg, hot-pluggable SFP) that may contain PHYs.  PHYLINK
+  provides management of the link state and link modes.
+
+.. kernel-doc:: include/linux/phylink.h
+   :internal:
+
+.. kernel-doc:: drivers/net/phy/phylink.c
drivers/net/phy/phylink.c +182 -0

309 lines not on this page · raw message

include/linux/phylink.h +135 -48

206 lines not on this page · raw message

Signature · 1 line
2.7.4
#16 lore raw

PATCH 8/11 sfp: add documentation for kernel APIs

In reply to Russell King - ARM Linux

Add kernel-doc documentation for sfp kernel APIs, and link it into the networking kapi documentation under "Network device support".

---
 Documentation/networking/kapi.rst |  12 +++++
 drivers/net/phy/sfp-bus.c         | 104 ++++++++++++++++++++++++++++++++++++++
 include/linux/sfp.h               |  50 +++++++++++++-----
 3 files changed, 152 insertions(+), 14 deletions(-)
Documentation/networking/kapi.rst +12 -0
index df4141b72f24..f03ae64be8bc 100644
@@ -157,3 +157,15 @@ PHYLINK
    :internal:
 
 .. kernel-doc:: drivers/net/phy/phylink.c
+
+SFP support
+-----------
+
+.. kernel-doc:: drivers/net/phy/sfp-bus.c
+   :internal:
+
+.. kernel-doc:: include/linux/sfp.h
+   :internal:
+
+.. kernel-doc:: drivers/net/phy/sfp-bus.c
+   :export:
drivers/net/phy/sfp-bus.c +104 -0

165 lines not on this page · raw message

include/linux/sfp.h +36 -14

80 lines not on this page · raw message

Signature · 1 line
2.7.4
#18 lore raw

PATCH 9/11 sfp: fix sparse warning

In reply to Russell King - ARM Linux

drivers/net/phy/sfp-bus.c:298:13: warning: context imbalance in 'sfp_bus_release' - wrong count at exit

---
 drivers/net/phy/sfp-bus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/phy/sfp-bus.c +1 -1
index 2b8c256156a2..a28859022ddb 100644
@@ -291,7 +291,7 @@ static struct sfp_bus *sfp_bus_get(struct device_node *np)
 	return found;
 }
 
-static void sfp_bus_release(struct kref *kref) __releases(sfp_mutex)
+static void sfp_bus_release(struct kref *kref)
 {
 	struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref);
 
Signature · 1 line
2.7.4
#20 lore raw

PATCH 10/11 sfp: convert to fwnode

In reply to Russell King - ARM Linux

Convert sfp-bus to use fwnode rather than device_node internally, so we can support more than just device tree firmware.

---
 drivers/net/phy/phylink.c |  3 ++-
 drivers/net/phy/sfp-bus.c | 14 +++++++-------
 include/linux/sfp.h       |  7 ++++---
 3 files changed, 13 insertions(+), 11 deletions(-)
drivers/net/phy/phylink.c +2 -1
index 5a1bd48eb6d7..bca142a4863c 100644
@@ -499,7 +499,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
 	if (!sfp_np)
 		return 0;
 
-	pl->sfp_bus = sfp_register_upstream(sfp_np, pl->netdev, pl,
+	pl->sfp_bus = sfp_register_upstream(of_fwnode_handle(sfp_np),
+					    pl->netdev, pl,
 					    &sfp_phylink_ops);
 	if (!pl->sfp_bus)
 		return -ENOMEM;
drivers/net/phy/sfp-bus.c +7 -7
index a28859022ddb..1356dba0d9d3 100644
@@ -15,7 +15,7 @@ struct sfp_bus {
 	/* private: */
 	struct kref kref;
 	struct list_head node;
-	struct device_node *device_node;
+	struct fwnode_handle *fwnode;
 
 	const struct sfp_socket_ops *socket_ops;
 	struct device *sfp_dev;
@@ -260,7 +260,7 @@ static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
 	return bus->registered ? bus->upstream_ops : NULL;
 }
 
-static struct sfp_bus *sfp_bus_get(struct device_node *np)
+static struct sfp_bus *sfp_bus_get(struct fwnode_handle *fwnode)
 {
 	struct sfp_bus *sfp, *new, *found = NULL;
 
@@ -269,7 +269,7 @@ static struct sfp_bus *sfp_bus_get(struct device_node *np)
 	mutex_lock(&sfp_mutex);
 
 	list_for_each_entry(sfp, &sfp_buses, node) {
-		if (sfp->device_node == np) {
+		if (sfp->fwnode == fwnode) {
 			kref_get(&sfp->kref);
 			found = sfp;
 			break;
@@ -278,7 +278,7 @@ static struct sfp_bus *sfp_bus_get(struct device_node *np)
 
 	if (!found && new) {
 		kref_init(&new->kref);
-		new->device_node = np;
+		new->fwnode = fwnode;
 		list_add(&new->node, &sfp_buses);
 		found = new;
 		new = NULL;
@@ -423,11 +423,11 @@ EXPORT_SYMBOL_GPL(sfp_upstream_stop);
  *
  * On error, returns %NULL.
  */
-struct sfp_bus *sfp_register_upstream(struct device_node *np,
+struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
 				      struct net_device *ndev, void *upstream,
 				      const struct sfp_upstream_ops *ops)
 {
-	struct sfp_bus *bus = sfp_bus_get(np);
+	struct sfp_bus *bus = sfp_bus_get(fwnode);
 	int ret = 0;
 
 	if (bus) {
@@ -537,7 +537,7 @@ EXPORT_SYMBOL_GPL(sfp_module_remove);
 struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp,
 				    const struct sfp_socket_ops *ops)
 {
-	struct sfp_bus *bus = sfp_bus_get(dev->of_node);
+	struct sfp_bus *bus = sfp_bus_get(dev->fwnode);
 	int ret = 0;
 
 	if (bus) {
include/linux/sfp.h +4 -3
index b6089fe72378..47ea32d3e816 100644
@@ -356,7 +356,7 @@ enum {
 	SFP_PAGE			= 0x7f,
 };
 
-struct device_node;
+struct fwnode_handle;
 struct ethtool_eeprom;
 struct ethtool_modinfo;
 struct net_device;
@@ -397,7 +397,7 @@ 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 device_node *np,
+struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
 				      struct net_device *ndev, void *upstream,
 				      const struct sfp_upstream_ops *ops);
 void sfp_unregister_upstream(struct sfp_bus *bus);
@@ -441,7 +441,8 @@ static inline void sfp_upstream_stop(struct sfp_bus *bus)
 {
 }
 
-static inline struct sfp_bus *sfp_register_upstream(struct device_node *np,
+static inline struct sfp_bus *sfp_register_upstream(
+	struct fwnode_handle *fwnode,
 	struct net_device *ndev, void *upstream,
 	const struct sfp_upstream_ops *ops)
 {
Signature · 1 line
2.7.4
#22 lore raw

PATCH 11/11 phylink: convert to fwnode

In reply to Russell King - ARM Linux

Convert phylink to fwnode, switching phylink_create() from taking a device_node to taking a fwnode_handle. This will allow other firmware systems to take advantage of sfp/phylink support.

---
 drivers/net/phy/phylink.c | 91 +++++++++++++++++++++++++++--------------------
 include/linux/phylink.h   |  3 +-
 2 files changed, 55 insertions(+), 39 deletions(-)
drivers/net/phy/phylink.c +53 -38
index bca142a4863c..2bfb548d3dff 100644
@@ -142,59 +142,64 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
 }
 
-static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np)
+static int phylink_parse_fixedlink(struct phylink *pl,
+				   struct fwnode_handle *fwnode)
 {
-	struct device_node *fixed_node;
+	struct fwnode_handle *fixed_node;
 	const struct phy_setting *s;
 	struct gpio_desc *desc;
-	const __be32 *fixed_prop;
 	u32 speed;
-	int ret, len;
+	int ret;
 
-	fixed_node = of_get_child_by_name(np, "fixed-link");
+	fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link");
 	if (fixed_node) {
-		ret = of_property_read_u32(fixed_node, "speed", &speed);
+		ret = fwnode_property_read_u32(fixed_node, "speed", &speed);
 
 		pl->link_config.speed = speed;
 		pl->link_config.duplex = DUPLEX_HALF;
 
-		if (of_property_read_bool(fixed_node, "full-duplex"))
+		if (fwnode_property_read_bool(fixed_node, "full-duplex"))
 			pl->link_config.duplex = DUPLEX_FULL;
 
 		/* We treat the "pause" and "asym-pause" terminology as
 		 * defining the link partner's ability. */
-		if (of_property_read_bool(fixed_node, "pause"))
+		if (fwnode_property_read_bool(fixed_node, "pause"))
 			pl->link_config.pause |= MLO_PAUSE_SYM;
-		if (of_property_read_bool(fixed_node, "asym-pause"))
+		if (fwnode_property_read_bool(fixed_node, "asym-pause"))
 			pl->link_config.pause |= MLO_PAUSE_ASYM;
 
 		if (ret == 0) {
-			desc = fwnode_get_named_gpiod(&fixed_node->fwnode,
-						      "link-gpios", 0,
-						      GPIOD_IN, "?");
+			desc = fwnode_get_named_gpiod(fixed_node, "link-gpios",
+						      0, GPIOD_IN, "?");
 
 			if (!IS_ERR(desc))
 				pl->link_gpio = desc;
 			else if (desc == ERR_PTR(-EPROBE_DEFER))
 				ret = -EPROBE_DEFER;
 		}
-		of_node_put(fixed_node);
+		fwnode_handle_put(fixed_node);
 
 		if (ret)
 			return ret;
 	} else {
-		fixed_prop = of_get_property(np, "fixed-link", &len);
-		if (!fixed_prop) {
+		u32 prop[5];
+
+		ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
+						     NULL, 0);
+		if (ret != ARRAY_SIZE(prop)) {
 			netdev_err(pl->netdev, "broken fixed-link?\n");
 			return -EINVAL;
 		}
-		if (len == 5 * sizeof(*fixed_prop)) {
-			pl->link_config.duplex = be32_to_cpu(fixed_prop[1]) ?
+
+		ret = fwnode_property_read_u32_array(fwnode, "fixed-link",
+						     prop, ARRAY_SIZE(prop));
+		if (!ret) {
+			pl->link_config.duplex = prop[1] ?
 						DUPLEX_FULL : DUPLEX_HALF;
-			pl->link_config.speed = be32_to_cpu(fixed_prop[2]);
-			if (be32_to_cpu(fixed_prop[3]))
+			pl->link_config.speed = prop[2];
+			if (prop[3])
 				pl->link_config.pause |= MLO_PAUSE_SYM;
-			if (be32_to_cpu(fixed_prop[4]))
+			if (prop[4])
 				pl->link_config.pause |= MLO_PAUSE_ASYM;
 		}
 	}
@@ -230,17 +235,17 @@ static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np)
 	return 0;
 }
 
-static int phylink_parse_mode(struct phylink *pl, struct device_node *np)
+static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
 {
-	struct device_node *dn;
+	struct fwnode_handle *dn;
 	const char *managed;
 
-	dn = of_get_child_by_name(np, "fixed-link");
-	if (dn || of_find_property(np, "fixed-link", NULL))
+	dn = fwnode_get_named_child_node(fwnode, "fixed-link");
+	if (dn || fwnode_property_present(fwnode, "fixed-link"))
 		pl->link_an_mode = MLO_AN_FIXED;
-	of_node_put(dn);
+	fwnode_handle_put(dn);
 
-	if (of_property_read_string(np, "managed", &managed) == 0 &&
+	if (fwnode_property_read_string(fwnode, "managed", &managed) == 0 &&
 	    strcmp(managed, "in-band-status") == 0) {
 		if (pl->link_an_mode == MLO_AN_FIXED) {
 			netdev_err(pl->netdev,
@@ -491,16 +496,24 @@ static void phylink_run_resolve(struct phylink *pl)
 
 static const struct sfp_upstream_ops sfp_phylink_ops;
 
-static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
+static int phylink_register_sfp(struct phylink *pl,
+				struct fwnode_handle *fwnode)
 {
-	struct device_node *sfp_np;
+	struct fwnode_reference_args ref;
+	int ret;
 
-	sfp_np = of_parse_phandle(np, "sfp", 0);
-	if (!sfp_np)
-		return 0;
+	ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
+						 0, 0, &ref);
+	if (ret < 0) {
+		if (ret == -ENOENT)
+			return 0;
+
+		netdev_err(pl->netdev, "unable to parse \"sfp\" node: %d\n",
+			   ret);
+		return ret;
+	}
 
-	pl->sfp_bus = sfp_register_upstream(of_fwnode_handle(sfp_np),
-					    pl->netdev, pl,
+	pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl->netdev, pl,
 					    &sfp_phylink_ops);
 	if (!pl->sfp_bus)
 		return -ENOMEM;
@@ -511,7 +524,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
 /**
  * phylink_create() - create a phylink instance
  * @ndev: a pointer to the &struct net_device
- * @np: a pointer to a &struct device_node describing the network interface
+ * @fwnode: a pointer to a &struct fwnode_handle describing the network
+ *	interface
  * @iface: the desired link mode defined by &typedef phy_interface_t
  * @ops: a pointer to a &struct phylink_mac_ops for the MAC.
  *
@@ -521,7 +535,8 @@ static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
  * Returns a pointer to a &struct phylink, or an error-pointer value. Users
  * must use IS_ERR() to check for errors from this function.
  */
-struct phylink *phylink_create(struct net_device *ndev, struct device_node *np,
+struct phylink *phylink_create(struct net_device *ndev,
+			       struct fwnode_handle *fwnode,
 			       phy_interface_t iface,
 			       const struct phylink_mac_ops *ops)
 {
@@ -549,21 +564,21 @@ struct phylink *phylink_create(struct net_device *ndev, struct device_node *np,
 	linkmode_copy(pl->link_config.advertising, pl->supported);
 	phylink_validate(pl, pl->supported, &pl->link_config);
 
-	ret = phylink_parse_mode(pl, np);
+	ret = phylink_parse_mode(pl, fwnode);
 	if (ret < 0) {
 		kfree(pl);
 		return ERR_PTR(ret);
 	}
 
 	if (pl->link_an_mode == MLO_AN_FIXED) {
-		ret = phylink_parse_fixedlink(pl, np);
+		ret = phylink_parse_fixedlink(pl, fwnode);
 		if (ret < 0) {
 			kfree(pl);
 			return ERR_PTR(ret);
 		}
 	}
 
-	ret = phylink_register_sfp(pl, np);
+	ret = phylink_register_sfp(pl, fwnode);
 	if (ret < 0) {
 		kfree(pl);
 		return ERR_PTR(ret);
include/linux/phylink.h +2 -1
index 30e9d0070377..4f0f452ff38d 100644
@@ -7,6 +7,7 @@
 
 struct device_node;
 struct ethtool_cmd;
+struct fwnode_handle;
 struct net_device;
 
 enum {
@@ -182,7 +183,7 @@ void mac_link_up(struct net_device *ndev, unsigned int mode,
 		 struct phy_device *phy);
 #endif
 
-struct phylink *phylink_create(struct net_device *, struct device_node *,
+struct phylink *phylink_create(struct net_device *, struct fwnode_handle *,
 	phy_interface_t iface, const struct phylink_mac_ops *ops);
 void phylink_destroy(struct phylink *);
 
Signature · 1 line
2.7.4
author maintainer
#24 lore raw

Re: [PATCH net-next 00/11] SFP/phylink updates

In reply to Russell King - ARM Linux
Quoted 4 lines · Russell King - ARM Linux

Hi,

This series, which follows on from the fixes posted earlier, improves the phylink/sfp support. Changes included here are:

Sorry, just realised I sent the patches without the net-next annotation after the [PATCH in their subject line.

Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
maintainer
#25 lore raw

Re: [PATCH net-next 00/11] SFP/phylink updates

In reply to Russell King - ARM Linux

From: Russell King - ARM Linux <[email protected]>
Date: Fri, 1 Dec 2017 10:23:07 +0000

Quoted 2 lines

This series, which follows on from the fixes posted earlier, improves the phylink/sfp support. Changes included here are:

Ok, I'll merge this in the next time I get 'net' into 'net-next'.

maintainer
#26 lore raw

Re: [PATCH net-next 00/11] SFP/phylink updates

In reply to Russell King - ARM Linux

From: Russell King - ARM Linux <[email protected]>
Date: Fri, 1 Dec 2017 10:23:07 +0000

Quoted 2 lines

This series, which follows on from the fixes posted earlier, improves the phylink/sfp support. Changes included here are:

...

Series applied, thanks!

maintainer
#27 lore raw
In reply to Russell King - ARM Linux

From: Russell King - ARM Linux <[email protected]>
Date: Thu, 30 Nov 2017 13:58:35 +0000

Quoted 9 lines

Here are four phylink fixes:
- the "options" is a big-endian value, we must test the bits taking the endian-ness into account.
- improve the handling of RX_LOS polarity, taking no RX_LOS polarity bits set to mean there is no RX_LOS functionality provided.
- do not report modules that require the address mode switching as supporting SFF8472.
- ensure that the mac_link_down() function is called when phylink_stop() is called.

Series applied, thank you.