[][kernel][common][eth][Add debug information to the SFP]

[Description]
Add debug information to the SFP.

In this patch, we provide the following information to assist
users in easily locating issues.
  - Dump SFP state machine
  - Dump System/Line interface status
  - Dump SFP, PHY, and Host link mode
If debug messages is too annoying, user can disable it by "dmesg -n 7"
command.

Without this patch, users cannot locate SFP issues easily.

[Release-log]
N/A


Change-Id: I567ed96bfb489cecb1887cd08518d01a7ed33657
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7714996
diff --git a/target/linux/mediatek/patches-5.4/999-2727-net-phy-sfp-add-debug-info.patch.patch b/target/linux/mediatek/patches-5.4/999-2727-net-phy-sfp-add-debug-info.patch.patch
new file mode 100644
index 0000000..593ddb1
--- /dev/null
+++ b/target/linux/mediatek/patches-5.4/999-2727-net-phy-sfp-add-debug-info.patch.patch
@@ -0,0 +1,211 @@
+From 76314e98504e691f17a5d9d1362d476c534a5e0e Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Fri, 7 Jul 2023 11:14:32 +0800
+Subject: [PATCH] 999-2727-net-phy-sfp-add-debug-info.patch
+
+---
+ drivers/net/phy/phylink.c     | 11 +++++++-
+ drivers/net/phy/sfp-bus.c     |  3 +++
+ drivers/net/phy/sfp.c         | 51 +++++++++++++++++++++++++++++------
+ include/linux/mdio/mdio-i2c.h | 16 +++++++++++
+ 4 files changed, 72 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index 949e3b8..bb4cd28 100644
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -782,6 +782,15 @@ static void phylink_resolve(struct work_struct *w)
+ 								  &link_state);
+ 			}
+ 
++			if (pl->phydev && !(link_state.link & pl->phy_state.link))
++				phylink_printk(KERN_DEBUG, pl,
++					       "resolve link status: system iface=%d, line iface=%d\n",
++					       link_state.link, pl->phy_state.link);
++			else if (!link_state.link)
++				phylink_printk(KERN_DEBUG, pl,
++					       "resolve link status: system iface=%d\n",
++					       link_state.link);
++
+ 			/* If we have a phy, the "up" state is the union of
+ 			 * both the PHY and the MAC
+ 			 */
+@@ -2084,7 +2093,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
+ 		return ret;
+ 	}
+ 
+-	phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
++	phylink_info(pl, "requesting link mode %s/%s with support %*pb\n",
+ 		    phylink_an_mode_str(mode), phy_modes(config.interface),
+ 		    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
+ 
+diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
+index 4be2440..bcf45dd 100644
+--- a/drivers/net/phy/sfp-bus.c
++++ b/drivers/net/phy/sfp-bus.c
+@@ -279,6 +279,9 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
+ 	if (bus->sfp_quirk && bus->sfp_quirk->modes)
+ 		bus->sfp_quirk->modes(id, modes);
+ 
++	dev_info(bus->sfp_dev, "sfp: support mode %*pb\n",
++		 __ETHTOOL_LINK_MODE_MASK_NBITS, modes);
++
+ 	bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
+ }
+ EXPORT_SYMBOL_GPL(sfp_parse_support);
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index 0fdf5d6..0c335b1 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -480,7 +480,7 @@ static bool sfp_match(const char *qs, const char *str, size_t len)
+ 	return !strncmp(qs, str, len);
+ }
+ 
+-static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
++static const struct sfp_quirk *sfp_lookup_quirk(struct sfp *sfp, const struct sfp_eeprom_id *id)
+ {
+ 	const struct sfp_quirk *q;
+ 	unsigned int i;
+@@ -493,8 +493,14 @@ static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
+ 	for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
+ 		if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
+ 		    sfp_match(q->part, id->base.vendor_pn, ps) &&
+-		    sfp_match(q->revision, id->base.vendor_rev, rs))
++		    sfp_match(q->revision, id->base.vendor_rev, rs)) {
++			dev_info(sfp->dev,
++			         "module %.*s %.*s rev %.*s has been found in the quirk list\n",
++				 (int)sizeof(id->base.vendor_name), id->base.vendor_name,
++				 (int)sizeof(id->base.vendor_pn), id->base.vendor_pn,
++				 (int)sizeof(id->base.vendor_rev), id->base.vendor_rev);
+ 			return q;
++		}
+ 
+ 	return NULL;
+ }
+@@ -1597,7 +1603,7 @@ static void sfp_hwmon_exit(struct sfp *sfp)
+ /* Helpers */
+ static void sfp_module_tx_disable(struct sfp *sfp)
+ {
+-	dev_dbg(sfp->dev, "tx disable %u -> %u\n",
++	dev_info(sfp->dev, "tx disable %u -> %u\n",
+ 		sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 1);
+ 	sfp->state |= SFP_F_TX_DISABLE;
+ 	sfp_set_state(sfp, sfp->state);
+@@ -1605,7 +1611,7 @@ static void sfp_module_tx_disable(struct sfp *sfp)
+ 
+ static void sfp_module_tx_enable(struct sfp *sfp)
+ {
+-	dev_dbg(sfp->dev, "tx disable %u -> %u\n",
++	dev_info(sfp->dev, "tx disable %u -> %u\n",
+ 		sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 0);
+ 	sfp->state &= ~SFP_F_TX_DISABLE;
+ 	sfp_set_state(sfp, sfp->state);
+@@ -1660,7 +1666,8 @@ static void sfp_sm_phy_detach(struct sfp *sfp)
+ static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)
+ {
+ 	struct phy_device *phy;
+-	int err;
++	int err, i;
++	u32 id;
+ 
+ 	phy = get_phy_device(sfp->i2c_mii, addr, is_c45);
+ 	if (phy == ERR_PTR(-ENODEV))
+@@ -1677,6 +1684,30 @@ static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)
+ 		return err;
+ 	}
+ 
++	if (phy->is_c45) {
++		for (i = 0; i < ARRAY_SIZE(phy->c45_ids.device_ids); i++) {
++			id = phy->c45_ids.device_ids[i];
++			if (id == 0xffffffff)
++				continue;
++
++			dev_info(sfp->dev,
++				 "CL45 PHY device [0x%04x:0x%04x] found!\n",
++				 (id >> 16) & 0xffff, id & 0xffff);
++		}
++	} else {
++		id = phy->phy_id;
++		dev_info(sfp->dev,
++			 "CL22 PHY device [0x%04x:0x%04x] found!\n",
++			 (id >> 16) & 0xffff, id & 0xffff);
++	}
++
++	dev_info(sfp->dev, "CL%s PHY driver [%s] found!\n",
++		 phy->is_c45 ? "45" : "22",
++		 phy->drv ? phy->drv->name : "not");
++
++	dev_info(sfp->dev, "phy: support mode %*pb\n",
++		__ETHTOOL_LINK_MODE_MASK_NBITS, phy->supported);
++
+ 	err = sfp_add_phy(sfp->sfp_bus, phy);
+ 	if (err) {
+ 		phy_device_remove(phy);
+@@ -1779,6 +1810,10 @@ static int sfp_sm_add_mdio_bus(struct sfp *sfp)
+ static int sfp_sm_probe_for_phy(struct sfp *sfp)
+ {
+ 	int err = 0;
++	struct phy_device *phy;
++
++	dev_info(sfp->dev, "probing phy device through the [%s] protocol\n",
++	         mdio_i2c_proto_type(sfp->mdio_protocol));
+ 
+ 	switch (sfp->mdio_protocol) {
+ 	case MDIO_I2C_NONE:
+@@ -2090,7 +2125,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
+ 	else
+ 		sfp->mdio_protocol = MDIO_I2C_NONE;
+ 
+-	sfp->quirk = sfp_lookup_quirk(&id);
++	sfp->quirk = sfp_lookup_quirk(sfp, &id);
+ 	if (sfp->quirk && sfp->quirk->fixup)
+ 		sfp->quirk->fixup(sfp);
+ 
+@@ -2419,7 +2454,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+ {
+ 	mutex_lock(&sfp->sm_mutex);
+ 
+-	dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
++	dev_info(sfp->dev, "SM: enter %s:%s:%s event %s\n",
+ 		mod_state_to_str(sfp->sm_mod_state),
+ 		dev_state_to_str(sfp->sm_dev_state),
+ 		sm_state_to_str(sfp->sm_state),
+@@ -2429,7 +2464,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+ 	sfp_sm_module(sfp, event);
+ 	sfp_sm_main(sfp, event);
+ 
+-	dev_dbg(sfp->dev, "SM: exit %s:%s:%s\n",
++	dev_info(sfp->dev, "SM: exit %s:%s:%s\n",
+ 		mod_state_to_str(sfp->sm_mod_state),
+ 		dev_state_to_str(sfp->sm_dev_state),
+ 		sm_state_to_str(sfp->sm_state));
+diff --git a/include/linux/mdio/mdio-i2c.h b/include/linux/mdio/mdio-i2c.h
+index 1c21140..4bf833d 100644
+--- a/include/linux/mdio/mdio-i2c.h
++++ b/include/linux/mdio/mdio-i2c.h
+@@ -18,6 +18,22 @@ enum mdio_i2c_proto {
+ 	MDIO_I2C_ROLLBALL,
+ };
+ 
++static inline const char *mdio_i2c_proto_type(int type)
++{
++	switch (type) {
++	case MDIO_I2C_NONE:
++		return "MDIO_I2C_NONE";
++	case MDIO_I2C_MARVELL_C22:
++		return "MDIO_I2C_MARVELL_C22";
++	case MDIO_I2C_C45:
++		return "MDIO_I2C_C45";
++	case MDIO_I2C_ROLLBALL:
++		return "MDIO_I2C_ROLLBALL";
++	default:
++		return "UNKNOWN";
++	}
++}
++
+ struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c,
+ 			       enum mdio_i2c_proto protocol);
+ 
+-- 
+2.18.0
+