All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v2 00/14] Add support for SFP+ copper modules
@ 2019-12-09 15:15 Russell King - ARM Linux admin
  2019-12-09 15:18 ` [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support Russell King
                   ` (14 more replies)
  0 siblings, 15 replies; 35+ messages in thread
From: Russell King - ARM Linux admin @ 2019-12-09 15:15 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Hi,

This series adds support for Copper SFP+ modules with Clause 45 PHYs.
Specifically the patches:

1. drop support for the probably never tested 100BASE-*X modules.
2. drop EEPROM ID from sfp_select_interface()
3. add more compliance code definitions from SFF-8024, renaming the
   existing definitions.
4. add module start/stop methods so phylink knows when a module is
   about to become active. The module start method is called after
   we have probed for a PHY on the module.
5. move start/stop of module PHY down into phylink using the new
   module start/stop methods.
6. add support for Clause 45 I2C accesses, tested with Methode DM7052.
   Other modules appear to use the same protocol, but slight
   differences, but I do not have those modules to test with.
   (if someone does, please holler!)
7. rearrange how we attach to PHYs so that we can support Clause 45
   PHYs with indeterminant interface modes.  (Clause 45 PHYs appear
   to like to change their PHY interface mode depending on the
   negotiated speed.)
8. add support for phylink to connect to a clause 45 PHY on a SFP
   module.
9. split the link_an_mode between the configured value and the
   currently selected mode value; some clause 45 PHYs have no
   capability to provide in-band negotiation.
10. split the link configuration on SFP module insertion in phylink
    so we can use it in other code paths.
11. delay MAC configuration for copper modules without a PHY to the
    module start method - after any module PHY has been probed.  If
    the module has a PHY, then we setup the MAC when the PHY is
    detected.
12. the Broadcom 84881 PHY does not support in-band negotiation even
    though it uses SGMII and 2500BASE-X.  Having the MAC operating
    with in-band negotiation enabled, even with AN bypass enabled,
    results in no link - Broadcom say that the host MAC must always
    be forced.
13. add support for the Broadcom 84881 PHY found on the Methode
    DM7052 module.
