Move sfp HALNy patch from pending to backport as they got merged upstream. The patch was reordered and one was squashed in the upstream variant. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
		
			
				
	
	
		
			292 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 23571c7b96437483d28a990c906cc81f5f66374e Mon Sep 17 00:00:00 2001
 | 
						|
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
						|
Date: Tue, 13 Sep 2022 20:06:32 +0100
 | 
						|
Subject: [PATCH 1/1] net: sfp: move quirk handling into sfp.c
 | 
						|
 | 
						|
We need to handle more quirks than just those which affect the link
 | 
						|
modes of the module. Move the quirk lookup into sfp.c, and pass the
 | 
						|
quirk to sfp-bus.c
 | 
						|
 | 
						|
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
						|
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
						|
---
 | 
						|
 drivers/net/phy/sfp-bus.c | 98 ++-------------------------------------
 | 
						|
 drivers/net/phy/sfp.c     | 94 ++++++++++++++++++++++++++++++++++++-
 | 
						|
 drivers/net/phy/sfp.h     |  9 +++-
 | 
						|
 3 files changed, 104 insertions(+), 97 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/net/phy/sfp-bus.c
 | 
						|
+++ b/drivers/net/phy/sfp-bus.c
 | 
						|
@@ -10,12 +10,6 @@
 | 
						|
 
 | 
						|
 #include "sfp.h"
 | 
						|
 
 | 
						|
-struct sfp_quirk {
 | 
						|
-	const char *vendor;
 | 
						|
-	const char *part;
 | 
						|
-	void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
 | 
						|
-};
 | 
						|
-
 | 
						|
 /**
 | 
						|
  * struct sfp_bus - internal representation of a sfp bus
 | 
						|
  */
 | 
						|
@@ -38,93 +32,6 @@ struct sfp_bus {
 | 
						|
 	bool started;
 | 
						|
 };
 | 
						|
 
 | 
						|
-static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
 | 
						|
-				unsigned long *modes)
 | 
						|
-{
 | 
						|
-	phylink_set(modes, 2500baseX_Full);
 | 
						|
-}
 | 
						|
-
 | 
						|
-static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
 | 
						|
-				      unsigned long *modes)
 | 
						|
-{
 | 
						|
-	/* Ubiquiti U-Fiber Instant module claims that support all transceiver
 | 
						|
-	 * types including 10G Ethernet which is not truth. So clear all claimed
 | 
						|
-	 * modes and set only one mode which module supports: 1000baseX_Full.
 | 
						|
-	 */
 | 
						|
-	phylink_zero(modes);
 | 
						|
-	phylink_set(modes, 1000baseX_Full);
 | 
						|
-}
 | 
						|
-
 | 
						|
-static const struct sfp_quirk sfp_quirks[] = {
 | 
						|
-	{
 | 
						|
-		// Alcatel Lucent G-010S-P can operate at 2500base-X, but
 | 
						|
-		// incorrectly report 2500MBd NRZ in their EEPROM
 | 
						|
-		.vendor = "ALCATELLUCENT",
 | 
						|
-		.part = "G010SP",
 | 
						|
-		.modes = sfp_quirk_2500basex,
 | 
						|
-	}, {
 | 
						|
-		// Alcatel Lucent G-010S-A can operate at 2500base-X, but
 | 
						|
-		// report 3.2GBd NRZ in their EEPROM
 | 
						|
-		.vendor = "ALCATELLUCENT",
 | 
						|
-		.part = "3FE46541AA",
 | 
						|
-		.modes = sfp_quirk_2500basex,
 | 
						|
-	}, {
 | 
						|
-		// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
 | 
						|
-		// NRZ in their EEPROM
 | 
						|
-		.vendor = "HUAWEI",
 | 
						|
-		.part = "MA5671A",
 | 
						|
-		.modes = sfp_quirk_2500basex,
 | 
						|
-	}, {
 | 
						|
-		// Lantech 8330-262D-E can operate at 2500base-X, but
 | 
						|
-		// incorrectly report 2500MBd NRZ in their EEPROM
 | 
						|
-		.vendor = "Lantech",
 | 
						|
-		.part = "8330-262D-E",
 | 
						|
-		.modes = sfp_quirk_2500basex,
 | 
						|
-	}, {
 | 
						|
-		.vendor = "UBNT",
 | 
						|
-		.part = "UF-INSTANT",
 | 
						|
-		.modes = sfp_quirk_ubnt_uf_instant,
 | 
						|
-	},
 | 
						|
-};
 | 
						|
