netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules
@ 2020-11-16 11:15 Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 1/5] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

Hello,

this is v3 of series adding support for RollBall/Hilink SFP modules.

Checked with:
  checkpatch.pl --max-line-length=80

Changes from v2:
- added comment into the patch adding support for RollBall I2C MDIO
  protocol, saying that we expect the SFP_PAGE not to be changed by
  the SFP code, as requested by Russell. If, in the future, SFP code
  starts modifying SFP_PAGE, we will have to handle it in mdio-i2c
  somehow
- destruction of I2C MDIO bus in patch 3/5 now depends on whether the
  MDIO bus is not NULL, instead of whether PHY exists, as suggested by
  Russell
- changed waiting time for RollBall module to initialize from 30 seconds
  to 25 seconds. Testing shows that it is never longer than 21-22
  seconds, so waiting 25 seconds instead of 30 is IMO safe enough
- added Russell's Reviewed-by tags where relevant

Changes from v1:
- wrapped to 80 columns as per Russell's request
- initialization of RollBall MDIO I2C protocol moved from sfp.c to
  mdio-i2c.c as per Russell's request
- second patch removes the 802.3z check also from phylink_sfp_config
  as suggested by Russell
- creation/destruction of mdiobus for SFP now occurs before probing
  for PHY/after releasing PHY (as suggested by Russell)
- the last patch became a little simpler after the above was done

Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>

Marek Behún (5):
  net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  net: phylink: allow attaching phy for SFP modules on 802.3z mode
  net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY
    release
  net: phy: marvell10g: change MACTYPE if underlying MAC does not
    support it
  net: sfp: add support for multigig RollBall transceivers

 drivers/net/mdio/mdio-i2c.c   | 236 +++++++++++++++++++++++++++++++++-
 drivers/net/phy/marvell10g.c  |  31 +++++
 drivers/net/phy/phylink.c     |   5 +-
 drivers/net/phy/sfp.c         |  65 ++++++++--
 include/linux/mdio/mdio-i2c.h |   8 +-
 5 files changed, 325 insertions(+), 20 deletions(-)


base-commit: 0064c5c1b3bf2a695c772c90e8dea38426a870ff
-- 
2.26.2


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

* [PATCH net-next v3 1/5] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall SFP modules
  2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
