 d7a6e171c0
			
		
	
	d7a6e171c0
	
	
	
		
			
			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);
 |