-
 | 
						|
-static size_t sfp_strlen(const char *str, size_t maxlen)
 | 
						|
-{
 | 
						|
-	size_t size, i;
 | 
						|
-
 | 
						|
-	/* Trailing characters should be filled with space chars */
 | 
						|
-	for (i = 0, size = 0; i < maxlen; i++)
 | 
						|
-		if (str[i] != ' ')
 | 
						|
-			size = i + 1;
 | 
						|
-
 | 
						|
-	return size;
 | 
						|
-}
 | 
						|
-
 | 
						|
-static bool sfp_match(const char *qs, const char *str, size_t len)
 | 
						|
-{
 | 
						|
-	if (!qs)
 | 
						|
-		return true;
 | 
						|
-	if (strlen(qs) != len)
 | 
						|
-		return false;
 | 
						|
-	return !strncmp(qs, str, len);
 | 
						|
-}
 | 
						|
-
 | 
						|
-static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
 | 
						|
-{
 | 
						|
-	const struct sfp_quirk *q;
 | 
						|
-	unsigned int i;
 | 
						|
-	size_t vs, ps;
 | 
						|
-
 | 
						|
-	vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
 | 
						|
-	ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
 | 
						|
-
 | 
						|
-	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))
 | 
						|
-			return q;
 | 
						|
-
 | 
						|
-	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
 | 
						|
@@ -786,12 +693,13 @@ void sfp_link_down(struct sfp_bus *bus)
 | 
						|
 }
 | 
						|
 EXPORT_SYMBOL_GPL(sfp_link_down);
 | 
						|
 
 | 
						|
-int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
 | 
						|
+int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 | 
						|
+		      const struct sfp_quirk *quirk)
 | 
						|
 {
 | 
						|
 	const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 | 
						|
 	int ret = 0;
 | 
						|
 
 | 
						|
-	bus->sfp_quirk = sfp_lookup_quirk(id);
 | 
						|
+	bus->sfp_quirk = quirk;
 | 
						|
 
 | 
						|
 	if (ops && ops->module_insert)
 | 
						|
 		ret = ops->module_insert(bus->upstream, id);
 | 
						|
--- a/drivers/net/phy/sfp.c
 | 
						|
+++ b/drivers/net/phy/sfp.c
 | 
						|
@@ -253,6 +253,8 @@ struct sfp {
 | 
						|
 	unsigned int module_t_start_up;
 | 
						|
 	bool tx_fault_ignore;
 | 
						|
 
 | 
						|
+	const struct sfp_quirk *quirk;
 | 
						|
+
 | 
						|
 #if IS_ENABLED(CONFIG_HWMON)
 | 
						|
 	struct sfp_diag diag;
 | 
						|
 	struct delayed_work hwmon_probe;
 | 
						|
@@ -309,6 +311,93 @@ static const struct of_device_id sfp_of_
 | 
						|
 };
 | 
						|
 MODULE_DEVICE_TABLE(of, sfp_of_match);
 | 
						|
 
 | 
						|
+static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
 | 
						|
+				unsigned long *modes)
 | 
						|
+{
 | 
						|
+	linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
 | 
						|
+				      unsigned long *modes)
 | 
						|