@ 2020-11-16 11:15 ` Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 2/5] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

Some multigig SFPs from RollBall and Hilink do not expose functional
MDIO access to the internal PHY of the SFP via I2C address 0x56
(although there seems to be read-only clause 22 access on this address).

Instead these SFPs PHY can be accessed via I2C via the SFP Enhanced
Digital Diagnostic Interface - I2C address 0x51. The SFP_PAGE has to be
selected to 3 and the password must be filled with 0xff bytes for this
PHY communication to work.

This extends the mdio-i2c driver to support this protocol by adding a
special parameter to mdio_i2c_alloc function via which this RollBall
protocol can be selected.

Signed-off-by: Marek Behún <kabel@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/mdio/mdio-i2c.c   | 236 +++++++++++++++++++++++++++++++++-
 drivers/net/phy/sfp.c         |   2 +-
 include/linux/mdio/mdio-i2c.h |   8 +-
 3 files changed, 239 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mdio/mdio-i2c.c b/drivers/net/mdio/mdio-i2c.c
index 09200a70b315..2e26bf1c81d1 100644
--- a/drivers/net/mdio/mdio-i2c.c
+++ b/drivers/net/mdio/mdio-i2c.c
@@ -3,6 +3,7 @@
  * MDIO I2C bridge
  *
  * Copyright (C) 2015-2016 Russell King
+ * Copyright (C) 2020 Marek Behun
  *
  * Network PHYs can appear on I2C buses when they are part of SFP module.
  * This driver exposes these PHYs to the networking PHY code, allowing
@@ -12,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/mdio/mdio-i2c.h>
 #include <linux/phy.h>
+#include <linux/sfp.h>
 
 /*
  * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
@@ -28,7 +30,7 @@ static unsigned int i2c_mii_phy_addr(int phy_id)
 	return phy_id + 0x40;
 }
 
-static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
+static int i2c_mii_read_default(struct mii_bus *bus, int phy_id, int reg)
 {
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msgs[2];
@@ -62,7 +64,8 @@ static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
 	return data[0] << 8 | data[1];
 }
 
-static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+static int i2c_mii_write_default(struct mii_bus *bus, int phy_id, int reg,
+				 u16 val)
 {
 	struct i2c_adapter *i2c = bus->priv;
 	struct i2c_msg msg;
@@ -91,9 +94,214 @@ static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
 	return ret < 0 ? ret : 0;
 }
 
-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
+/* RollBall SFPs do not access internal PHY via I2C address 0x56, but
+ * instead via address 0x51, when SFP page is set to 0x03 and password to
+ * 0xffffffff.
+ * Since current SFP code does not modify SFP_PAGE, we set it to 0x03 only at
+ * bus creation time, and expect it to remain set to 0x03 throughout the
+ * lifetime of the module plugged into the system. If the SFP code starts
+ * modifying SFP_PAGE in the future, this code will need to change.
+ *
+ * address  size  contents  description
+ * -------  ----  --------  -----------
+ * 0x80     1     CMD       0x01/0x02/0x04 for write/read/done
+ * 0x81     1     DEV       Clause 45 device
+ * 0x82     2     REG       Clause 45 register
+ * 0x84     2     VAL       Register value
+ */
+#define ROLLBALL_PHY_I2C_ADDR		0x51
+#define ROLLBALL_SFP_PASSWORD_ADDR	0x7b
+
+#define ROLLBALL_CMD_ADDR		0x80
+#define ROLLBALL_DATA_ADDR		0x81
+
+#define ROLLBALL_CMD_WRITE		0x01
+#define ROLLBALL_CMD_READ		0x02
+#define ROLLBALL_CMD_DONE		0x04
+
+static int i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
+				 size_t len)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msgs[2];
+	u8 buf0[2], *res;
+	int i, ret;
+
+	buf0[0] = ROLLBALL_CMD_ADDR;
+
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &buf0[0];
+
+	res = buf ? buf : &buf0[1];
+
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = buf ? len : 1;
+	msgs[1].buf = res;
+
+	/* By experiment it takes up to 70 ms to access a register for these
+	 * SFPs. Sleep 20ms between iteratios and try 10 times.
+	 */
+	i = 10;
+	do {
+		msleep(20);
+
+		ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs));
+		if (ret < 0)
+			return ret;
+		else if (ret != ARRAY_SIZE(msgs))
+			return -EIO;
+
+		if (*res == ROLLBALL_CMD_DONE)
+			return 0;
+	} while (i-- > 0);
+
+	dev_dbg(&bus->dev, "poll timed out\n");
+
+	return -ETIMEDOUT;
+}
+
+static int i2c_rollball_mii_cmd(struct mii_bus *bus, int bus_addr, u8 cmd,
+				u8 *data, size_t len)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msgs[2];
+	u8 cmdbuf[2];
+	int ret;
+
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = len;
+	msgs[0].buf = data;
+
+	cmdbuf[0] = ROLLBALL_CMD_ADDR;
+	cmdbuf[1] = cmd;
+
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = 0;
+	msgs[1].len = sizeof(cmdbuf);
+	msgs[1].buf = cmdbuf;
+
+	ret = i2c_transfer(i2c, msgs, 2);
+	if (ret < 0)
+		return ret;
+
+	return ret == ARRAY_SIZE(msgs) ? 0 : -EIO;
+}
+
+static int i2c_mii_read_rollball(struct mii_bus *bus, int phy_id, int reg)
+{
+	u8 buf[4], res[6];
+	int bus_addr, ret;
+	u16 val;
+
+	if (!(reg & MII_ADDR_C45))
+		return -EOPNOTSUPP;
+
+	bus_addr = i2c_mii_phy_addr(phy_id);
+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
+		return 0xffff;
+
+	buf[0] = ROLLBALL_DATA_ADDR;
+	buf[1] = (reg >> 16) & 0x1f;
+	buf[2] = (reg >> 8) & 0xff;
+	buf[3] = reg & 0xff;
+
+	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_READ, buf,
+				   sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_rollball_mii_poll(bus, bus_addr, res, sizeof(res));
+	if (ret == -ETIMEDOUT)
+		return 0xffff;
+	else if (ret < 0)
+		return ret;
+
+	val = res[4] << 8 | res[5];
+
+	dev_dbg(&bus->dev, "read reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
+		reg & 0xffff, val);
+
+	return val;
+}
+
+static int i2c_mii_write_rollball(struct mii_bus *bus, int phy_id, int reg,
+				  u16 val)
+{
+	int bus_addr, ret;
+	u8 buf[6];
+
+	if (!(reg & MII_ADDR_C45))
+		return -EOPNOTSUPP;
+
+	bus_addr = i2c_mii_phy_addr(phy_id);
+	if (bus_addr != ROLLBALL_PHY_I2C_ADDR)
+		return 0;
+
+	buf[0] = ROLLBALL_DATA_ADDR;
+	buf[1] = (reg >> 16) & 0x1f;
+	buf[2] = (reg >> 8) & 0xff;
+	buf[3] = reg & 0xff;
+	buf[4] = val >> 8;
+	buf[5] = val & 0xff;
+
+	ret = i2c_rollball_mii_cmd(bus, bus_addr, ROLLBALL_CMD_WRITE, buf,
+				   sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_rollball_mii_poll(bus, bus_addr, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&bus->dev, "write reg %02x:%04x = %04x\n", (reg >> 16) & 0x1f,
+		reg & 0xffff, val);
+
+	return 0;
+}
+
+static int i2c_mii_init_rollball(struct i2c_adapter *i2c)
+{
+	u8 page_buf[2], pw_buf[5];
+	struct i2c_msg msgs[2];
+	int ret;
+
+	page_buf[0] = SFP_PAGE;
+	page_buf[1] = 3;
+
+	msgs[0].addr = ROLLBALL_PHY_I2C_ADDR;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(page_buf);
+	msgs[0].buf = page_buf;
+
+	pw_buf[0] = ROLLBALL_SFP_PASSWORD_ADDR;
+	pw_buf[1] = 0xff;
+	pw_buf[2] = 0xff;
+	pw_buf[3] = 0xff;
+	pw_buf[4] = 0xff;
+
+	msgs[1].addr = ROLLBALL_PHY_I2C_ADDR;
+	msgs[1].flags = 0;
+	msgs[1].len = sizeof(pw_buf);
+	msgs[1].buf = pw_buf;
+
+	ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		return ret;
+	else if (ret != ARRAY_SIZE(msgs))
+		return -EIO;
+
+	return 0;
+}
+
+struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
+			       enum mdio_i2c_proto protocol)
 {
 	struct mii_bus *mii;
+	int ret;
 
 	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
 		return ERR_PTR(-EINVAL);
@@ -104,10 +312,28 @@ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
 
 	snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent));
 	mii->parent = parent;
-	mii->read = i2c_mii_read;
-	mii->write = i2c_mii_write;
 	mii->priv = i2c;
 
+	switch (protocol) {
+	case MDIO_I2C_ROLLBALL:
+		ret = i2c_mii_init_rollball(i2c);
+		if (ret < 0) {
+			dev_err(parent,
+				"Cannot initialize RollBall MDIO I2C protocol: %d\n",
+				ret);
+			mdiobus_free(mii);
+			return ERR_PTR(ret);
+		}
+
+		mii->read = i2c_mii_read_rollball;
+		mii->write = i2c_mii_write_rollball;
+		break;
+	default:
+		mii->read = i2c_mii_read_default;
+		mii->write = i2c_mii_write_default;
+		break;
+	}
+
 	return mii;
 }
 EXPORT_SYMBOL_GPL(mdio_i2c_alloc);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 34aa196b7465..3a4f34e5365a 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -409,7 +409,7 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	sfp->read = sfp_i2c_read;
 	sfp->write = sfp_i2c_write;
 
-	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c);
+	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
 	if (IS_ERR(i2c_mii))
 		return PTR_ERR(i2c_mii);
 
diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
index b1d27f7cd23f..53eedb0dc1d3 100644
--- a/include/linux/mdio/mdio-i2c.h
+++ b/include/linux/mdio/mdio-i2c.h
@@ -11,6 +11,12 @@ struct device;
 struct i2c_adapter;
 struct mii_bus;
 
-struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
+enum mdio_i2c_proto {
+	MDIO_I2C_DEFAULT,
+	MDIO_I2C_ROLLBALL,
+};
+
+struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
+			       enum mdio_i2c_proto protocol);
 
 #endif
-- 
2.26.2


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

* [PATCH net-next v3 2/5] net: phylink: allow attaching phy for SFP modules on 802.3z mode
  2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 1/5] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
@ 2020-11-16 11:15 ` Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 3/5] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

