mlxsw: spectrum: Add support for access cable info via ethtool
Add support for access cable info via ethtool. Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									7ca36994a3
								
							
						
					
					
						commit
						2ea109039c
					
				| @ -2519,6 +2519,135 @@ out: | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #define MLXSW_SP_QSFP_I2C_ADDR 0x50 | ||||||
|  | 
 | ||||||
|  | static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, | ||||||
|  | 					u16 offset, u16 size, void *data, | ||||||
|  | 					unsigned int *p_read_size) | ||||||
|  | { | ||||||
|  | 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; | ||||||
|  | 	char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE]; | ||||||
|  | 	char mcia_pl[MLXSW_REG_MCIA_LEN]; | ||||||
|  | 	int status; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE); | ||||||
|  | 	mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module, | ||||||
|  | 			    0, 0, offset, size, MLXSW_SP_QSFP_I2C_ADDR); | ||||||
|  | 
 | ||||||
|  | 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcia), mcia_pl); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	status = mlxsw_reg_mcia_status_get(mcia_pl); | ||||||
|  | 	if (status) | ||||||
|  | 		return -EIO; | ||||||
|  | 
 | ||||||
|  | 	mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); | ||||||
|  | 	memcpy(data, eeprom_tmp, size); | ||||||
|  | 	*p_read_size = size; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum mlxsw_sp_eeprom_module_info_rev_id { | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC      = 0x00, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436       = 0x01, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636       = 0x03, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum mlxsw_sp_eeprom_module_info_id { | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP              = 0x03, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP             = 0x0C, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS        = 0x0D, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28           = 0x11, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum mlxsw_sp_eeprom_module_info { | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_ID, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_REV_ID, | ||||||
|  | 	MLXSW_SP_EEPROM_MODULE_INFO_SIZE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int mlxsw_sp_get_module_info(struct net_device *netdev, | ||||||
|  | 				    struct ethtool_modinfo *modinfo) | ||||||
|  | { | ||||||
|  | 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); | ||||||
|  | 	u8 module_info[MLXSW_SP_EEPROM_MODULE_INFO_SIZE]; | ||||||
|  | 	u8 module_rev_id, module_id; | ||||||
|  | 	unsigned int read_size; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, | ||||||
|  | 					   MLXSW_SP_EEPROM_MODULE_INFO_SIZE, | ||||||
|  | 					   module_info, &read_size); | ||||||
|  | 	if (err) | ||||||
|  | 		return err; | ||||||
|  | 
 | ||||||
|  | 	if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE) | ||||||
|  | 		return -EIO; | ||||||
|  | 
 | ||||||
|  | 	module_rev_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_REV_ID]; | ||||||
|  | 	module_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_ID]; | ||||||
|  | 
 | ||||||
|  | 	switch (module_id) { | ||||||
|  | 	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP: | ||||||
|  | 		modinfo->type       = ETH_MODULE_SFF_8436; | ||||||
|  | 		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; | ||||||
|  | 		break; | ||||||
|  | 	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS: | ||||||
|  | 	case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28: | ||||||
|  | 		if (module_id  == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 || | ||||||
|  | 		    module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636) { | ||||||
|  | 			modinfo->type       = ETH_MODULE_SFF_8636; | ||||||
|  | 			modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; | ||||||
|  | 		} else { | ||||||
|  | 			modinfo->type       = ETH_MODULE_SFF_8436; | ||||||
|  | 			modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP: | ||||||
|  | 		modinfo->type       = ETH_MODULE_SFF_8472; | ||||||
|  | 		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int mlxsw_sp_get_module_eeprom(struct net_device *netdev, | ||||||
|  | 				      struct ethtool_eeprom *ee, | ||||||
|  | 				      u8 *data) | ||||||
|  | { | ||||||
|  | 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); | ||||||
|  | 	int offset = ee->offset; | ||||||
|  | 	unsigned int read_size; | ||||||
|  | 	int i = 0; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	if (!ee->len) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	memset(data, 0, ee->len); | ||||||
|  | 
 | ||||||
|  | 	while (i < ee->len) { | ||||||
|  | 		err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, offset, | ||||||
|  | 						   ee->len - i, data + i, | ||||||
|  | 						   &read_size); | ||||||
|  | 		if (err) { | ||||||
|  | 			netdev_err(mlxsw_sp_port->dev, "Eeprom query failed\n"); | ||||||
|  | 			return err; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		i += read_size; | ||||||
|  | 		offset += read_size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { | static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { | ||||||
| 	.get_drvinfo		= mlxsw_sp_port_get_drvinfo, | 	.get_drvinfo		= mlxsw_sp_port_get_drvinfo, | ||||||
| 	.get_link		= ethtool_op_get_link, | 	.get_link		= ethtool_op_get_link, | ||||||
| @ -2531,6 +2660,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { | |||||||
| 	.get_link_ksettings	= mlxsw_sp_port_get_link_ksettings, | 	.get_link_ksettings	= mlxsw_sp_port_get_link_ksettings, | ||||||
| 	.set_link_ksettings	= mlxsw_sp_port_set_link_ksettings, | 	.set_link_ksettings	= mlxsw_sp_port_set_link_ksettings, | ||||||
| 	.flash_device		= mlxsw_sp_flash_device, | 	.flash_device		= mlxsw_sp_flash_device, | ||||||
|  | 	.get_module_info	= mlxsw_sp_get_module_info, | ||||||
|  | 	.get_module_eeprom	= mlxsw_sp_get_module_eeprom, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user