14. add support to SFP to probe for a Clause 45 PHY on copper SFP+
    modules.

 drivers/net/phy/Kconfig      |   6 +
 drivers/net/phy/Makefile     |   1 +
 drivers/net/phy/bcm84881.c   | 269 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/marvell10g.c |   2 +-
 drivers/net/phy/mdio-i2c.c   |  28 +++--
 drivers/net/phy/phylink.c    | 229 ++++++++++++++++++++++++++----------
 drivers/net/phy/sfp-bus.c    | 122 ++++++++++++++------
 drivers/net/phy/sfp.c        |  69 ++++++++---
 drivers/net/phy/sfp.h        |   2 +
 include/linux/sfp.h          |  95 ++++++++++-----
 10 files changed, 670 insertions(+), 153 deletions(-)
 create mode 100644 drivers/net/phy/bcm84881.c

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 16:52   ` Andrew Lunn
  2019-12-09 15:18 ` [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes Russell King
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

The 100BASE-FX and 100BASE-LX support assumes a PHY is present; this
is probably an incorrect assumption. In any case, sfp_parse_support()
will fail such a module. Let's stop pretending we support these
modules.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp-bus.c |  4 +---
 drivers/net/phy/sfp.c     | 13 +------------
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 5a72093ab6e7..02ab07624c89 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -342,9 +342,7 @@ phy_interface_t sfp_select_interface(struct sfp_bus *bus,
 	if (phylink_test(link_modes, 2500baseX_Full))
 		return PHY_INTERFACE_MODE_2500BASEX;
 
-	if (id->base.e1000_base_t ||
-	    id->base.e100_base_lx ||
-	    id->base.e100_base_fx)
+	if (id->base.e1000_base_t)
 		return PHY_INTERFACE_MODE_SGMII;
 
 	if (phylink_test(link_modes, 1000baseX_Full))
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 27360d1840b2..ae6a52a19458 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1489,18 +1489,7 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
 
 static void sfp_sm_probe_for_phy(struct sfp *sfp)
 {
-	/* Setting the serdes link mode is guesswork: there's no
-	 * field in the EEPROM which indicates what mode should
-	 * be used.
-	 *
-	 * If it's a gigabit-only fiber module, it probably does
-	 * not have a PHY, so switch to 802.3z negotiation mode.
-	 * Otherwise, switch to SGMII mode (which is required to
-	 * support non-gigabit speeds) and probe for a PHY.
-	 */
-	if (sfp->id.base.e1000_base_t ||
-	    sfp->id.base.e100_base_lx ||
-	    sfp->id.base.e100_base_fx)
+	if (sfp->id.base.e1000_base_t)
 		sfp_sm_probe_phy(sfp);
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
  2019-12-09 15:18 ` [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support Russell King
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 16:53   ` Andrew Lunn
  2019-12-09 15:18 ` [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes Russell King
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

We don't need the EEPROM ID to derive the phy interface mode as we can
derive it merely from the ethtool link modes.  Remove the EEPROM ID
argument to sfp_select_interface().

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/marvell10g.c |  2 +-
 drivers/net/phy/phylink.c    |  2 +-
 drivers/net/phy/sfp-bus.c    | 11 ++++-------
 include/linux/sfp.h          |  2 --
 4 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 6397e7c4219f..5c0140546ca2 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -216,7 +216,7 @@ static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
 	phy_interface_t iface;
 
 	sfp_parse_support(phydev->sfp_bus, id, support);
-	iface = sfp_select_interface(phydev->sfp_bus, id, support);
+	iface = sfp_select_interface(phydev->sfp_bus, support);
 
 	if (iface != PHY_INTERFACE_MODE_10GKR) {
 		dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 8e2a12885789..d02eb83ed151 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1717,7 +1717,7 @@ static int phylink_sfp_module_insert(void *upstream,
 
 	linkmode_copy(support1, support);
 
-	iface = sfp_select_interface(pl->sfp_bus, id, config.advertising);
+	iface = sfp_select_interface(pl->sfp_bus, config.advertising);
 	if (iface == PHY_INTERFACE_MODE_NA) {
 		phylink_err(pl,
 			    "selection of interface failed, advertisement %*pb\n",
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 02ab07624c89..1561962fda30 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -320,16 +320,12 @@ EXPORT_SYMBOL_GPL(sfp_parse_support);
 /**
  * sfp_select_interface() - Select appropriate phy_interface_t mode
  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
- * @id: a pointer to the module's &struct sfp_eeprom_id
  * @link_modes: ethtool link modes mask
  *
- * Derive the phy_interface_t mode for the information found in the
- * module's identifying EEPROM and the link modes mask. There is no
- * standard or defined way to derive this information, so we decide
- * based upon the link mode mask.
+ * Derive the phy_interface_t mode for the SFP module from the link
+ * modes mask.
  */
 phy_interface_t sfp_select_interface(struct sfp_bus *bus,
-				     const struct sfp_eeprom_id *id,
 				     unsigned long *link_modes)
 {
 	if (phylink_test(link_modes, 10000baseCR_Full) ||
@@ -342,7 +338,8 @@ phy_interface_t sfp_select_interface(struct sfp_bus *bus,
 	if (phylink_test(link_modes, 2500baseX_Full))
 		return PHY_INTERFACE_MODE_2500BASEX;
 
-	if (id->base.e1000_base_t)
+	if (phylink_test(link_modes, 1000baseT_Half) ||
+	    phylink_test(link_modes, 1000baseT_Full))
 		return PHY_INTERFACE_MODE_SGMII;
 
 	if (phylink_test(link_modes, 1000baseX_Full))
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 487fd9412d10..8d7b98c214d7 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -504,7 +504,6 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 		       unsigned long *support);
 phy_interface_t sfp_select_interface(struct sfp_bus *bus,
-				     const struct sfp_eeprom_id *id,
 				     unsigned long *link_modes);
 
 int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo);
@@ -532,7 +531,6 @@ static inline void sfp_parse_support(struct sfp_bus *bus,
 }
 
 static inline phy_interface_t sfp_select_interface(struct sfp_bus *bus,
-						   const struct sfp_eeprom_id *id,
 						   unsigned long *link_modes)
 {
 	return PHY_INTERFACE_MODE_NA;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
  2019-12-09 15:18 ` [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support Russell King
  2019-12-09 15:18 ` [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes Russell King
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 16:57   ` Andrew Lunn
  2019-12-09 15:18 ` [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications Russell King
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

SFF-8024 is used to define various constants re-used in several SFF
SFP-related specifications.  Split these constants from the enum, and
rename them to indicate that they're defined by SFF-8024.

Add and use updated SFF-8024 extended compliance code definitions for
10GBASE-T, 5GBASE-T and 2.5GBASE-T modules.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp-bus.c | 60 ++++++++++++++++------------
 drivers/net/phy/sfp.c     |  4 +-
 include/linux/sfp.h       | 82 ++++++++++++++++++++++++++-------------
 3 files changed, 93 insertions(+), 53 deletions(-)

diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 1561962fda30..c6627f1e5d68 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -124,35 +124,35 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 
 	/* port is the physical connector, set this from the connector field. */
 	switch (id->base.connector) {
-	case SFP_CONNECTOR_SC:
-	case SFP_CONNECTOR_FIBERJACK:
-	case SFP_CONNECTOR_LC:
-	case SFP_CONNECTOR_MT_RJ:
-	case SFP_CONNECTOR_MU:
-	case SFP_CONNECTOR_OPTICAL_PIGTAIL:
+	case SFF8024_CONNECTOR_SC:
+	case SFF8024_CONNECTOR_FIBERJACK:
+	case SFF8024_CONNECTOR_LC:
+	case SFF8024_CONNECTOR_MT_RJ:
+	case SFF8024_CONNECTOR_MU:
+	case SFF8024_CONNECTOR_OPTICAL_PIGTAIL:
+	case SFF8024_CONNECTOR_MPO_1X12:
+	case SFF8024_CONNECTOR_MPO_2X16:
 		port = PORT_FIBRE;
 		break;
 
-	case SFP_CONNECTOR_RJ45:
+	case SFF8024_CONNECTOR_RJ45:
 		port = PORT_TP;
 		break;
 
-	case SFP_CONNECTOR_COPPER_PIGTAIL:
+	case SFF8024_CONNECTOR_COPPER_PIGTAIL:
 		port = PORT_DA;
 		break;
 
-	case SFP_CONNECTOR_UNSPEC:
+	case SFF8024_CONNECTOR_UNSPEC:
 		if (id->base.e1000_base_t) {
 			port = PORT_TP;
 			break;
 		}
 		/* fallthrough */
-	case SFP_CONNECTOR_SG: /* guess */
-	case SFP_CONNECTOR_MPO_1X12:
-	case SFP_CONNECTOR_MPO_2X16:
-	case SFP_CONNECTOR_HSSDC_II:
-	case SFP_CONNECTOR_NOSEPARATE:
-	case SFP_CONNECTOR_MXC_2X16:
+	case SFF8024_CONNECTOR_SG: /* guess */
+	case SFF8024_CONNECTOR_HSSDC_II:
+	case SFF8024_CONNECTOR_NOSEPARATE:
+	case SFF8024_CONNECTOR_MXC_2X16:
 		port = PORT_OTHER;
 		break;
 	default:
@@ -261,22 +261,33 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 	}
 
 	switch (id->base.extended_cc) {
-	case 0x00: /* Unspecified */
+	case SFF8024_ECC_UNSPEC:
 		break;
-	case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */
+	case SFF8024_ECC_100GBASE_SR4_25GBASE_SR:
 		phylink_set(modes, 100000baseSR4_Full);
 		phylink_set(modes, 25000baseSR_Full);
 		break;
-	case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */
-	case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */
+	case SFF8024_ECC_100GBASE_LR4_25GBASE_LR:
+	case SFF8024_ECC_100GBASE_ER4_25GBASE_ER:
 		phylink_set(modes, 100000baseLR4_ER4_Full);
 		break;
-	case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */
-	case 0x0c: /* 25Gbase-CR CA-S */
-	case 0x0d: /* 25Gbase-CR CA-N */
+	case SFF8024_ECC_100GBASE_CR4:
 		phylink_set(modes, 100000baseCR4_Full);
+		/* fallthrough */
+	case SFF8024_ECC_25GBASE_CR_S:
+	case SFF8024_ECC_25GBASE_CR_N:
 		phylink_set(modes, 25000baseCR_Full);
 		break;
+	case SFF8024_ECC_10GBASE_T_SFI:
+	case SFF8024_ECC_10GBASE_T_SR:
+		phylink_set(modes, 10000baseT_Full);
+		break;
+	case SFF8024_ECC_5GBASE_T:
+		phylink_set(modes, 5000baseT_Full);
+		break;
+	case SFF8024_ECC_2_5GBASE_T:
+		phylink_set(modes, 2500baseT_Full);
+		break;
 	default:
 		dev_warn(bus->sfp_dev,
 			 "Unknown/unsupported extended compliance code: 0x%02x\n",
@@ -301,7 +312,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 	 */
 	if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
 		/* If the encoding and bit rate allows 1000baseX */
-		if (id->base.encoding == SFP_ENCODING_8B10B && br_nom &&
+		if (id->base.encoding == SFF8024_ENCODING_8B10B && br_nom &&
 		    br_min <= 1300 && br_max >= 1200)
 			phylink_set(modes, 1000baseX_Full);
 	}
@@ -332,7 +343,8 @@ phy_interface_t sfp_select_interface(struct sfp_bus *bus,
 	    phylink_test(link_modes, 10000baseSR_Full) ||
 	    phylink_test(link_modes, 10000baseLR_Full) ||
 	    phylink_test(link_modes, 10000baseLRM_Full) ||
-	    phylink_test(link_modes, 10000baseER_Full))
+	    phylink_test(link_modes, 10000baseER_Full) ||
+	    phylink_test(link_modes, 10000baseT_Full))
 		return PHY_INTERFACE_MODE_10GKR;
 
 	if (phylink_test(link_modes, 2500baseX_Full))
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index ae6a52a19458..ad3808307dba 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -242,7 +242,7 @@ struct sfp {
 
 static bool sff_module_supported(const struct sfp_eeprom_id *id)
 {
-	return id->base.phys_id == SFP_PHYS_ID_SFF &&
+	return id->base.phys_id == SFF8024_ID_SFF_8472 &&
 	       id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
 }
 
@@ -253,7 +253,7 @@ static const struct sff_data sff_data = {
 
 static bool sfp_module_supported(const struct sfp_eeprom_id *id)
 {
-	return id->base.phys_id == SFP_PHYS_ID_SFP &&
+	return id->base.phys_id == SFF8024_ID_SFP &&
 	       id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
 }
 
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 8d7b98c214d7..373d8b67ea86 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -275,6 +275,61 @@ struct sfp_diag {
 	__be16 cal_v_offset;
 } __packed;
 
+/* SFF8024 defined constants */
+enum {
+	SFF8024_ID_UNK			= 0x00,
+	SFF8024_ID_SFF_8472		= 0x02,
+	SFF8024_ID_SFP			= 0x03,
+	SFF8024_ID_DWDM_SFP		= 0x0b,
+	SFF8024_ID_QSFP_8438		= 0x0c,
+	SFF8024_ID_QSFP_8436_8636	= 0x0d,
+	SFF8024_ID_QSFP28_8636		= 0x11,
+
+	SFF8024_ENCODING_UNSPEC		= 0x00,
+	SFF8024_ENCODING_8B10B		= 0x01,
+	SFF8024_ENCODING_4B5B		= 0x02,
+	SFF8024_ENCODING_NRZ		= 0x03,
+	SFF8024_ENCODING_8472_MANCHESTER= 0x04,
+	SFF8024_ENCODING_8472_SONET	= 0x05,
+	SFF8024_ENCODING_8472_64B66B	= 0x06,
+	SFF8024_ENCODING_8436_MANCHESTER= 0x06,
+	SFF8024_ENCODING_8436_SONET	= 0x04,
+	SFF8024_ENCODING_8436_64B66B	= 0x05,
+	SFF8024_ENCODING_256B257B	= 0x07,
+	SFF8024_ENCODING_PAM4		= 0x08,
+
+	SFF8024_CONNECTOR_UNSPEC	= 0x00,
+	/* codes 01-05 not supportable on SFP, but some modules have single SC */
+	SFF8024_CONNECTOR_SC		= 0x01,
+	SFF8024_CONNECTOR_FIBERJACK	= 0x06,
+	SFF8024_CONNECTOR_LC		= 0x07,
+	SFF8024_CONNECTOR_MT_RJ		= 0x08,
+	SFF8024_CONNECTOR_MU		= 0x09,
+	SFF8024_CONNECTOR_SG		= 0x0a,
+	SFF8024_CONNECTOR_OPTICAL_PIGTAIL= 0x0b,
+	SFF8024_CONNECTOR_MPO_1X12	= 0x0c,
+	SFF8024_CONNECTOR_MPO_2X16	= 0x0d,
+	SFF8024_CONNECTOR_HSSDC_II	= 0x20,
+	SFF8024_CONNECTOR_COPPER_PIGTAIL= 0x21,
+	SFF8024_CONNECTOR_RJ45		= 0x22,
+	SFF8024_CONNECTOR_NOSEPARATE	= 0x23,
+	SFF8024_CONNECTOR_MXC_2X16	= 0x24,
+
+	SFF8024_ECC_UNSPEC		= 0x00,
+	SFF8024_ECC_100G_25GAUI_C2M_AOC	= 0x01,
+	SFF8024_ECC_100GBASE_SR4_25GBASE_SR = 0x02,
+	SFF8024_ECC_100GBASE_LR4_25GBASE_LR = 0x03,
+	SFF8024_ECC_100GBASE_ER4_25GBASE_ER = 0x04,
+	SFF8024_ECC_100GBASE_SR10	= 0x05,
+	SFF8024_ECC_100GBASE_CR4	= 0x0b,
+	SFF8024_ECC_25GBASE_CR_S	= 0x0c,
+	SFF8024_ECC_25GBASE_CR_N	= 0x0d,
+	SFF8024_ECC_10GBASE_T_SFI	= 0x16,
+	SFF8024_ECC_10GBASE_T_SR	= 0x1c,
+	SFF8024_ECC_5GBASE_T		= 0x1d,
+	SFF8024_ECC_2_5GBASE_T		= 0x1e,
+};
+
 /* SFP EEPROM registers */
 enum {
 	SFP_PHYS_ID			= 0x00,
@@ -309,34 +364,7 @@ enum {
 	SFP_SFF8472_COMPLIANCE		= 0x5e,
 	SFP_CC_EXT			= 0x5f,
 
-	SFP_PHYS_ID_SFF			= 0x02,
-	SFP_PHYS_ID_SFP			= 0x03,
 	SFP_PHYS_EXT_ID_SFP		= 0x04,
-	SFP_CONNECTOR_UNSPEC		= 0x00,
-	/* codes 01-05 not supportable on SFP, but some modules have single SC */
-	SFP_CONNECTOR_SC		= 0x01,
-	SFP_CONNECTOR_FIBERJACK		= 0x06,
-	SFP_CONNECTOR_LC		= 0x07,
-	SFP_CONNECTOR_MT_RJ		= 0x08,
-	SFP_CONNECTOR_MU		= 0x09,
-	SFP_CONNECTOR_SG		= 0x0a,
-	SFP_CONNECTOR_OPTICAL_PIGTAIL	= 0x0b,
-	SFP_CONNECTOR_MPO_1X12		= 0x0c,
-	SFP_CONNECTOR_MPO_2X16		= 0x0d,
-	SFP_CONNECTOR_HSSDC_II		= 0x20,
-	SFP_CONNECTOR_COPPER_PIGTAIL	= 0x21,
-	SFP_CONNECTOR_RJ45		= 0x22,
-	SFP_CONNECTOR_NOSEPARATE	= 0x23,
-	SFP_CONNECTOR_MXC_2X16		= 0x24,
-	SFP_ENCODING_UNSPEC		= 0x00,
-	SFP_ENCODING_8B10B		= 0x01,
-	SFP_ENCODING_4B5B		= 0x02,
-	SFP_ENCODING_NRZ		= 0x03,
-	SFP_ENCODING_8472_MANCHESTER	= 0x04,
-	SFP_ENCODING_8472_SONET		= 0x05,
-	SFP_ENCODING_8472_64B66B	= 0x06,
-	SFP_ENCODING_256B257B		= 0x07,
-	SFP_ENCODING_PAM4		= 0x08,
 	SFP_OPTIONS_HIGH_POWER_LEVEL	= BIT(13),
 	SFP_OPTIONS_PAGING_A2		= BIT(12),
 	SFP_OPTIONS_RETIMER		= BIT(11),
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (2 preceding siblings ...)
  2019-12-09 15:18 ` [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes Russell King
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 16:59   ` Andrew Lunn
  2019-12-09 15:18 ` [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink Russell King
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

When dealing with some copper modules, we can't positively know the
module capabilities are until we have probed the PHY. Without the full
capabilities, we may end up failing a module that we could otherwise
drive with a restricted set of capabilities.

An example of this would be a module with a NBASE-T PHY plugged into
a host that supports phy interface modes 2500BASE-X and SGMII. The
PHY supports 10GBASE-R, 5000BASE-X, 2500BASE-X, SGMII interface modes,
which means a subset of the capabilities are compatible with the host.

However, reading the module EEPROM leads us to believe that the module
only supports ethtool link mode 10GBASE-T, which is incompatible with
the host - and thus results in the module being rejected.

This patch adds an extra notification which are triggered after the
SFP module's PHY probe, and a corresponding notification just before
the PHY is removed.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp-bus.c | 21 +++++++++++++++++++++
 drivers/net/phy/sfp.c     |  8 ++++++++
 drivers/net/phy/sfp.h     |  2 ++
 include/linux/sfp.h       |  4 ++++
 4 files changed, 35 insertions(+)

diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index c6627f1e5d68..eabc9e3f0a9e 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -712,6 +712,27 @@ void sfp_module_remove(struct sfp_bus *bus)
 }
 EXPORT_SYMBOL_GPL(sfp_module_remove);
 
+int sfp_module_start(struct sfp_bus *bus)
+{
+	const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
+	int ret = 0;
+
+	if (ops && ops->module_start)
+		ret = ops->module_start(bus->upstream);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sfp_module_start);
+
+void sfp_module_stop(struct sfp_bus *bus)
+{
+	const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
+
+	if (ops && ops->module_stop)
+		ops->module_stop(bus->upstream);
+}
+EXPORT_SYMBOL_GPL(sfp_module_stop);
+
 static void sfp_socket_clear(struct sfp_bus *bus)
 {
 	bus->sfp_dev = NULL;
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index ad3808307dba..23f30dac0f17 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -59,6 +59,7 @@ enum {
 	SFP_DEV_UP,
 
 	SFP_S_DOWN = 0,
+	SFP_S_FAIL,
 	SFP_S_WAIT,
 	SFP_S_INIT,
 	SFP_S_INIT_TX_FAULT,
@@ -122,6 +123,7 @@ static const char *event_to_str(unsigned short event)
 
 static const char * const sm_state_strings[] = {
 	[SFP_S_DOWN] = "down",
+	[SFP_S_FAIL] = "fail",
 	[SFP_S_WAIT] = "wait",
 	[SFP_S_INIT] = "init",
 	[SFP_S_INIT_TX_FAULT] = "init_tx_fault",
@@ -1826,6 +1828,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 		if (sfp->sm_state == SFP_S_LINK_UP &&
 		    sfp->sm_dev_state == SFP_DEV_UP)
 			sfp_sm_link_down(sfp);
+		if (sfp->sm_state > SFP_S_INIT)
+			sfp_module_stop(sfp->sfp_bus);
 		if (sfp->mod_phy)
 			sfp_sm_phy_detach(sfp);
 		sfp_module_tx_disable(sfp);
@@ -1893,6 +1897,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 			 * clear.  Probe for the PHY and check the LOS state.
 			 */
 			sfp_sm_probe_for_phy(sfp);
+			if (sfp_module_start(sfp->sfp_bus)) {
+				sfp_sm_next(sfp, SFP_S_FAIL, 0);
+				break;
+			}
 			sfp_sm_link_check_los(sfp);
 
 			/* Reset the fault retry count */
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 64f54b0bbd8c..b83f70526270 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -22,6 +22,8 @@ void sfp_link_up(struct sfp_bus *bus);
 void sfp_link_down(struct sfp_bus *bus);
 int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
 void sfp_module_remove(struct sfp_bus *bus);
+int sfp_module_start(struct sfp_bus *bus);
+void sfp_module_stop(struct sfp_bus *bus);
 int sfp_link_configure(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
 struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp,
 				    const struct sfp_socket_ops *ops);
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 373d8b67ea86..66a56396e8e3 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -507,6 +507,8 @@ struct sfp_bus;
  * @module_insert: called after a module has been detected to determine
  *   whether the module is supported for the upstream device.
  * @module_remove: called after the module has been removed.
+ * @module_start: called after the PHY probe step
+ * @module_stop: called before the PHY is removed
  * @link_down: called when the link is non-operational for whatever
  *   reason.
  * @link_up: called when the link is operational.
@@ -520,6 +522,8 @@ struct sfp_upstream_ops {
 	void (*detach)(void *priv, struct sfp_bus *bus);
 	int (*module_insert)(void *priv, const struct sfp_eeprom_id *id);
 	void (*module_remove)(void *priv);
+	int (*module_start)(void *priv);
+	void (*module_stop)(void *priv);
 	void (*link_down)(void *priv);
 	void (*link_up)(void *priv);
 	int (*connect_phy)(void *priv, struct phy_device *);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (3 preceding siblings ...)
  2019-12-09 15:18 ` [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications Russell King
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 17:00   ` Andrew Lunn
  2019-12-09 15:18 ` [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses Russell King
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Move phy_start() and phy_stop() into the module_start and module_stop
notifications in phylink, rather than having them in the SFP code.
This gives phylink responsibility for controlling the PHY, rather
than having SFP start and stop the PHY state machine.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 22 ++++++++++++++++++++++
 drivers/net/phy/sfp.c     |  2 --
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index d02eb83ed151..8c3fafebe667 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1770,6 +1770,26 @@ static int phylink_sfp_module_insert(void *upstream,
 	return ret;
 }
 
+static int phylink_sfp_module_start(void *upstream)
+{
+	struct phylink *pl = upstream;
+
+	/* If this SFP module has a PHY, start the PHY now. */
+	if (pl->phydev)
+		phy_start(pl->phydev);
+
+	return 0;
+}
+
+static void phylink_sfp_module_stop(void *upstream)
+{
+	struct phylink *pl = upstream;
+
+	/* If this SFP module has a PHY, stop it. */
+	if (pl->phydev)
+		phy_stop(pl->phydev);
+}
+
 static void phylink_sfp_link_down(void *upstream)
 {
 	struct phylink *pl = upstream;
@@ -1805,6 +1825,8 @@ static const struct sfp_upstream_ops sfp_phylink_ops = {
 	.attach = phylink_sfp_attach,
 	.detach = phylink_sfp_detach,
 	.module_insert = phylink_sfp_module_insert,
+	.module_start = phylink_sfp_module_start,
+	.module_stop = phylink_sfp_module_stop,
 	.link_up = phylink_sfp_link_up,
 	.link_down = phylink_sfp_link_down,
 	.connect_phy = phylink_sfp_connect_phy,
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 23f30dac0f17..d7d2c797c89c 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1396,7 +1396,6 @@ static void sfp_sm_mod_next(struct sfp *sfp, unsigned int state,
 
 static void sfp_sm_phy_detach(struct sfp *sfp)
 {
-	phy_stop(sfp->mod_phy);
 	sfp_remove_phy(sfp->sfp_bus);
 	phy_device_remove(sfp->mod_phy);
 	phy_device_free(sfp->mod_phy);
@@ -1427,7 +1426,6 @@ static void sfp_sm_probe_phy(struct sfp *sfp)
 	}
 
 	sfp->mod_phy = phy;
-	phy_start(phy);
 }
 
 static void sfp_sm_link_up(struct sfp *sfp)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (4 preceding siblings ...)
  2019-12-09 15:18 ` [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink Russell King
@ 2019-12-09 15:18 ` Russell King
  2019-12-10 17:05   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy() Russell King
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Some SFP+ modules have PHYs on them just like SFP modules do, except
they are Clause 45 PHYs.  The I2C protocol used to access them is
modified slightly in order to send the device address and 16-bit
register index.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/mdio-i2c.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c
index 0dce67672548..0746e2cc39ae 100644
--- a/drivers/net/phy/mdio-i2c.c
+++ b/drivers/net/phy/mdio-i2c.c
@@ -33,17 +33,24 @@ static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
 {
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msgs[2];
-	u8 data[2], dev_addr = reg;
+	u8 addr[3], data[2], *p;
 	int bus_addr, ret;
 
 	if (!i2c_mii_valid_phy_id(phy_id))
 		return 0xffff;
 
+	p = addr;
+	if (reg & MII_ADDR_C45) {
+		*p++ = 0x20 | ((reg >> 16) & 31);
+		*p++ = reg >> 8;
+	}
+	*p++ = reg;
+
 	bus_addr = i2c_mii_phy_addr(phy_id);
 	msgs[0].addr = bus_addr;
 	msgs[0].flags = 0;
-	msgs[0].len = 1;
-	msgs[0].buf = &dev_addr;
+	msgs[0].len = p - addr;
+	msgs[0].buf = addr;
 	msgs[1].addr = bus_addr;
 	msgs[1].flags = I2C_M_RD;
 	msgs[1].len = sizeof(data);
@@ -61,18 +68,23 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msg;
 	int ret;
-	u8 data[3];
+	u8 data[5], *p;
 
 	if (!i2c_mii_valid_phy_id(phy_id))
 		return 0;
 
-	data[0] = reg;
-	data[1] = val >> 8;
-	data[2] = val;
+	p = data;
+	if (reg & MII_ADDR_C45) {
+		*p++ = (reg >> 16) & 31;
+		*p++ = reg >> 8;
+	}
+	*p++ = reg;
+	*p++ = val >> 8;
+	*p++ = val;
 
 	msg.addr = i2c_mii_phy_addr(phy_id);
 	msg.flags = 0;
-	msg.len = 3;
+	msg.len = p - data;
 	msg.buf = data;
 
 	ret = i2c_transfer(i2c, &msg, 1);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy()
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (5 preceding siblings ...)
  2019-12-09 15:18 ` [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:06   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules Russell King
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

In order to support Clause 45 PHYs on SFP+ modules, which have an
indeterminant phy interface mode, we need to be able to call
phylink_bringup_phy() with a different interface mode to that used when
binding the PHY. Reduce __phylink_connect_phy() to an attach operation,
and move the call to phylink_bringup_phy() to its call sites.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 8c3fafebe667..c32b2c080584 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -764,8 +764,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
 	return 0;
 }
 
-static int __phylink_connect_phy(struct phylink *pl, struct phy_device *phy,
-		phy_interface_t interface)
+static int phylink_attach_phy(struct phylink *pl, struct phy_device *phy,
+			      phy_interface_t interface)
 {
 	int ret;
 
@@ -777,15 +777,7 @@ static int __phylink_connect_phy(struct phylink *pl, struct phy_device *phy,
 	if (pl->phydev)
 		return -EBUSY;
 
-	ret = phy_attach_direct(pl->netdev, phy, 0, interface);
-	if (ret)
-		return ret;
-
-	ret = phylink_bringup_phy(pl, phy);
-	if (ret)
-		phy_detach(phy);
-
-	return ret;
+	return phy_attach_direct(pl->netdev, phy, 0, interface);
 }
 
 /**
@@ -805,13 +797,23 @@ static int __phylink_connect_phy(struct phylink *pl, struct phy_device *phy,
  */
 int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
 {
+	int ret;
+
 	/* Use PHY device/driver interface */
 	if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
 		pl->link_interface = phy->interface;
 		pl->link_config.interface = pl->link_interface;
 	}
 
-	return __phylink_connect_phy(pl, phy, pl->link_interface);
+	ret = phylink_attach_phy(pl, phy, pl->link_interface);
+	if (ret < 0)
+		return ret;
+
+	ret = phylink_bringup_phy(pl, phy);
+	if (ret)
+		phy_detach(phy);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(phylink_connect_phy);
 
@@ -1812,8 +1814,17 @@ static void phylink_sfp_link_up(void *upstream)
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 {
 	struct phylink *pl = upstream;
+	int ret;
+
+	ret = phylink_attach_phy(pl, phy, pl->link_config.interface);
+	if (ret < 0)
+		return ret;
+
+	ret = phylink_bringup_phy(pl, phy);
+	if (ret)
+		phy_detach(phy);
 
-	return __phylink_connect_phy(upstream, phy, pl->link_config.interface);
+	return ret;
 }
 
 static void phylink_sfp_disconnect_phy(void *upstream)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (6 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy() Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:07   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings Russell King
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Some SFP+ modules have Clause 45 PHYs embedded on them, which need a
little more handling in order to ensure that they are correctly setup,
as they switch the PHY link mode according to the negotiated speed.

With Clause 22 PHYs, we assumed that they would operate in SGMII mode,
but this assumption is now false.  Adapt phylink to support Clause 45
PHYs on SFP+ modules.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index c32b2c080584..f4c8d50234ed 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -711,7 +711,8 @@ static void phylink_phy_change(struct phy_device *phydev, bool up,
 		    phy_duplex_to_str(phydev->duplex));
 }
 
-static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
+static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
+			       phy_interface_t interface)
 {
 	struct phylink_link_state config;
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
@@ -729,7 +730,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
 	memset(&config, 0, sizeof(config));
 	linkmode_copy(supported, phy->supported);
 	linkmode_copy(config.advertising, phy->advertising);
-	config.interface = pl->link_config.interface;
+	config.interface = interface;
 
 	ret = phylink_validate(pl, supported, &config);
 	if (ret)
@@ -745,6 +746,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
 	mutex_lock(&phy->lock);
 	mutex_lock(&pl->state_mutex);
 	pl->phydev = phy;
+	pl->phy_state.interface = interface;
 	linkmode_copy(pl->supported, supported);
 	linkmode_copy(pl->link_config.advertising, config.advertising);
 
@@ -809,7 +811,7 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
 	if (ret < 0)
 		return ret;
 
-	ret = phylink_bringup_phy(pl, phy);
+	ret = phylink_bringup_phy(pl, phy, pl->link_config.interface);
 	if (ret)
 		phy_detach(phy);
 
@@ -862,7 +864,7 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
 	if (!phy_dev)
 		return -ENODEV;
 
-	ret = phylink_bringup_phy(pl, phy_dev);
+	ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
 	if (ret)
 		phy_detach(phy_dev);
 
@@ -1814,13 +1816,22 @@ static void phylink_sfp_link_up(void *upstream)
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 {
 	struct phylink *pl = upstream;
+	phy_interface_t interface = pl->link_config.interface;
 	int ret;
 
 	ret = phylink_attach_phy(pl, phy, pl->link_config.interface);
 	if (ret < 0)
 		return ret;
 
-	ret = phylink_bringup_phy(pl, phy);
+	/* Clause 45 PHYs switch their Serdes lane between several different
+	 * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G
+	 * speeds.  We really need to know which interface modes the PHY and
+	 * MAC supports to properly work out which linkmodes can be supported.
+	 */
+	if (phy->is_c45)
+		interface = PHY_INTERFACE_MODE_NA;
+
+	ret = phylink_bringup_phy(pl, phy, interface);
 	if (ret)
 		phy_detach(phy);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (7 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:09   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert() Russell King
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Split link_an_mode between the configured setting and the current
operating setting.  This is an important distinction to make when we
need to configure PHY mode for a plugged SFP+ module that does not
use in-band signalling.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 59 ++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 28 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index f4c8d50234ed..204c62026b26 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -48,7 +48,8 @@ struct phylink {
 	unsigned long phylink_disable_state; /* bitmask of disables */
 	struct phy_device *phydev;
 	phy_interface_t link_interface;	/* PHY_INTERFACE_xxx */
-	u8 link_an_mode;		/* MLO_AN_xxx */
+	u8 cfg_link_an_mode;		/* MLO_AN_xxx */
+	u8 cur_link_an_mode;
 	u8 link_port;			/* The current non-phy ethtool port */
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
 
@@ -256,12 +257,12 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
 
 	dn = fwnode_get_named_child_node(fwnode, "fixed-link");
 	if (dn || fwnode_property_present(fwnode, "fixed-link"))
-		pl->link_an_mode = MLO_AN_FIXED;
+		pl->cfg_link_an_mode = MLO_AN_FIXED;
 	fwnode_handle_put(dn);
 
 	if (fwnode_property_read_string(fwnode, "managed", &managed) == 0 &&
 	    strcmp(managed, "in-band-status") == 0) {
-		if (pl->link_an_mode == MLO_AN_FIXED) {
+		if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
 			phylink_err(pl,
 				    "can't use both fixed-link and in-band-status\n");
 			return -EINVAL;
@@ -273,7 +274,7 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
 		phylink_set(pl->supported, Asym_Pause);
 		phylink_set(pl->supported, Pause);
 		pl->link_config.an_enabled = true;
-		pl->link_an_mode = MLO_AN_INBAND;
+		pl->cfg_link_an_mode = MLO_AN_INBAND;
 
 		switch (pl->link_config.interface) {
 		case PHY_INTERFACE_MODE_SGMII:
@@ -333,14 +334,14 @@ static void phylink_mac_config(struct phylink *pl,
 {
 	phylink_dbg(pl,
 		    "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
-		    __func__, phylink_an_mode_str(pl->link_an_mode),
+		    __func__, phylink_an_mode_str(pl->cur_link_an_mode),
 		    phy_modes(state->interface),
 		    phy_speed_to_str(state->speed),
 		    phy_duplex_to_str(state->duplex),
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
 		    state->pause, state->link, state->an_enabled);
 
-	pl->ops->mac_config(pl->config, pl->link_an_mode, state);
+	pl->ops->mac_config(pl->config, pl->cur_link_an_mode, state);
 }
 
 static void phylink_mac_config_up(struct phylink *pl,
@@ -441,7 +442,7 @@ static void phylink_mac_link_up(struct phylink *pl,
 	struct net_device *ndev = pl->netdev;
 
 	pl->cur_interface = link_state.interface;
-	pl->ops->mac_link_up(pl->config, pl->link_an_mode,
+	pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode,
 			     pl->phy_state.interface,
 			     pl->phydev);
 
@@ -461,7 +462,7 @@ static void phylink_mac_link_down(struct phylink *pl)
 
 	if (ndev)
 		netif_carrier_off(ndev);
-	pl->ops->mac_link_down(pl->config, pl->link_an_mode,
+	pl->ops->mac_link_down(pl->config, pl->cur_link_an_mode,
 			       pl->cur_interface);
 	phylink_info(pl, "Link is Down\n");
 }
@@ -480,7 +481,7 @@ static void phylink_resolve(struct work_struct *w)
 	} else if (pl->mac_link_dropped) {
 		link_state.link = false;
 	} else {
-		switch (pl->link_an_mode) {
+		switch (pl->cur_link_an_mode) {
 		case MLO_AN_PHY:
 			link_state = pl->phy_state;
 			phylink_resolve_flow(pl, &link_state);
@@ -648,7 +649,7 @@ struct phylink *phylink_create(struct phylink_config *config,
 		return ERR_PTR(ret);
 	}
 
-	if (pl->link_an_mode == MLO_AN_FIXED) {
+	if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
 		ret = phylink_parse_fixedlink(pl, fwnode);
 		if (ret < 0) {
 			kfree(pl);
@@ -656,6 +657,8 @@ struct phylink *phylink_create(struct phylink_config *config,
 		}
 	}
 
+	pl->cur_link_an_mode = pl->cfg_link_an_mode;
+
 	ret = phylink_register_sfp(pl, fwnode);
 	if (ret < 0) {
 		kfree(pl);
@@ -771,8 +774,8 @@ static int phylink_attach_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_INBAND &&
+	if (WARN_ON(pl->cfg_link_an_mode == MLO_AN_FIXED ||
+		    (pl->cfg_link_an_mode == MLO_AN_INBAND &&
 		     phy_interface_mode_is_8023z(interface))))
 		return -EINVAL;
 
@@ -839,8 +842,8 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
 	int ret;
 
 	/* 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_INBAND &&
+	if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+	    (pl->cfg_link_an_mode == MLO_AN_INBAND &&
 	     phy_interface_mode_is_8023z(pl->link_interface)))
 		return 0;
 
@@ -851,7 +854,7 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
 		phy_node = of_parse_phandle(dn, "phy-device", 0);
 
 	if (!phy_node) {
-		if (pl->link_an_mode == MLO_AN_PHY)
+		if (pl->cfg_link_an_mode == MLO_AN_PHY)
 			return -ENODEV;
 		return 0;
 	}
@@ -914,7 +917,7 @@ int phylink_fixed_state_cb(struct phylink *pl,
 	/* It does not make sense to let the link be overriden unless we use
 	 * MLO_AN_FIXED
 	 */
-	if (pl->link_an_mode != MLO_AN_FIXED)
+	if (pl->cfg_link_an_mode != MLO_AN_FIXED)
 		return -EINVAL;
 
 	mutex_lock(&pl->state_mutex);
@@ -964,7 +967,7 @@ void phylink_start(struct phylink *pl)
 	ASSERT_RTNL();
 
 	phylink_info(pl, "configuring for %s/%s link mode\n",
-		     phylink_an_mode_str(pl->link_an_mode),
+		     phylink_an_mode_str(pl->cur_link_an_mode),
 		     phy_modes(pl->link_config.interface));
 
 	/* Always set the carrier off */
@@ -987,7 +990,7 @@ void phylink_start(struct phylink *pl)
 	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
 	phylink_run_resolve(pl);
 
-	if (pl->link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
+	if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
 		int irq = gpiod_to_irq(pl->link_gpio);
 
 		if (irq > 0) {
@@ -1002,7 +1005,7 @@ void phylink_start(struct phylink *pl)
 		if (irq <= 0)
 			mod_timer(&pl->link_poll, jiffies + HZ);
 	}
-	if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
+	if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
 		mod_timer(&pl->link_poll, jiffies + HZ);
 	if (pl->phydev)
 		phy_start(pl->phydev);
@@ -1129,7 +1132,7 @@ int phylink_ethtool_ksettings_get(struct phylink *pl,
 
 	linkmode_copy(kset->link_modes.supported, pl->supported);
 
-	switch (pl->link_an_mode) {
+	switch (pl->cur_link_an_mode) {
 	case MLO_AN_FIXED:
 		/* We are using fixed settings. Report these as the
 		 * current link settings - and note that these also
@@ -1201,7 +1204,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 		/* If we have a fixed link (as specified by firmware), refuse
 		 * to change link parameters.
 		 */
-		if (pl->link_an_mode == MLO_AN_FIXED &&
+		if (pl->cur_link_an_mode == MLO_AN_FIXED &&
 		    (s->speed != pl->link_config.speed ||
 		     s->duplex != pl->link_config.duplex))
 			return -EINVAL;
@@ -1213,7 +1216,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 		__clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
 	} else {
 		/* If we have a fixed link, refuse to enable autonegotiation */
-		if (pl->link_an_mode == MLO_AN_FIXED)
+		if (pl->cur_link_an_mode == MLO_AN_FIXED)
 			return -EINVAL;
 
 		config.speed = SPEED_UNKNOWN;
@@ -1255,7 +1258,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
 	 * configuration. For a fixed link, this isn't able to change any
 	 * parameters, which just leaves inband mode.
 	 */
-	if (pl->link_an_mode == MLO_AN_INBAND &&
+	if (pl->cur_link_an_mode == MLO_AN_INBAND &&
 	    !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
 		phylink_mac_config(pl, &pl->link_config);
 		phylink_mac_an_restart(pl);
@@ -1345,7 +1348,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
 				   pause->tx_pause);
 	} else if (!test_bit(PHYLINK_DISABLE_STOPPED,
 			     &pl->phylink_disable_state)) {
-		switch (pl->link_an_mode) {
+		switch (pl->cur_link_an_mode) {
 		case MLO_AN_FIXED:
 			/* Should we allow fixed links to change against the config? */
 			phylink_resolve_flow(pl, config);
@@ -1552,7 +1555,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
 	struct phylink_link_state state;
 	int val = 0xffff;
 
-	switch (pl->link_an_mode) {
+	switch (pl->cur_link_an_mode) {
 	case MLO_AN_FIXED:
 		if (phy_id == 0) {
 			phylink_get_fixed_state(pl, &state);
@@ -1580,7 +1583,7 @@ static int phylink_mii_read(struct phylink *pl, unsigned int phy_id,
 static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
 			     unsigned int reg, unsigned int val)
 {
-	switch (pl->link_an_mode) {
+	switch (pl->cur_link_an_mode) {
 	case MLO_AN_FIXED:
 		break;
 
@@ -1753,10 +1756,10 @@ static int phylink_sfp_module_insert(void *upstream,
 		linkmode_copy(pl->link_config.advertising, config.advertising);
 	}
 
-	if (pl->link_an_mode != MLO_AN_INBAND ||
+	if (pl->cur_link_an_mode != MLO_AN_INBAND ||
 	    pl->link_config.interface != config.interface) {
 		pl->link_config.interface = config.interface;
-		pl->link_an_mode = MLO_AN_INBAND;
+		pl->cur_link_an_mode = MLO_AN_INBAND;
 
 		changed = true;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert()
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (8 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:10   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules Russell King
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Split out the configuration step from phylink_sfp_module_insert() so
we can re-use this later.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 47 +++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 204c62026b26..6f9d7d23dabc 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1689,25 +1689,21 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
 	pl->netdev->sfp_bus = NULL;
 }
 
-static int phylink_sfp_module_insert(void *upstream,
-				     const struct sfp_eeprom_id *id)
+static int phylink_sfp_config(struct phylink *pl, u8 mode, u8 port,
+			      const unsigned long *supported,
+			      const unsigned long *advertising)
 {
-	struct phylink *pl = upstream;
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
 	struct phylink_link_state config;
 	phy_interface_t iface;
-	int ret = 0;
 	bool changed;
-	u8 port;
-
-	ASSERT_RTNL();
+	int ret;
 
-	sfp_parse_support(pl->sfp_bus, id, support);
-	port = sfp_parse_port(pl->sfp_bus, id, support);
+	linkmode_copy(support, supported);
 
 	memset(&config, 0, sizeof(config));
-	linkmode_copy(config.advertising, support);
+	linkmode_copy(config.advertising, advertising);
 	config.interface = PHY_INTERFACE_MODE_NA;
 	config.speed = SPEED_UNKNOWN;
 	config.duplex = DUPLEX_UNKNOWN;
@@ -1722,8 +1718,6 @@ static int phylink_sfp_module_insert(void *upstream,
 		return ret;
 	}
 
-	linkmode_copy(support1, support);
-
 	iface = sfp_select_interface(pl->sfp_bus, config.advertising);
 	if (iface == PHY_INTERFACE_MODE_NA) {
 		phylink_err(pl,
@@ -1733,18 +1727,18 @@ static int phylink_sfp_module_insert(void *upstream,
 	}
 
 	config.interface = iface;
+	linkmode_copy(support1, support);
 	ret = phylink_validate(pl, support1, &config);
 	if (ret) {
 		phylink_err(pl, "validation of %s/%s with support %*pb failed: %d\n",
-			    phylink_an_mode_str(MLO_AN_INBAND),
+			    phylink_an_mode_str(mode),
 			    phy_modes(config.interface),
 			    __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret);
 		return ret;
 	}
 
 	phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
-		    phylink_an_mode_str(MLO_AN_INBAND),
-		    phy_modes(config.interface),
+		    phylink_an_mode_str(mode), phy_modes(config.interface),
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 
 	if (phy_interface_mode_is_8023z(iface) && pl->phydev)
@@ -1756,15 +1750,15 @@ static int phylink_sfp_module_insert(void *upstream,
 		linkmode_copy(pl->link_config.advertising, config.advertising);
 	}
 
-	if (pl->cur_link_an_mode != MLO_AN_INBAND ||
+	if (pl->cur_link_an_mode != mode ||
 	    pl->link_config.interface != config.interface) {
 		pl->link_config.interface = config.interface;
-		pl->cur_link_an_mode = MLO_AN_INBAND;
+		pl->cur_link_an_mode = mode;
 
 		changed = true;
 
 		phylink_info(pl, "switched to %s/%s link mode\n",
-			     phylink_an_mode_str(MLO_AN_INBAND),
+			     phylink_an_mode_str(mode),
 			     phy_modes(config.interface));
 	}
 
@@ -1777,6 +1771,21 @@ static int phylink_sfp_module_insert(void *upstream,
 	return ret;
 }
 
+static int phylink_sfp_module_insert(void *upstream,
+				     const struct sfp_eeprom_id *id)
+{
+	struct phylink *pl = upstream;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
+	u8 port;
+
+	ASSERT_RTNL();
+
+	sfp_parse_support(pl->sfp_bus, id, support);
+	port = sfp_parse_port(pl->sfp_bus, id, support);
+
+	return phylink_sfp_config(pl, MLO_AN_INBAND, port, support, support);
+}
+
 static int phylink_sfp_module_start(void *upstream)
 {
 	struct phylink *pl = upstream;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (9 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert() Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:14   ` Andrew Lunn
  2019-12-09 15:19 ` [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work Russell King
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Knowing whether we need to delay the MAC configuration because a module
may have a PHY is useful to phylink to allow NBASE-T modules to work on
systems supporting no more than 2.5G speeds.

This commit allows us to delay such configuration until after the PHY
has been probed by recording the parsed capabilities, and if the module
may have a PHY, doing no more until the module_start() notification is
called.  At that point, we either have a PHY, or we don't.

We move the PHY-based setup a little later, and use the PHYs support
capabilities rather than the EEPROM parsed capabilities to determine
whether we can support the PHY.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 53 +++++++++++++++++++++++++++++++--------
 drivers/net/phy/sfp-bus.c | 28 +++++++++++++++++++++
 include/linux/sfp.h       |  7 ++++++
 3 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 6f9d7d23dabc..c3eda3800357 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -72,6 +72,9 @@ struct phylink {
 	bool mac_link_dropped;
 
 	struct sfp_bus *sfp_bus;
+	bool sfp_may_have_phy;
+	__ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
+	u8 sfp_port;
 };
 
 #define phylink_printk(level, pl, fmt, ...) \
@@ -1689,7 +1692,7 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
 	pl->netdev->sfp_bus = NULL;
 }
 
-static int phylink_sfp_config(struct phylink *pl, u8 mode, u8 port,
+static int phylink_sfp_config(struct phylink *pl, u8 mode,
 			      const unsigned long *supported,
 			      const unsigned long *advertising)
 {
@@ -1762,7 +1765,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode, u8 port,
 			     phy_modes(config.interface));
 	}
 
-	pl->link_port = port;
+	pl->link_port = pl->sfp_port;
 
 	if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
 				 &pl->phylink_disable_state))
@@ -1775,15 +1778,20 @@ static int phylink_sfp_module_insert(void *upstream,
 				     const struct sfp_eeprom_id *id)
 {
 	struct phylink *pl = upstream;
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
-	u8 port;
+	unsigned long *support = pl->sfp_support;
 
 	ASSERT_RTNL();
 
+	linkmode_zero(support);
 	sfp_parse_support(pl->sfp_bus, id, support);
-	port = sfp_parse_port(pl->sfp_bus, id, support);
+	pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support);
 
-	return phylink_sfp_config(pl, MLO_AN_INBAND, port, support, support);
+	/* If this module may have a PHY connecting later, defer until later */
+	pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
+	if (pl->sfp_may_have_phy)
+		return 0;
+
+	return phylink_sfp_config(pl, MLO_AN_INBAND, support, support);
 }
 
 static int phylink_sfp_module_start(void *upstream)
@@ -1791,10 +1799,19 @@ static int phylink_sfp_module_start(void *upstream)
 	struct phylink *pl = upstream;
 
 	/* If this SFP module has a PHY, start the PHY now. */
-	if (pl->phydev)
+	if (pl->phydev) {
 		phy_start(pl->phydev);
+		return 0;
+	}
 
-	return 0;
+	/* If the module may have a PHY but we didn't detect one we
+	 * need to configure the MAC here.
+	 */
+	if (!pl->sfp_may_have_phy)
+		return 0;
+
+	return phylink_sfp_config(pl, MLO_AN_INBAND,
+				  pl->sfp_support, pl->sfp_support);
 }
 
 static void phylink_sfp_module_stop(void *upstream)
@@ -1828,10 +1845,26 @@ static void phylink_sfp_link_up(void *upstream)
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 {
 	struct phylink *pl = upstream;
-	phy_interface_t interface = pl->link_config.interface;
+	phy_interface_t interface;
 	int ret;
 
-	ret = phylink_attach_phy(pl, phy, pl->link_config.interface);
+	/*
+	 * This is the new way of dealing with flow control for PHYs,
+	 * as described by Timur Tabi in commit 529ed1275263 ("net: phy:
+	 * phy drivers should not set SUPPORTED_[Asym_]Pause") except
+	 * using our validate call to the MAC, we rely upon the MAC
+	 * clearing the bits from both supported and advertising fields.
+	 */
+	phy_support_asym_pause(phy);
+
+	/* Do the initial configuration */
+	ret = phylink_sfp_config(pl, ML_AN_INBAND, phy->supported,
+				 phy->advertising);
+	if (ret < 0)
+		return ret;
+
+	interface = pl->link_config.interface;
+	ret = phylink_attach_phy(pl, phy, interface);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index eabc9e3f0a9e..06e6429b8b71 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -103,6 +103,7 @@ static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
 
 	return NULL;
 }
+
 /**
  * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
@@ -178,6 +179,33 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 }
 EXPORT_SYMBOL_GPL(sfp_parse_port);
 
+/**
+ * sfp_may_have_phy() - indicate whether the module may have a PHY
+ * @bus: a pointer to the &struct sfp_bus structure for the sfp module
+ * @id: a pointer to the module's &struct sfp_eeprom_id
+ *
+ * Parse the EEPROM identification given in @id, and return whether
+ * this module may have a PHY.
+ */
+bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
+{
+	if (id->base.e1000_base_t)
+		return true;
+
+	if (id->base.phys_id != SFF8024_ID_DWDM_SFP) {
+		switch (id->base.extended_cc) {
+		case SFF8024_ECC_10GBASE_T_SFI:
+		case SFF8024_ECC_10GBASE_T_SR:
+		case SFF8024_ECC_5GBASE_T:
+		case SFF8024_ECC_2_5GBASE_T:
+			return true;
+		}
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(sfp_may_have_phy);
+
 /**
  * sfp_parse_support() - Parse the eeprom id for supported link modes
  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 66a56396e8e3..38893e4dd0f0 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -533,6 +533,7 @@ struct sfp_upstream_ops {
 #if IS_ENABLED(CONFIG_SFP)
 int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 		   unsigned long *support);
+bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
 void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 		       unsigned long *support);
 phy_interface_t sfp_select_interface(struct sfp_bus *bus,
@@ -556,6 +557,12 @@ static inline int sfp_parse_port(struct sfp_bus *bus,
 	return PORT_OTHER;
 }
 
+static inline bool sfp_may_have_phy(struct sfp_bus *bus,
+				    const struct sfp_eeprom_id *id)
+{
+	return false;
+}
+
 static inline void sfp_parse_support(struct sfp_bus *bus,
 				     const struct sfp_eeprom_id *id,
 				     unsigned long *support)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (10 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:32   ` Florian Fainelli
  2019-12-09 15:19 ` [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver Russell King
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

The Broadcom BCM84881 does not appear to send the SGMII control word
when operating in SGMII mode, which causes network adapters to fail
to link with the PHY, or decide to operate at fixed 1G speed, even if
the PHY negotiated 100M.

Work around this by detecting the Broadcom BCM84881 and switch to phy
mode rather than inband mode.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/phylink.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index c3eda3800357..66b4357ccbda 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1842,10 +1842,20 @@ static void phylink_sfp_link_up(void *upstream)
 	phylink_run_resolve(pl);
 }
 
+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
+ * or 802.3z control word, so inband will not work.
+ */
+static bool phylink_phy_no_inband(struct phy_device *phy)
+{
+	return phy->is_c45 &&
+		(phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150;
+}
+
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 {
 	struct phylink *pl = upstream;
 	phy_interface_t interface;
+	u8 mode;
 	int ret;
 
 	/*
@@ -1857,9 +1867,13 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 	 */
 	phy_support_asym_pause(phy);
 
+	if (phylink_phy_no_inband(phy))
+		mode = MLO_AN_PHY;
+	else
+		mode = MLO_AN_INBAND;
+
 	/* Do the initial configuration */
-	ret = phylink_sfp_config(pl, ML_AN_INBAND, phy->supported,
-				 phy->advertising);
+	ret = phylink_sfp_config(pl, mode, phy->supported, phy->advertising);
 	if (ret < 0)
 		return ret;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (11 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:34   ` Florian Fainelli
  2019-12-09 15:19 ` [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs Russell King
  2019-12-11  1:23 ` [PATCH net-next v2 00/14] Add support for SFP+ copper modules David Miller
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
Methode DM7052 SFPs.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/Kconfig    |   6 +
 drivers/net/phy/Makefile   |   1 +
 drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
 3 files changed, 276 insertions(+)
 create mode 100644 drivers/net/phy/bcm84881.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fe602648b99f..41272106dea9 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -329,6 +329,12 @@ config BROADCOM_PHY
 	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
 	  BCM5481, BCM54810 and BCM5482 PHYs.
 
+config BCM84881_PHY
+	bool "Broadcom BCM84881 PHY"
+	depends on PHYLIB=y
+	---help---
+	  Support the Broadcom BCM84881 PHY.
+
 config CICADA_PHY
 	tristate "Cicada PHYs"
 	---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a03437e091f3..d3b8152443e7 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_BCM87XX_PHY)	+= bcm87xx.o
 obj-$(CONFIG_BCM_CYGNUS_PHY)	+= bcm-cygnus.o
 obj-$(CONFIG_BCM_NET_PHYLIB)	+= bcm-phy-lib.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
+obj-$(CONFIG_BCM84881_PHY)	+= bcm84881.o
 obj-$(CONFIG_CICADA_PHY)	+= cicada.o
 obj-$(CONFIG_CORTINA_PHY)	+= cortina.o
 obj-$(CONFIG_DAVICOM_PHY)	+= davicom.o
diff --git a/drivers/net/phy/bcm84881.c b/drivers/net/phy/bcm84881.c
new file mode 100644
index 000000000000..db59911b9b3c
--- /dev/null
+++ b/drivers/net/phy/bcm84881.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0
+// Broadcom BCM84881 NBASE-T PHY driver, as found on a SFP+ module.
+// Copyright (C) 2019 Russell King, Deep Blue Solutions Ltd.
+//
+// Like the Marvell 88x3310, the Broadcom 84881 changes its host-side
+// interface according to the operating speed between 10GBASE-R,
+// 2500BASE-X and SGMII (but unlike the 88x3310, without the control
+// word).
+//
+// This driver only supports those aspects of the PHY that I'm able to
+// observe and test with the SFP+ module, which is an incomplete subset
+// of what this PHY is able to support. For example, I only assume it
+// supports a single lane Serdes connection, but it may be that the PHY
+// is able to support more than that.
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+enum {
+	MDIO_AN_C22 = 0xffe0,
+};
+
+static int bcm84881_wait_init(struct phy_device *phydev)
+{
+	unsigned int tries = 20;
+	int ret, val;
+
+	do {
+		val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
+		if (val < 0) {
+			ret = val;
+			break;
+		}
+		if (!(val & MDIO_CTRL1_RESET)) {
+			ret = 0;
+			break;
+		}
+		if (!--tries) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+		msleep(100);
+	} while (1);
+
+	if (ret)
+		phydev_err(phydev, "%s failed: %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int bcm84881_config_init(struct phy_device *phydev)
+{
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_2500BASEX:
+	case PHY_INTERFACE_MODE_10GKR:
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int bcm84881_probe(struct phy_device *phydev)
+{
+	/* This driver requires PMAPMD and AN blocks */
+	const u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+
+	if (!phydev->is_c45 ||
+	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int bcm84881_get_features(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = genphy_c45_pma_read_abilities(phydev);
+	if (ret)
+		return ret;
+
+	/* Although the PHY sets bit 1.11.8, it does not support 10M modes */
+	linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+			   phydev->supported);
+	linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
+			   phydev->supported);
+
+	return 0;
+}
+
+static int bcm84881_config_aneg(struct phy_device *phydev)
+{
+	bool changed = false;
+	u32 adv;
+	int ret;
+
+	/* Wait for the PHY to finish initialising, otherwise our
+	 * advertisement may be overwritten.
+	 */
+	ret = bcm84881_wait_init(phydev);
+	if (ret)
+		return ret;
+
+	/* We don't support manual MDI control */
+	phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+
+	/* disabled autoneg doesn't seem to work with this PHY */
+	if (phydev->autoneg == AUTONEG_DISABLE)
+		return -EINVAL;
+
+	ret = genphy_c45_an_config_aneg(phydev);
+	if (ret < 0)
+		return ret;
+	if (ret > 0)
+		changed = true;
+
+	adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
+				     MDIO_AN_C22 + MII_CTRL1000,
+				     ADVERTISE_1000FULL | ADVERTISE_1000HALF,
+				     adv);
+	if (ret < 0)
+		return ret;
+	if (ret > 0)
+		changed = true;
+
+	return genphy_c45_check_and_restart_aneg(phydev, changed);
+}
+
+static int bcm84881_aneg_done(struct phy_device *phydev)
+{
+	int bmsr, val;
+
+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+	if (val < 0)
+		return val;
+
+	bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR);
+	if (bmsr < 0)
+		return val;
+
+	return !!(val & MDIO_AN_STAT1_COMPLETE) &&
+	       !!(bmsr & BMSR_ANEGCOMPLETE);
+}
+
+static int bcm84881_read_status(struct phy_device *phydev)
+{
+	unsigned int mode;
+	int bmsr, val;
+
+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+	if (val < 0)
+		return val;
+
+	if (val & MDIO_AN_CTRL1_RESTART) {
+		phydev->link = 0;
+		return 0;
+	}
+
+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
+	if (val < 0)
+		return val;
+
+	bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR);
+	if (bmsr < 0)
+		return val;
+
+	phydev->autoneg_complete = !!(val & MDIO_AN_STAT1_COMPLETE) &&
+				   !!(bmsr & BMSR_ANEGCOMPLETE);
+	phydev->link = !!(val & MDIO_STAT1_LSTATUS) &&
+		       !!(bmsr & BMSR_LSTATUS);
+	if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+		phydev->link = false;
+
+	if (!phydev->link)
+		return 0;
+
+	linkmode_zero(phydev->lp_advertising);
+	phydev->speed = SPEED_UNKNOWN;
+	phydev->duplex = DUPLEX_UNKNOWN;
+	phydev->pause = 0;
+	phydev->asym_pause = 0;
+	phydev->mdix = 0;
+
+	if (phydev->autoneg_complete) {
+		val = genphy_c45_read_lpa(phydev);
+		if (val < 0)
+			return val;
+
+		val = phy_read_mmd(phydev, MDIO_MMD_AN,
+				   MDIO_AN_C22 + MII_STAT1000);
+		if (val < 0)
+			return val;
+
+		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
+
+		if (phydev->autoneg == AUTONEG_ENABLE)
+			phy_resolve_aneg_linkmode(phydev);
+	}
+
+	if (phydev->autoneg == AUTONEG_DISABLE) {
+		/* disabled autoneg doesn't seem to work, so force the link
+		 * down.
+		 */
+		phydev->link = 0;
+		return 0;
+	}
+
+	/* Set the host link mode - we set the phy interface mode and
+	 * the speed according to this register so that downshift works.
+	 * We leave the duplex setting as per the resolution from the
+	 * above.
+	 */
+	val = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x4011);
+	mode = (val & 0x1e) >> 1;
+	if (mode == 1 || mode == 2)
+		phydev->interface = PHY_INTERFACE_MODE_SGMII;
+	else if (mode == 3)
+		phydev->interface = PHY_INTERFACE_MODE_10GKR;
+	else if (mode == 4)
+		phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
+	switch (mode & 7) {
+	case 1:
+		phydev->speed = SPEED_100;
+		break;
+	case 2:
+		phydev->speed = SPEED_1000;
+		break;
+	case 3:
+		phydev->speed = SPEED_10000;
+		break;
+	case 4:
+		phydev->speed = SPEED_2500;
+		break;
+	case 5:
+		phydev->speed = SPEED_5000;
+		break;
+	}
+
+	return genphy_c45_read_mdix(phydev);
+}
+
+static struct phy_driver bcm84881_drivers[] = {
+	{
+		.phy_id		= 0xae025150,
+		.phy_id_mask	= 0xfffffff0,
+		.name		= "Broadcom BCM84881",
+		.config_init	= bcm84881_config_init,
+		.probe		= bcm84881_probe,
+		.get_features	= bcm84881_get_features,
+		.config_aneg	= bcm84881_config_aneg,
+		.aneg_done	= bcm84881_aneg_done,
+		.read_status	= bcm84881_read_status,
+	},
+};
+
+module_phy_driver(bcm84881_drivers);
+
+/* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */
+static struct mdio_device_id __maybe_unused bcm84881_tbl[] = {
+	{ 0xae025150, 0xfffffff0 },
+	{ },
+};
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("Broadcom BCM84881 PHY driver");
+MODULE_DEVICE_TABLE(mdio, bcm84881_tbl);
+MODULE_LICENSE("GPL");
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (12 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver Russell King
@ 2019-12-09 15:19 ` Russell King
  2019-12-10 17:21   ` Andrew Lunn
  2019-12-11  1:23 ` [PATCH net-next v2 00/14] Add support for SFP+ copper modules David Miller
  14 siblings, 1 reply; 35+ messages in thread
From: Russell King @ 2019-12-09 15:19 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli, Heiner Kallweit; +Cc: David S. Miller, netdev

Some SFP+ modules have a Clause 45 PHY onboard, which is accessible via
the normal I2C address.  Detect 10G BASE-T PHYs which may have an
accessible PHY and probe for it.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp.c | 44 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index d7d2c797c89c..bfe268028154 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1402,12 +1402,12 @@ static void sfp_sm_phy_detach(struct sfp *sfp)
 	sfp->mod_phy = NULL;
 }
 
-static void sfp_sm_probe_phy(struct sfp *sfp)
+static void sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
 {
 	struct phy_device *phy;
 	int err;
 
-	phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
+	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
 	if (phy == ERR_PTR(-ENODEV)) {
 		dev_info(sfp->dev, "no PHY detected\n");
 		return;
@@ -1417,6 +1417,13 @@ static void sfp_sm_probe_phy(struct sfp *sfp)
 		return;
 	}
 
+	err = phy_device_register(phy);
+	if (err) {
+		phy_device_free(phy);
+		dev_err(sfp->dev, "phy_device_register failed: %d\n", err);
+		return;
+	}
+
 	err = sfp_add_phy(sfp->sfp_bus, phy);
 	if (err) {
 		phy_device_remove(phy);
@@ -1487,10 +1494,32 @@ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
 	}
 }
 
+/* Probe a SFP for a PHY device if the module supports copper - the PHY
+ * normally sits at I2C bus address 0x56, and may either be a clause 22
+ * or clause 45 PHY.
+ *
+ * Clause 22 copper SFP modules normally operate in Cisco SGMII mode with
+ * negotiation enabled, but some may be in 1000base-X - which is for the
+ * PHY driver to determine.
+ *
+ * Clause 45 copper SFP+ modules (10G) appear to switch their interface
+ * mode according to the negotiated line speed.
+ */
 static void sfp_sm_probe_for_phy(struct sfp *sfp)
 {
-	if (sfp->id.base.e1000_base_t)
-		sfp_sm_probe_phy(sfp);
+	switch (sfp->id.base.extended_cc) {
+	case SFF8024_ECC_10GBASE_T_SFI:
+	case SFF8024_ECC_10GBASE_T_SR:
+	case SFF8024_ECC_5GBASE_T:
+	case SFF8024_ECC_2_5GBASE_T:
+		sfp_sm_probe_phy(sfp, true);
+		break;
+
+	default:
+		if (sfp->id.base.e1000_base_t)
+			sfp_sm_probe_phy(sfp, false);
+		break;
+	}
 }
 
 static int sfp_module_parse_power(struct sfp *sfp)
@@ -1550,6 +1579,13 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
 		return -EAGAIN;
 	}
 
+	/* DM7052 reports as a high power module, responds to reads (with
+	 * all bytes 0xff) at 0x51 but does not accept writes.  In any case,
+	 * if the bit is already set, we're already in high power mode.
+	 */
+	if (!!(val & BIT(0)) == enable)
+		return 0;
+
 	if (enable)
 		val |= BIT(0);
 	else
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support
  2019-12-09 15:18 ` [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support Russell King
@ 2019-12-10 16:52   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 16:52 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:29PM +0000, Russell King wrote:
> The 100BASE-FX and 100BASE-LX support assumes a PHY is present; this
> is probably an incorrect assumption. In any case, sfp_parse_support()
> will fail such a module. Let's stop pretending we support these
> modules.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes
  2019-12-09 15:18 ` [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes Russell King
@ 2019-12-10 16:53   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 16:53 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:34PM +0000, Russell King wrote:
> We don't need the EEPROM ID to derive the phy interface mode as we can
> derive it merely from the ethtool link modes.  Remove the EEPROM ID
> argument to sfp_select_interface().
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes
  2019-12-09 15:18 ` [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes Russell King
@ 2019-12-10 16:57   ` Andrew Lunn
  2019-12-10 17:21     ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 16:57 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:39PM +0000, Russell King wrote:
> SFF-8024 is used to define various constants re-used in several SFF
> SFP-related specifications.  Split these constants from the enum, and
> rename them to indicate that they're defined by SFF-8024.
> 
> Add and use updated SFF-8024 extended compliance code definitions for
> 10GBASE-T, 5GBASE-T and 2.5GBASE-T modules.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

> +	case SFF8024_CONNECTOR_SG: /* guess */

Does SFF8024 say anything about this, or is it still a guess?

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications
  2019-12-09 15:18 ` [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications Russell King
@ 2019-12-10 16:59   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 16:59 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:44PM +0000, Russell King wrote:
> When dealing with some copper modules, we can't positively know the
> module capabilities are until we have probed the PHY. Without the full
> capabilities, we may end up failing a module that we could otherwise
> drive with a restricted set of capabilities.
> 
> An example of this would be a module with a NBASE-T PHY plugged into
> a host that supports phy interface modes 2500BASE-X and SGMII. The
> PHY supports 10GBASE-R, 5000BASE-X, 2500BASE-X, SGMII interface modes,
> which means a subset of the capabilities are compatible with the host.
> 
> However, reading the module EEPROM leads us to believe that the module
> only supports ethtool link mode 10GBASE-T, which is incompatible with
> the host - and thus results in the module being rejected.
> 
> This patch adds an extra notification which are triggered after the
> SFP module's PHY probe, and a corresponding notification just before
> the PHY is removed.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink
  2019-12-09 15:18 ` [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink Russell King
@ 2019-12-10 17:00   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:00 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:50PM +0000, Russell King wrote:
> Move phy_start() and phy_stop() into the module_start and module_stop
> notifications in phylink, rather than having them in the SFP code.
> This gives phylink responsibility for controlling the PHY, rather
> than having SFP start and stop the PHY state machine.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses
  2019-12-09 15:18 ` [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses Russell King
@ 2019-12-10 17:05   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:05 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:18:55PM +0000, Russell King wrote:
> Some SFP+ modules have PHYs on them just like SFP modules do, except
> they are Clause 45 PHYs.  The I2C protocol used to access them is
> modified slightly in order to send the device address and 16-bit
> register index.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy()
  2019-12-09 15:19 ` [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy() Russell King
@ 2019-12-10 17:06   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:06 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:01PM +0000, Russell King wrote:
> In order to support Clause 45 PHYs on SFP+ modules, which have an
> indeterminant phy interface mode, we need to be able to call
> phylink_bringup_phy() with a different interface mode to that used when
> binding the PHY. Reduce __phylink_connect_phy() to an attach operation,
> and move the call to phylink_bringup_phy() to its call sites.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules
  2019-12-09 15:19 ` [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules Russell King
@ 2019-12-10 17:07   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:07 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:06PM +0000, Russell King wrote:
> Some SFP+ modules have Clause 45 PHYs embedded on them, which need a
> little more handling in order to ensure that they are correctly setup,
> as they switch the PHY link mode according to the negotiated speed.
> 
> With Clause 22 PHYs, we assumed that they would operate in SGMII mode,
> but this assumption is now false.  Adapt phylink to support Clause 45
> PHYs on SFP+ modules.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings
  2019-12-09 15:19 ` [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings Russell King
@ 2019-12-10 17:09   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:09 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:11PM +0000, Russell King wrote:
> Split link_an_mode between the configured setting and the current
> operating setting.  This is an important distinction to make when we
> need to configure PHY mode for a plugged SFP+ module that does not
> use in-band signalling.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert()
  2019-12-09 15:19 ` [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert() Russell King
@ 2019-12-10 17:10   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:10 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:17PM +0000, Russell King wrote:
> Split out the configuration step from phylink_sfp_module_insert() so
> we can re-use this later.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules
  2019-12-09 15:19 ` [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules Russell King
@ 2019-12-10 17:14   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:14 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:22PM +0000, Russell King wrote:
> Knowing whether we need to delay the MAC configuration because a module
> may have a PHY is useful to phylink to allow NBASE-T modules to work on
> systems supporting no more than 2.5G speeds.
> 
> This commit allows us to delay such configuration until after the PHY
> has been probed by recording the parsed capabilities, and if the module
> may have a PHY, doing no more until the module_start() notification is
> called.  At that point, we either have a PHY, or we don't.
> 
> We move the PHY-based setup a little later, and use the PHYs support
> capabilities rather than the EEPROM parsed capabilities to determine
> whether we can support the PHY.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs
  2019-12-09 15:19 ` [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs Russell King
@ 2019-12-10 17:21   ` Andrew Lunn
  0 siblings, 0 replies; 35+ messages in thread
From: Andrew Lunn @ 2019-12-10 17:21 UTC (permalink / raw)
  To: Russell King; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Mon, Dec 09, 2019 at 03:19:38PM +0000, Russell King wrote:
> Some SFP+ modules have a Clause 45 PHY onboard, which is accessible via
> the normal I2C address.  Detect 10G BASE-T PHYs which may have an
> accessible PHY and probe for it.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes
  2019-12-10 16:57   ` Andrew Lunn
@ 2019-12-10 17:21     ` Russell King - ARM Linux admin
  0 siblings, 0 replies; 35+ messages in thread
From: Russell King - ARM Linux admin @ 2019-12-10 17:21 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: Florian Fainelli, Heiner Kallweit, David S. Miller, netdev

On Tue, Dec 10, 2019 at 05:57:16PM +0100, Andrew Lunn wrote:
> On Mon, Dec 09, 2019 at 03:18:39PM +0000, Russell King wrote:
> > SFF-8024 is used to define various constants re-used in several SFF
> > SFP-related specifications.  Split these constants from the enum, and
> > rename them to indicate that they're defined by SFF-8024.
> > 
> > Add and use updated SFF-8024 extended compliance code definitions for
> > 10GBASE-T, 5GBASE-T and 2.5GBASE-T modules.
> > 
> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> 
> > +	case SFF8024_CONNECTOR_SG: /* guess */
> 
> Does SFF8024 say anything about this, or is it still a guess?

SFF-8024 doesn't describe the connectors.  It just gives a table:

            09h        MU (Multiple Optical)
	    0Ah        SG
            0Bh        Optical Pigtail
	    0Ch        MPO 1x12 (Multifiber Parallel Optic)

Searching for "SFP SG connector" or "fiber SG connector" on google
doesn't provide anything useful.  So yes, it remains a guess until
someone can say what it actually is.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work
  2019-12-09 15:19 ` [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work Russell King
@ 2019-12-10 17:32   ` Florian Fainelli
  0 siblings, 0 replies; 35+ messages in thread
From: Florian Fainelli @ 2019-12-10 17:32 UTC (permalink / raw)
  To: Russell King, Andrew Lunn, Heiner Kallweit; +Cc: David S. Miller, netdev

On 12/9/19 7:19 AM, Russell King wrote:
> The Broadcom BCM84881 does not appear to send the SGMII control word
> when operating in SGMII mode, which causes network adapters to fail
> to link with the PHY, or decide to operate at fixed 1G speed, even if
> the PHY negotiated 100M.
> 
> Work around this by detecting the Broadcom BCM84881 and switch to phy
> mode rather than inband mode.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-09 15:19 ` [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver Russell King
@ 2019-12-10 17:34   ` Florian Fainelli
  2019-12-10 17:58     ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 35+ messages in thread
From: Florian Fainelli @ 2019-12-10 17:34 UTC (permalink / raw)
  To: Russell King, Andrew Lunn, Heiner Kallweit; +Cc: David S. Miller, netdev

On 12/9/19 7:19 AM, Russell King wrote:
> Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
> Methode DM7052 SFPs.
> 
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

> ---
>  drivers/net/phy/Kconfig    |   6 +
>  drivers/net/phy/Makefile   |   1 +
>  drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 276 insertions(+)
>  create mode 100644 drivers/net/phy/bcm84881.c
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index fe602648b99f..41272106dea9 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -329,6 +329,12 @@ config BROADCOM_PHY
>  	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
>  	  BCM5481, BCM54810 and BCM5482 PHYs.
>  
> +config BCM84881_PHY
> +	bool "Broadcom BCM84881 PHY"
> +	depends on PHYLIB=y
> +	---help---
> +	  Support the Broadcom BCM84881 PHY.

Cannot we make this tristate, I believe we cannot until there are more
fundamental issues (that you just reported) to be fixed, correct?
-- 
Florian

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-10 17:34   ` Florian Fainelli
@ 2019-12-10 17:58     ` Russell King - ARM Linux admin
  2019-12-10 18:46       ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 35+ messages in thread
From: Russell King - ARM Linux admin @ 2019-12-10 17:58 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, netdev

On Tue, Dec 10, 2019 at 09:34:16AM -0800, Florian Fainelli wrote:
> On 12/9/19 7:19 AM, Russell King wrote:
> > Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
> > Methode DM7052 SFPs.
> > 
> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> 
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> 
> > ---
> >  drivers/net/phy/Kconfig    |   6 +
> >  drivers/net/phy/Makefile   |   1 +
> >  drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
> >  3 files changed, 276 insertions(+)
> >  create mode 100644 drivers/net/phy/bcm84881.c
> > 
> > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> > index fe602648b99f..41272106dea9 100644
> > --- a/drivers/net/phy/Kconfig
> > +++ b/drivers/net/phy/Kconfig
> > @@ -329,6 +329,12 @@ config BROADCOM_PHY
> >  	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
> >  	  BCM5481, BCM54810 and BCM5482 PHYs.
> >  
> > +config BCM84881_PHY
> > +	bool "Broadcom BCM84881 PHY"
> > +	depends on PHYLIB=y
> > +	---help---
> > +	  Support the Broadcom BCM84881 PHY.
> 
> Cannot we make this tristate, I believe we cannot until there are more
> fundamental issues (that you just reported) to be fixed, correct?

Indeed.  The problem I saw was that although the bcm84881 has the
PHY correctly described, for whatever reason, the module was not
loaded.

What I think is going in is that with modern udev userspace,
request_module() is not functional, and we do not publish the
module IDs for Clause 45 PHYs via uevent.  Consequently, there
exists no mechanism to load a Clause 45 PHY driver from the
filesystem.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-10 17:58     ` Russell King - ARM Linux admin
@ 2019-12-10 18:46       ` Russell King - ARM Linux admin
  2019-12-19  0:55         ` Russell King - ARM Linux admin
  0 siblings, 1 reply; 35+ messages in thread
From: Russell King - ARM Linux admin @ 2019-12-10 18:46 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, netdev

On Tue, Dec 10, 2019 at 05:58:37PM +0000, Russell King - ARM Linux admin wrote:
> On Tue, Dec 10, 2019 at 09:34:16AM -0800, Florian Fainelli wrote:
> > On 12/9/19 7:19 AM, Russell King wrote:
> > > Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
> > > Methode DM7052 SFPs.
> > > 
> > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> > 
> > Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> > 
> > > ---
> > >  drivers/net/phy/Kconfig    |   6 +
> > >  drivers/net/phy/Makefile   |   1 +
> > >  drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 276 insertions(+)
> > >  create mode 100644 drivers/net/phy/bcm84881.c
> > > 
> > > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> > > index fe602648b99f..41272106dea9 100644
> > > --- a/drivers/net/phy/Kconfig
> > > +++ b/drivers/net/phy/Kconfig
> > > @@ -329,6 +329,12 @@ config BROADCOM_PHY
> > >  	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
> > >  	  BCM5481, BCM54810 and BCM5482 PHYs.
> > >  
> > > +config BCM84881_PHY
> > > +	bool "Broadcom BCM84881 PHY"
> > > +	depends on PHYLIB=y
> > > +	---help---
> > > +	  Support the Broadcom BCM84881 PHY.
> > 
> > Cannot we make this tristate, I believe we cannot until there are more
> > fundamental issues (that you just reported) to be fixed, correct?
> 
> Indeed.  The problem I saw was that although the bcm84881 has the
> PHY correctly described, for whatever reason, the module was not
> loaded.
> 
> What I think is going in is that with modern udev userspace,
> request_module() is not functional, and we do not publish the
> module IDs for Clause 45 PHYs via uevent.  Consequently, there
> exists no mechanism to load a Clause 45 PHY driver from the
> filesystem.

I just attempted booting with sfp as a module, bcm84881 as a module.
sfp has to be loaded for the SFP cage to be recognised, so module
loading is availble prior to the PHY being known to the kernel.

The SFP is probed, and the PHY identified (via my debug):

[    7.209549] sfp sfp: phy PMA devid: 0xae02 0x5151

The PHY is not bound to its driver at this point.

We then try to connect to the PHY, but the support mask is zero,
so we know nothing about what modes this PHY supports:

[    7.215985] mvneta f1034000.ethernet eno2: phylink_sfp_connect_phy: s=00,00000000,00000000 a=00,00000000,00000000
[    7.215997] mvneta f1034000.ethernet eno2: validation with support 00,00000000,00000000 failed: -22
[    7.226343] sfp sfp: sfp_add_phy failed: -22

and we fail - because we are unable to identify what mode we should
configure the MAC side for, because we have no idea what the
capabilities of the PHY are at this stage.

We can't wait until we've called phylink_attach_phy(), because that
configures the PHY for the phy interface mode that was passed in.

There is no sign of the bcm84881 module being loaded.

This is the opposite problem to the one I recently posted about
regarding the 88e1111 issue, as here we rely on knowing something
about the PHY capabilities.

I think this is showing that phylink has a very difficult job trying
to match the capabilities of the SFP module with the capabilities of
the host MAC - we have no real idea what phy interface modes the
host MAC supports, or how the PHY is going to behave (which of the
many modes the PHY is going to choose for particular speeds.)
Plus the problem that the phylib support mask no longer reflects
the PHYs abilities after phy_attach_direct() has been called.

I thought I had something sorted, but only if the PHY driver is
built-in.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 00/14] Add support for SFP+ copper modules
  2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
                   ` (13 preceding siblings ...)
  2019-12-09 15:19 ` [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs Russell King
@ 2019-12-11  1:23 ` David Miller
  14 siblings, 0 replies; 35+ messages in thread
From: David Miller @ 2019-12-11  1:23 UTC (permalink / raw)
  To: linux; +Cc: andrew, f.fainelli, hkallweit1, netdev

From: Russell King - ARM Linux admin <linux@armlinux.org.uk>
Date: Mon, 9 Dec 2019 15:15:53 +0000

> This series adds support for Copper SFP+ modules with Clause 45 PHYs.
> Specifically the patches:

This series needs some work actually:

1) Patch #6 adds the following warning:

drivers/net/phy/phylink.c: In function ‘phylink_attach_phy’:
drivers/net/phy/phylink.c:770:6: warning: unused variable ‘ret’ [-Wunused-variable]

2) Patch #11 adds a reference to ML_AN_INBAND which breaks the build:

drivers/net/phy/phylink.c: In function ‘phylink_sfp_connect_phy’:
drivers/net/phy/phylink.c:1856:31: error: ‘ML_AN_INBAND’ undeclared (first use in this function); did you mean ‘MLO_AN_INBAND’?
  ret = phylink_sfp_config(pl, ML_AN_INBAND, phy->supported,
                               ^~~~~~~~~~~~
                               MLO_AN_INBAND

3) Patch #12 removes this line.

Please fix the warning and make this patch series properly bisectable.

You have all the ACKs, so once this is fixed up I'll apply it.

Thanks.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-10 18:46       ` Russell King - ARM Linux admin
@ 2019-12-19  0:55         ` Russell King - ARM Linux admin
  2019-12-19  0:57           ` Florian Fainelli
  0 siblings, 1 reply; 35+ messages in thread
From: Russell King - ARM Linux admin @ 2019-12-19  0:55 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, netdev

On Tue, Dec 10, 2019 at 06:46:40PM +0000, Russell King - ARM Linux admin wrote:
> On Tue, Dec 10, 2019 at 05:58:37PM +0000, Russell King - ARM Linux admin wrote:
> > On Tue, Dec 10, 2019 at 09:34:16AM -0800, Florian Fainelli wrote:
> > > On 12/9/19 7:19 AM, Russell King wrote:
> > > > Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
> > > > Methode DM7052 SFPs.
> > > > 
> > > > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> > > 
> > > Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> > > 
> > > > ---
> > > >  drivers/net/phy/Kconfig    |   6 +
> > > >  drivers/net/phy/Makefile   |   1 +
> > > >  drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 276 insertions(+)
> > > >  create mode 100644 drivers/net/phy/bcm84881.c
> > > > 
> > > > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> > > > index fe602648b99f..41272106dea9 100644
> > > > --- a/drivers/net/phy/Kconfig
> > > > +++ b/drivers/net/phy/Kconfig
> > > > @@ -329,6 +329,12 @@ config BROADCOM_PHY
> > > >  	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
> > > >  	  BCM5481, BCM54810 and BCM5482 PHYs.
> > > >  
> > > > +config BCM84881_PHY
> > > > +	bool "Broadcom BCM84881 PHY"
> > > > +	depends on PHYLIB=y
> > > > +	---help---
> > > > +	  Support the Broadcom BCM84881 PHY.
> > > 
> > > Cannot we make this tristate, I believe we cannot until there are more
> > > fundamental issues (that you just reported) to be fixed, correct?
> > 
> > Indeed.  The problem I saw was that although the bcm84881 has the
> > PHY correctly described, for whatever reason, the module was not
> > loaded.
> > 
> > What I think is going in is that with modern udev userspace,
> > request_module() is not functional, and we do not publish the
> > module IDs for Clause 45 PHYs via uevent.  Consequently, there
> > exists no mechanism to load a Clause 45 PHY driver from the
> > filesystem.
> 
> I just attempted booting with sfp as a module, bcm84881 as a module.
> sfp has to be loaded for the SFP cage to be recognised, so module
> loading is availble prior to the PHY being known to the kernel.
> 
> The SFP is probed, and the PHY identified (via my debug):
> 
> [    7.209549] sfp sfp: phy PMA devid: 0xae02 0x5151
> 
> The PHY is not bound to its driver at this point.
> 
> We then try to connect to the PHY, but the support mask is zero,
> so we know nothing about what modes this PHY supports:
> 
> [    7.215985] mvneta f1034000.ethernet eno2: phylink_sfp_connect_phy: s=00,00000000,00000000 a=00,00000000,00000000
> [    7.215997] mvneta f1034000.ethernet eno2: validation with support 00,00000000,00000000 failed: -22
> [    7.226343] sfp sfp: sfp_add_phy failed: -22
> 
> and we fail - because we are unable to identify what mode we should
> configure the MAC side for, because we have no idea what the
> capabilities of the PHY are at this stage.
> 
> We can't wait until we've called phylink_attach_phy(), because that
> configures the PHY for the phy interface mode that was passed in.
> 
> There is no sign of the bcm84881 module being loaded.

Okay, I see what is going on - I just added debug into __request_module,
and got:

[  234.729163] __request_module: mdio:-10101110000000100101000101010001
[  234.732561] __request_module: mdio:-10101110000000100101000101010001
[  234.735729] __request_module: mdio:00000011011000100000000000000000

on inserting this SFP.  This comes from this:

#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
#define MDIO_ID_ARGS(_id) \
        (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1,   \
        ((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
        ((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
        ((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
        ((_id)>>15) & 1, ((_id)>>14) & 1, ((_id)>>13) & 1, ((_id)>>12) & 1, \
        ((_id)>>11) & 1, ((_id)>>10) & 1, ((_id)>>9) & 1, ((_id)>>8) & 1, \
        ((_id)>>7) & 1, ((_id)>>6) & 1, ((_id)>>5) & 1, ((_id)>>4) & 1, \
        ((_id)>>3) & 1, ((_id)>>2) & 1, ((_id)>>1) & 1, (_id) & 1

coupled with:

static int phy_request_driver_module(struct phy_device *dev, int phy_id)
{
...
        ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
                             MDIO_ID_ARGS(phy_id));

The signed-ness of the parameter passed into MDIO_ID_ARGS() matters.
Hence, (0xae025151)>>31 becomes -1, and %d prints it as -1.

phy_id should be u32, just like it is everywhere else in phylib. Also,
MDIO_ID_ARGS() should probably be adapted to not care about the signed-
ness of its argument.

Thoughts?

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver
  2019-12-19  0:55         ` Russell King - ARM Linux admin
@ 2019-12-19  0:57           ` Florian Fainelli
  0 siblings, 0 replies; 35+ messages in thread
From: Florian Fainelli @ 2019-12-19  0:57 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, netdev

On 12/18/19 4:55 PM, Russell King - ARM Linux admin wrote:
> On Tue, Dec 10, 2019 at 06:46:40PM +0000, Russell King - ARM Linux admin wrote:
>> On Tue, Dec 10, 2019 at 05:58:37PM +0000, Russell King - ARM Linux admin wrote:
>>> On Tue, Dec 10, 2019 at 09:34:16AM -0800, Florian Fainelli wrote:
>>>> On 12/9/19 7:19 AM, Russell King wrote:
>>>>> Add a rudimentary Clause 45 driver for the BCM84881 PHY, found on
>>>>> Methode DM7052 SFPs.
>>>>>
>>>>> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>>>>
>>>> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
>>>>
>>>>> ---
>>>>>  drivers/net/phy/Kconfig    |   6 +
>>>>>  drivers/net/phy/Makefile   |   1 +
>>>>>  drivers/net/phy/bcm84881.c | 269 +++++++++++++++++++++++++++++++++++++
>>>>>  3 files changed, 276 insertions(+)
>>>>>  create mode 100644 drivers/net/phy/bcm84881.c
>>>>>
>>>>> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
>>>>> index fe602648b99f..41272106dea9 100644
>>>>> --- a/drivers/net/phy/Kconfig
>>>>> +++ b/drivers/net/phy/Kconfig
>>>>> @@ -329,6 +329,12 @@ config BROADCOM_PHY
>>>>>  	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
>>>>>  	  BCM5481, BCM54810 and BCM5482 PHYs.
>>>>>  
>>>>> +config BCM84881_PHY
>>>>> +	bool "Broadcom BCM84881 PHY"
>>>>> +	depends on PHYLIB=y
>>>>> +	---help---
>>>>> +	  Support the Broadcom BCM84881 PHY.
>>>>
>>>> Cannot we make this tristate, I believe we cannot until there are more
>>>> fundamental issues (that you just reported) to be fixed, correct?
>>>
>>> Indeed.  The problem I saw was that although the bcm84881 has the
>>> PHY correctly described, for whatever reason, the module was not
>>> loaded.
>>>
>>> What I think is going in is that with modern udev userspace,
>>> request_module() is not functional, and we do not publish the
>>> module IDs for Clause 45 PHYs via uevent.  Consequently, there
>>> exists no mechanism to load a Clause 45 PHY driver from the
>>> filesystem.
>>
>> I just attempted booting with sfp as a module, bcm84881 as a module.
>> sfp has to be loaded for the SFP cage to be recognised, so module
>> loading is availble prior to the PHY being known to the kernel.
>>
>> The SFP is probed, and the PHY identified (via my debug):
>>
>> [    7.209549] sfp sfp: phy PMA devid: 0xae02 0x5151
>>
>> The PHY is not bound to its driver at this point.
>>
>> We then try to connect to the PHY, but the support mask is zero,
>> so we know nothing about what modes this PHY supports:
>>
>> [    7.215985] mvneta f1034000.ethernet eno2: phylink_sfp_connect_phy: s=00,00000000,00000000 a=00,00000000,00000000
>> [    7.215997] mvneta f1034000.ethernet eno2: validation with support 00,00000000,00000000 failed: -22
>> [    7.226343] sfp sfp: sfp_add_phy failed: -22
>>
>> and we fail - because we are unable to identify what mode we should
>> configure the MAC side for, because we have no idea what the
>> capabilities of the PHY are at this stage.
>>
>> We can't wait until we've called phylink_attach_phy(), because that
>> configures the PHY for the phy interface mode that was passed in.
>>
>> There is no sign of the bcm84881 module being loaded.
> 
> Okay, I see what is going on - I just added debug into __request_module,
> and got:
> 
> [  234.729163] __request_module: mdio:-10101110000000100101000101010001
> [  234.732561] __request_module: mdio:-10101110000000100101000101010001
> [  234.735729] __request_module: mdio:00000011011000100000000000000000
> 
> on inserting this SFP.  This comes from this:
> 
> #define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
> #define MDIO_ID_ARGS(_id) \
>         (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1,   \
>         ((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
>         ((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
>         ((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
>         ((_id)>>15) & 1, ((_id)>>14) & 1, ((_id)>>13) & 1, ((_id)>>12) & 1, \
>         ((_id)>>11) & 1, ((_id)>>10) & 1, ((_id)>>9) & 1, ((_id)>>8) & 1, \
>         ((_id)>>7) & 1, ((_id)>>6) & 1, ((_id)>>5) & 1, ((_id)>>4) & 1, \
>         ((_id)>>3) & 1, ((_id)>>2) & 1, ((_id)>>1) & 1, (_id) & 1
> 
> coupled with:
> 
> static int phy_request_driver_module(struct phy_device *dev, int phy_id)
> {
> ...
>         ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
>                              MDIO_ID_ARGS(phy_id));
> 
> The signed-ness of the parameter passed into MDIO_ID_ARGS() matters.
> Hence, (0xae025151)>>31 becomes -1, and %d prints it as -1.
> 
> phy_id should be u32, just like it is everywhere else in phylib. Also,
> MDIO_ID_ARGS() should probably be adapted to not care about the signed-
> ness of its argument.
> 
> Thoughts?

Doh, yes that should be fixed, and that does make sense.
-- 
Florian

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2019-12-19  0:58 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-09 15:15 [PATCH net-next v2 00/14] Add support for SFP+ copper modules Russell King - ARM Linux admin
2019-12-09 15:18 ` [PATCH net-next v2 01/14] net: sfp: remove incomplete 100BASE-FX and 100BASE-LX support Russell King
2019-12-10 16:52   ` Andrew Lunn
2019-12-09 15:18 ` [PATCH net-next v2 02/14] net: sfp: derive interface mode from ethtool link modes Russell King
2019-12-10 16:53   ` Andrew Lunn
2019-12-09 15:18 ` [PATCH net-next v2 03/14] net: sfp: add more extended compliance codes Russell King
2019-12-10 16:57   ` Andrew Lunn
2019-12-10 17:21     ` Russell King - ARM Linux admin
2019-12-09 15:18 ` [PATCH net-next v2 04/14] net: sfp: add module start/stop upstream notifications Russell King
2019-12-10 16:59   ` Andrew Lunn
2019-12-09 15:18 ` [PATCH net-next v2 05/14] net: sfp: move phy_start()/phy_stop() to phylink Russell King
2019-12-10 17:00   ` Andrew Lunn
2019-12-09 15:18 ` [PATCH net-next v2 06/14] net: mdio-i2c: add support for Clause 45 accesses Russell King
2019-12-10 17:05   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 07/14] net: phylink: re-split __phylink_connect_phy() Russell King
2019-12-10 17:06   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 08/14] net: phylink: support Clause 45 PHYs on SFP+ modules Russell King
2019-12-10 17:07   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 09/14] net: phylink: split link_an_mode configured and current settings Russell King
2019-12-10 17:09   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 10/14] net: phylink: split phylink_sfp_module_insert() Russell King
2019-12-10 17:10   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 11/14] net: phylink: delay MAC configuration for copper SFP modules Russell King
2019-12-10 17:14   ` Andrew Lunn
2019-12-09 15:19 ` [PATCH net-next v2 12/14] net: phylink: make Broadcom BCM84881 based SFPs work Russell King
2019-12-10 17:32   ` Florian Fainelli
2019-12-09 15:19 ` [PATCH net-next v2 13/14] net: phy: add Broadcom BCM84881 PHY driver Russell King
2019-12-10 17:34   ` Florian Fainelli
2019-12-10 17:58     ` Russell King - ARM Linux admin
2019-12-10 18:46       ` Russell King - ARM Linux admin
2019-12-19  0:55         ` Russell King - ARM Linux admin
2019-12-19  0:57           ` Florian Fainelli
2019-12-09 15:19 ` [PATCH net-next v2 14/14] net: sfp: add support for Clause 45 PHYs Russell King
2019-12-10 17:21   ` Andrew Lunn
2019-12-11  1:23 ` [PATCH net-next v2 00/14] Add support for SFP+ copper modules David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.