Some SFPs may contain an internal PHY which may in some cases want to
connect with the host interface in 1000base-x/2500base-x mode.
Do not fail if such PHY is being attached in one of these PHY interface
modes.

Signed-off-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/phylink.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 5d8c015bc9f2..705c49c37348 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1018,7 +1018,7 @@ static int phylink_attach_phy(struct phylink *pl, struct phy_device *phy,
 {
 	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))))
+		     phy_interface_mode_is_8023z(interface) && !pl->sfp_bus)))
 		return -EINVAL;
 
 	if (pl->phydev)
@@ -2069,9 +2069,6 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
 		    phylink_an_mode_str(mode), phy_modes(config.interface),
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 
-	if (phy_interface_mode_is_8023z(iface) && pl->phydev)
-		return -EINVAL;
-
 	changed = !linkmode_equal(pl->supported, support);
 	if (changed) {
 		linkmode_copy(pl->supported, support);
-- 
2.26.2


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

* [PATCH net-next v3 3/5] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release
  2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 1/5] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 2/5] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
@ 2020-11-16 11:15 ` Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 5/5] net: sfp: add support for multigig RollBall transceivers Marek Behún
  4 siblings, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

Instead of configuring the I2C mdiobus when SFP driver is probed,
create/destroy the mdiobus before the PHY is probed for/after it is
released.

This way we can tell the mdio-i2c code which protocol to use for each
SFP transceiver.

Signed-off-by: Marek Behún <kabel@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 3a4f34e5365a..c486caabb44a 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -217,6 +217,7 @@ struct sfp {
 	struct i2c_adapter *i2c;
 	struct mii_bus *i2c_mii;
 	struct sfp_bus *sfp_bus;
+	enum mdio_i2c_proto mdio_protocol;
 	struct phy_device *mod_phy;
 	const struct sff_data *type;
 	u32 max_power_mW;
@@ -399,9 +400,6 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
 
 static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 {
-	struct mii_bus *i2c_mii;
-	int ret;
-
 	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
 		return -EINVAL;
 
@@ -409,7 +407,15 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	sfp->read = sfp_i2c_read;
 	sfp->write = sfp_i2c_write;
 
-	i2c_mii = mdio_i2c_alloc(sfp->dev, i2c, MDIO_I2C_DEFAULT);
+	return 0;
+}
+
+static int sfp_i2c_mdiobus_create(struct sfp *sfp)
+{
+	struct mii_bus *i2c_mii;
+	int ret;
+
+	i2c_mii = mdio_i2c_alloc(sfp->dev, sfp->i2c, sfp->mdio_protocol);
 	if (IS_ERR(i2c_mii))
 		return PTR_ERR(i2c_mii);
 
@@ -427,6 +433,12 @@ static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
 	return 0;
 }
 
+static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
+{
+	mdiobus_unregister(sfp->i2c_mii);
+	sfp->i2c_mii = NULL;
+}
+
 /* Interface */
 static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
 {
@@ -1768,6 +1780,8 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
 	else
 		sfp->module_t_start_up = T_START_UP;
 
+	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
+
 	return 0;
 }
 
@@ -1938,6 +1952,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 			sfp_module_stop(sfp->sfp_bus);
 		if (sfp->mod_phy)
 			sfp_sm_phy_detach(sfp);
+		if (sfp->i2c_mii)
+			sfp_i2c_mdiobus_destroy(sfp);
 		sfp_module_tx_disable(sfp);
 		sfp_soft_stop_poll(sfp);
 		sfp_sm_next(sfp, SFP_S_DOWN, 0);
@@ -2000,6 +2016,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 				     sfp->sm_fault_retries == N_FAULT_INIT);
 		} else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
 	init_done:
+			/* Create mdiobus and start trying for PHY */
+			ret = sfp_i2c_mdiobus_create(sfp);
+			if (ret < 0) {
+				sfp_sm_next(sfp, SFP_S_FAIL, 0);
+				break;
+			}
 			sfp->sm_phy_retries = R_PHY_RETRY;
 			goto phy_probe;
 		}
-- 
2.26.2


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

* [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it
  2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
                   ` (2 preceding siblings ...)
  2020-11-16 11:15 ` [PATCH net-next v3 3/5] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
@ 2020-11-16 11:15 ` Marek Behún
  2020-11-16 12:18   ` Marek Behún
  2020-11-16 14:45   ` Marek Behún
  2020-11-16 11:15 ` [PATCH net-next v3 5/5] net: sfp: add support for multigig RollBall transceivers Marek Behún
  4 siblings, 2 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

RollBall SFPs contain a Marvell 88X3310 PHY, but by default the MACTYPE
is set to 10GBASE-R with Rate Matching.

Some devices (for example those based on Armada 38x) only support up to
2500base-x SerDes modes.

Change the PHY's MACTYPE to 4 (which means changing between 10gbase-r,
5gbase-r, 2500base-x ans SGMII depending on copper speed) if this is the
case (which is infered from phydev->interface).

Signed-off-by: Marek Behún <kabel@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/marvell10g.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 1901ba277413..9e8e9aa66972 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -453,6 +453,33 @@ static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
 		MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
 }
 
+static int mv3310_select_mactype(struct phy_device *phydev)
+{
+	int mac_type, ret;
+
+	/* On some devices the MAC does not support 10G mode, but may support
+	 * lower modes, such as SGMII or 2500base-x.
+	 * By changing MACTYPE of the PHY to 4 in this case, we ensure that
+	 * the MAC will link with the PHY at least for these lower speeds.
+	 */
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_2500BASEX:
+		mac_type = 4;
+		break;
+	default:
+		return 0;
+	}
+
+	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+				     MV_V2_PORT_MAC_TYPE_MASK, mac_type);
+	if (ret <= 0)
+		return ret;
+
+	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
+			      MV_V2_PORT_CTRL_SWRST, MV_V2_PORT_CTRL_SWRST);
+}
+
 static int mv3310_config_init(struct phy_device *phydev)
 {
 	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
@@ -474,6 +501,10 @@ static int mv3310_config_init(struct phy_device *phydev)
 	if (err)
 		return err;
 
+	err = mv3310_select_mactype(phydev);
+	if (err)
+		return err;
+
 	val = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
 	if (val < 0)
 		return val;
-- 
2.26.2


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

* [PATCH net-next v3 5/5] net: sfp: add support for multigig RollBall transceivers
  2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
                   ` (3 preceding siblings ...)
  2020-11-16 11:15 ` [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it Marek Behún
@ 2020-11-16 11:15 ` Marek Behún
  4 siblings, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 11:15 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Marek Behún, Andrew Lunn