+{
 | 
						|
+	/* Ubiquiti U-Fiber Instant module claims that support all transceiver
 | 
						|
+	 * types including 10G Ethernet which is not truth. So clear all claimed
 | 
						|
+	 * modes and set only one mode which module supports: 1000baseX_Full.
 | 
						|
+	 */
 | 
						|
+	linkmode_zero(modes);
 | 
						|
+	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static const struct sfp_quirk sfp_quirks[] = {
 | 
						|
+	{
 | 
						|
+		// Alcatel Lucent G-010S-P can operate at 2500base-X, but
 | 
						|
+		// incorrectly report 2500MBd NRZ in their EEPROM
 | 
						|
+		.vendor = "ALCATELLUCENT",
 | 
						|
+		.part = "G010SP",
 | 
						|
+		.modes = sfp_quirk_2500basex,
 | 
						|
+	}, {
 | 
						|
+		// Alcatel Lucent G-010S-A can operate at 2500base-X, but
 | 
						|
+		// report 3.2GBd NRZ in their EEPROM
 | 
						|
+		.vendor = "ALCATELLUCENT",
 | 
						|
+		.part = "3FE46541AA",
 | 
						|
+		.modes = sfp_quirk_2500basex,
 | 
						|
+	}, {
 | 
						|
+		// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
 | 
						|
+		// NRZ in their EEPROM
 | 
						|
+		.vendor = "HUAWEI",
 | 
						|
+		.part = "MA5671A",
 | 
						|
+		.modes = sfp_quirk_2500basex,
 | 
						|
+	}, {
 | 
						|
+		// Lantech 8330-262D-E can operate at 2500base-X, but
 | 
						|
+		// incorrectly report 2500MBd NRZ in their EEPROM
 | 
						|
+		.vendor = "Lantech",
 | 
						|
+		.part = "8330-262D-E",
 | 
						|
+		.modes = sfp_quirk_2500basex,
 | 
						|
+	}, {
 | 
						|
+		.vendor = "UBNT",
 | 
						|
+		.part = "UF-INSTANT",
 | 
						|
+		.modes = sfp_quirk_ubnt_uf_instant,
 | 
						|
+	},
 | 
						|
+};
 | 
						|
+
 | 
						|
+static size_t sfp_strlen(const char *str, size_t maxlen)
 | 
						|
+{
 | 
						|
+	size_t size, i;
 | 
						|
+
 | 
						|
+	/* Trailing characters should be filled with space chars */
 | 
						|
+	for (i = 0, size = 0; i < maxlen; i++)
 | 
						|
+		if (str[i] != ' ')
 | 
						|
+			size = i + 1;
 | 
						|
+
 | 
						|
+	return size;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static bool sfp_match(const char *qs, const char *str, size_t len)
 | 
						|
+{
 | 
						|
+	if (!qs)
 | 
						|
+		return true;
 | 
						|
+	if (strlen(qs) != len)
 | 
						|
+		return false;
 | 
						|
+	return !strncmp(qs, str, len);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
 | 
						|
+{
 | 
						|
+	const struct sfp_quirk *q;
 | 
						|
+	unsigned int i;
 | 
						|
+	size_t vs, ps;
 | 
						|
+
 | 
						|
+	vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
 | 
						|
+	ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
 | 
						|
+
 | 
						|
+	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))
 | 
						|
+			return q;
 | 
						|
+
 | 
						|
+	return NULL;
 | 
						|
+}
 | 
						|
+
 | 
						|
 static unsigned long poll_jiffies;
 | 
						|
 
 | 
						|
 static unsigned int sfp_gpio_get_state(struct sfp *sfp)
 | 
						|
@@ -1964,6 +2053,8 @@ static int sfp_sm_mod_probe(struct sfp *
 | 
						|
 	else
 | 
						|
 		sfp->tx_fault_ignore = false;
 | 
						|
 
 | 
						|
+	sfp->quirk = sfp_lookup_quirk(&id);
 | 
						|
+
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -2075,7 +2166,8 @@ static void sfp_sm_module(struct sfp *sf
 | 
						|
 			break;
 | 
						|
 
 | 
						|
 		/* Report the module insertion to the upstream device */
 | 
						|
-		err = sfp_module_insert(sfp->sfp_bus, &sfp->id);
 | 
						|
+		err = sfp_module_insert(sfp->sfp_bus, &sfp->id,
 | 
						|
+					sfp->quirk);
 | 
						|
 		if (err < 0) {
 | 
						|
 			sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
 | 
						|
 			break;
 | 
						|
--- a/drivers/net/phy/sfp.h
 | 
						|
+++ b/drivers/net/phy/sfp.h
 | 
						|
@@ -6,6 +6,12 @@
 | 
						|
 
 | 
						|
 struct sfp;
 | 
						|
 
 | 
						|
+struct sfp_quirk {
 | 
						|
+	const char *vendor;
 | 
						|
+	const char *part;
 | 
						|
+	void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
 | 
						|
+};
 | 
						|
+
 | 
						|
 struct sfp_socket_ops {
 | 
						|
 	void (*attach)(struct sfp *sfp);
 | 
						|
 	void (*detach)(struct sfp *sfp);
 | 
						|
@@ -23,7 +29,8 @@ int sfp_add_phy(struct sfp_bus *bus, str
 | 
						|
 void sfp_remove_phy(struct sfp_bus *bus);
 | 
						|
 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);
 | 
						|
+int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 | 
						|
+		      const struct sfp_quirk *quirk);
 | 
						|
 void sfp_module_remove(struct sfp_bus *bus);
 | 
						|
 int sfp_module_start(struct sfp_bus *bus);
 | 
						|
 void sfp_module_stop(struct sfp_bus *bus);
 |