This adds support for multigig copper SFP modules from RollBall/Hilink.
These modules have a specific way to access clause 45 registers of the
internal PHY.

We also need to wait at least 22 seconds after deasserting TX disable
before accessing the PHY. The code waits for 25 seconds just to be sure.

Signed-off-by: Marek Behún <kabel@kernel.org>
Reviewed-by: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/sfp.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index c486caabb44a..1a61eaae643b 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -165,6 +165,7 @@ static const enum gpiod_flags gpio_flags[] = {
  * on board (for a copper SFP) time to initialise.
  */
 #define T_WAIT			msecs_to_jiffies(50)
+#define T_WAIT_ROLLBALL		msecs_to_jiffies(25000)
 #define T_START_UP		msecs_to_jiffies(300)
 #define T_START_UP_BAD_GPON	msecs_to_jiffies(60000)
 
@@ -204,8 +205,11 @@ static const enum gpiod_flags gpio_flags[] = {
 
 /* SFP modules appear to always have their PHY configured for bus address
  * 0x56 (which with mdio-i2c, translates to a PHY address of 22).
+ * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface
+ * via address 0x51 (mdio-i2c will use RollBall protocol on this address).
  */
-#define SFP_PHY_ADDR	22
+#define SFP_PHY_ADDR		22
+#define SFP_PHY_ADDR_ROLLBALL	17
 
 struct sff_data {
 	unsigned int gpios;
@@ -218,6 +222,7 @@ struct sfp {
 	struct mii_bus *i2c_mii;
 	struct sfp_bus *sfp_bus;
 	enum mdio_i2c_proto mdio_protocol;
+	int phy_addr;
 	struct phy_device *mod_phy;
 	const struct sff_data *type;
 	u32 max_power_mW;
@@ -249,6 +254,7 @@ struct sfp {
 	struct sfp_eeprom_id id;
 	unsigned int module_power_mW;
 	unsigned int module_t_start_up;
+	unsigned int module_t_wait;
 
 #if IS_ENABLED(CONFIG_HWMON)
 	struct sfp_diag diag;
@@ -1443,7 +1449,7 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
 	struct phy_device *phy;
 	int err;
 
-	phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
+	phy = get_phy_device(sfp->i2c_mii, sfp->phy_addr, is_c45);
 	if (phy == ERR_PTR(-ENODEV))
 		return PTR_ERR(phy);
 	if (IS_ERR(phy)) {
@@ -1781,6 +1787,22 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
 		sfp->module_t_start_up = T_START_UP;
 
 	sfp->mdio_protocol = MDIO_I2C_DEFAULT;
+	sfp->phy_addr = SFP_PHY_ADDR;
+	sfp->module_t_wait = T_WAIT;
+
+	if (((!memcmp(id.base.vendor_name, "OEM             ", 16) ||
+	      !memcmp(id.base.vendor_name, "Turris          ", 16)) &&
+	     (!memcmp(id.base.vendor_pn, "SFP-10G-T       ", 16) ||
+	      !memcmp(id.base.vendor_pn, "RTSFP-10", 8)))) {
+		sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
+		sfp->phy_addr = SFP_PHY_ADDR_ROLLBALL;
+		sfp->module_t_wait = T_WAIT_ROLLBALL;
+
+		/* RollBall SFPs may have wrong (zero) extended compliacne code
+		 * burned in EEPROM. For PHY probing we need the correct one.
+		 */
+		id.base.extended_cc = SFF8024_ECC_10GBASE_T_SFI;
+	}
 
 	return 0;
 }
@@ -1977,9 +1999,10 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 
 		/* We need to check the TX_FAULT state, which is not defined
 		 * while TX_DISABLE is asserted. The earliest we want to do
-		 * anything (such as probe for a PHY) is 50ms.
+		 * anything (such as probe for a PHY) is 50ms (or more on
+		 * specific modules).
 		 */
-		sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
+		sfp_sm_next(sfp, SFP_S_WAIT, sfp->module_t_wait);
 		break;
 
 	case SFP_S_WAIT:
@@ -1993,8 +2016,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
 			 * deasserting.
 			 */
 			timeout = sfp->module_t_start_up;
-			if (timeout > T_WAIT)
-				timeout -= T_WAIT;
+			if (timeout > sfp->module_t_wait)
+				timeout -= sfp->module_t_wait;
 			else
 				timeout = 1;
 
-- 
2.26.2


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

* Re: [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it
  2020-11-16 11:15 ` [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it Marek Behún
@ 2020-11-16 12:18   ` Marek Behún
  2020-11-16 14:45   ` Marek Behún
  1 sibling, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 12:18 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Andrew Lunn

> 5gbase-r, 2500base-x ans SGMII depending on copper speed) if this is the

s/ans/and/

It would seem I have a consistent problem with this typo. Should I send
another version?

Marek

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

* Re: [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it
  2020-11-16 11:15 ` [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it Marek Behún
  2020-11-16 12:18   ` Marek Behún
@ 2020-11-16 14:45   ` Marek Behún
  2020-11-16 15:02     ` Russell King - ARM Linux admin
  1 sibling, 1 reply; 10+ messages in thread
From: Marek Behún @ 2020-11-16 14:45 UTC (permalink / raw)
  To: Russell King, netdev, davem, Jakub Kicinski; +Cc: Andrew Lunn

Hi Russell,

previously you replied on this patch:

> This'll do as a stop-gap until we have a better way to determine which
> MACTYPE mode we should be using.

Can we consider this as Acked-by ?

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

* Re: [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it
  2020-11-16 14:45   ` Marek Behún
@ 2020-11-16 15:02     ` Russell King - ARM Linux admin
  2020-11-16 15:56       ` Marek Behún
  0 siblings, 1 reply; 10+ messages in thread
From: Russell King - ARM Linux admin @ 2020-11-16 15:02 UTC (permalink / raw)
  To: Marek Behún; +Cc: netdev, davem, Jakub Kicinski, Andrew Lunn

On Mon, Nov 16, 2020 at 03:45:52PM +0100, Marek Behún wrote:
> Hi Russell,
> 
> previously you replied on this patch:
> 
> > This'll do as a stop-gap until we have a better way to determine which
> > MACTYPE mode we should be using.
> 
> Can we consider this as Acked-by ?

Not really.

The selection of MACTYPE isn't as simple as you make out in this patch.
If we know that the MAC supports 2500BASE-X and/or SGMII, that means
MACTYPES 0, 3, 4, 5 are possible to fit that, all likely will work if
we restrict the PHY to either 2.5G only or 1G..10M only. However, it
only becomes important if the faster speeds are supported at the MAC.

I'm afraid I haven't put much thought into how to solve it, and as I'm
totally demotivated at the moment, that's unlikely to change.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

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

* Re: [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it
  2020-11-16 15:02     ` Russell King - ARM Linux admin
@ 2020-11-16 15:56       ` Marek Behún
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Behún @ 2020-11-16 15:56 UTC (permalink / raw)
  To: Russell King - ARM Linux admin; +Cc: netdev, davem, Jakub Kicinski, Andrew Lunn

On Mon, 16 Nov 2020 15:02:16 +0000
Russell King - ARM Linux admin <linux@armlinux.org.uk> wrote:

> On Mon, Nov 16, 2020 at 03:45:52PM +0100, Marek Behún wrote:
> > Hi Russell,
> > 
> > previously you replied on this patch:
> >   
> > > This'll do as a stop-gap until we have a better way to determine which
> > > MACTYPE mode we should be using.  
> > 
> > Can we consider this as Acked-by ?  
> 
> Not really.
> 
> The selection of MACTYPE isn't as simple as you make out in this patch.

Hi Russell,

I know that. The idea behind this patch is to add support for at least
something (for MACs supporting 1G/2.5G, but not 10G) in a simple way.
Full support can be added later, since it requires changes into other
subsystems (the experimental patches in your repo).

The question therefore IMO is whether this will introduce regression or
not.

> If we know that the MAC supports 2500BASE-X and/or SGMII, that means
> MACTYPES 0, 3, 4, 5 are possible to fit that, all likely will work if
> we restrict the PHY to either 2.5G only or 1G..10M only. However, it
> only becomes important if the faster speeds are supported at the MAC.

OK, but by applying this patch a regression could possibly occur only
if (and shouldn't anyway, see below):
- MAC supports 10G mode, but only XAUI/RXAUI, not XFI
- mactype is by default set to 1 (XAUI with rate matching) or 2 (RXAUI
  with rate matching) or 7 (USXGMII)
- before config_init, phydev->interface mode is 2500base-x or sgmii

The question is whether someone uses such a configuration and expects
the PHY driver to change phydev->interface.

Anyway a regression should not occur anyway (i.e. this patch should't
break something that did work previously), because even if XAUI/RXAUI
with rate matching or USXGMII was selected by default on the PHY, the
mv3310_update_interface does not support this modes currently
(only 10gbase-r, 2500base-x and sgmii).

So unless the MAC driver ignores the changed phydev->interface, this
patch should not break anything.

If it does cause a regression in spite of the points above, we can
condition the mactype change to occur only if the mactype before the
change was 6 (XFI with rate matching).
Or map the change like so:
  1 -> 3   XAUI with RM ->  XAUI/5gbase-r/2500base-x/SGMII
  2 -> 0  RXAUI with RM -> RXAUI/5gbase-r/2500base-x/SGMII
  6 -> 4    XFI with RM ->   XFI/5gbase-r/2500base-x/SGMII

I can put these thought into the commit message, if requested.

> I'm afraid I haven't put much thought into how to solve it, and as I'm
> totally demotivated at the moment, that's unlikely to change.

I am sorry to hear that, Russell :-(

Usually for me a lack of motivation is caused by bad mood (and also
vice-versa, so this can result in a self-feeding loop).

What I found that helps me with this is a good book to read.
If you are open to suggestions, the (IMO) best book I ever read is
Harry Potter and the Methods of Rationality (it's for free and online).

Marek

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

end of thread, other threads:[~2020-11-16 15:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-16 11:15 [PATCH net-next v3 0/5] Support for RollBall 10G copper SFP modules Marek Behún
2020-11-16 11:15 ` [PATCH net-next v3 1/5] net: phy: mdio-i2c: support I2C MDIO protocol for RollBall " Marek Behún
2020-11-16 11:15 ` [PATCH net-next v3 2/5] net: phylink: allow attaching phy for SFP modules on 802.3z mode Marek Behún
2020-11-16 11:15 ` [PATCH net-next v3 3/5] net: sfp: create/destroy I2C mdiobus before PHY probe/after PHY release Marek Behún
2020-11-16 11:15 ` [PATCH net-next v3 4/5] net: phy: marvell10g: change MACTYPE if underlying MAC does not support it Marek Behún
2020-11-16 12:18   ` Marek Behún
2020-11-16 14:45   ` Marek Behún
2020-11-16 15:02     ` Russell King - ARM Linux admin
2020-11-16 15:56       ` Marek Behún
2020-11-16 11:15 ` [PATCH net-next v3 5/5] net: sfp: add support for multigig RollBall transceivers Marek Behún

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).