forked from mirrors/linux
		
	net/mlx5: ethtool, Allow legacy link-modes configuration via non-extended ptys
Allow configuration of legacy link-modes even when extended link-modes
are supported. This requires reading of legacy advertisement even when
extended link-modes are supported. Since legacy and extended
advertisement are mutually excluded, wait for empty reply from extended
advertisement before reading legacy advertisement.
Fixes: 6a89737241 ("net/mlx5: ethtool, Add ethtool support for 50Gbps per lane link modes")
Signed-off-by: Aya Levin <ayal@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
			
			
This commit is contained in:
		
							parent
							
								
									8d047bf56a
								
							
						
					
					
						commit
						dd1b9e09c1
					
				
					 2 changed files with 31 additions and 19 deletions
				
			
		| 
						 | 
					@ -96,9 +96,6 @@ int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
 | 
				
			||||||
	if (!eproto)
 | 
						if (!eproto)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ext !=  MLX5_CAP_PCAM_FEATURE(dev, ptys_extended_ethernet))
 | 
					 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
 | 
						err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -603,16 +603,18 @@ static void ptys2ethtool_supported_link(struct mlx5_core_dev *mdev,
 | 
				
			||||||
			  __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
								  __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ptys2ethtool_adver_link(struct mlx5_core_dev *mdev,
 | 
					static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
 | 
				
			||||||
				    unsigned long *advertising_modes,
 | 
									    u32 eth_proto_cap, bool ext)
 | 
				
			||||||
				    u32 eth_proto_cap)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long proto_cap = eth_proto_cap;
 | 
						unsigned long proto_cap = eth_proto_cap;
 | 
				
			||||||
	struct ptys2ethtool_config *table;
 | 
						struct ptys2ethtool_config *table;
 | 
				
			||||||
	u32 max_size;
 | 
						u32 max_size;
 | 
				
			||||||
	int proto;
 | 
						int proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size);
 | 
						table = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
 | 
				
			||||||
 | 
						max_size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
 | 
				
			||||||
 | 
								 ARRAY_SIZE(ptys2legacy_ethtool_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for_each_set_bit(proto, &proto_cap, max_size)
 | 
						for_each_set_bit(proto, &proto_cap, max_size)
 | 
				
			||||||
		bitmap_or(advertising_modes, advertising_modes,
 | 
							bitmap_or(advertising_modes, advertising_modes,
 | 
				
			||||||
			  table[proto].advertised,
 | 
								  table[proto].advertised,
 | 
				
			||||||
| 
						 | 
					@ -794,12 +796,12 @@ static void get_supported(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
 | 
				
			||||||
	ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
 | 
						ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_cap,
 | 
					static void get_advertising(u32 eth_proto_cap, u8 tx_pause, u8 rx_pause,
 | 
				
			||||||
			    u8 tx_pause, u8 rx_pause,
 | 
								    struct ethtool_link_ksettings *link_ksettings,
 | 
				
			||||||
			    struct ethtool_link_ksettings *link_ksettings)
 | 
								    bool ext)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long *advertising = link_ksettings->link_modes.advertising;
 | 
						unsigned long *advertising = link_ksettings->link_modes.advertising;
 | 
				
			||||||
	ptys2ethtool_adver_link(mdev, advertising, eth_proto_cap);
 | 
						ptys2ethtool_adver_link(advertising, eth_proto_cap, ext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rx_pause)
 | 
						if (rx_pause)
 | 
				
			||||||
		ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
 | 
							ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
 | 
				
			||||||
| 
						 | 
					@ -854,8 +856,9 @@ static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp,
 | 
				
			||||||
			       struct ethtool_link_ksettings *link_ksettings)
 | 
								       struct ethtool_link_ksettings *link_ksettings)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
 | 
						unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
 | 
				
			||||||
 | 
						bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ptys2ethtool_adver_link(mdev, lp_advertising, eth_proto_lp);
 | 
						ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
 | 
					int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
| 
						 | 
					@ -872,6 +875,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
	u8 an_disable_admin;
 | 
						u8 an_disable_admin;
 | 
				
			||||||
	u8 an_status;
 | 
						u8 an_status;
 | 
				
			||||||
	u8 connector_type;
 | 
						u8 connector_type;
 | 
				
			||||||
 | 
						bool admin_ext;
 | 
				
			||||||
	bool ext;
 | 
						bool ext;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -886,6 +890,19 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
					      eth_proto_capability);
 | 
										      eth_proto_capability);
 | 
				
			||||||
	eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 | 
						eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 | 
				
			||||||
					      eth_proto_admin);
 | 
										      eth_proto_admin);
 | 
				
			||||||
 | 
						/* Fields: eth_proto_admin and ext_eth_proto_admin  are
 | 
				
			||||||
 | 
						 * mutually exclusive. Hence try reading legacy advertising
 | 
				
			||||||
 | 
						 * when extended advertising is zero.
 | 
				
			||||||
 | 
						 * admin_ext indicates how eth_proto_admin should be
 | 
				
			||||||
 | 
						 * interpreted
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						admin_ext = ext;
 | 
				
			||||||
 | 
						if (ext && !eth_proto_admin) {
 | 
				
			||||||
 | 
							eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, false,
 | 
				
			||||||
 | 
											      eth_proto_admin);
 | 
				
			||||||
 | 
							admin_ext = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 | 
						eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 | 
				
			||||||
					      eth_proto_oper);
 | 
										      eth_proto_oper);
 | 
				
			||||||
	eth_proto_lp	    = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
 | 
						eth_proto_lp	    = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
 | 
				
			||||||
| 
						 | 
					@ -899,7 +916,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
	ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
 | 
						ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	get_supported(mdev, eth_proto_cap, link_ksettings);
 | 
						get_supported(mdev, eth_proto_cap, link_ksettings);
 | 
				
			||||||
	get_advertising(mdev, eth_proto_admin, tx_pause, rx_pause, link_ksettings);
 | 
						get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
 | 
				
			||||||
 | 
								admin_ext);
 | 
				
			||||||
	get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
 | 
						get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 | 
						eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 | 
				
			||||||
| 
						 | 
					@ -1001,16 +1019,13 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
			MLX5E_PTYS_EXT ||
 | 
								MLX5E_PTYS_EXT ||
 | 
				
			||||||
			link_ksettings->link_modes.advertising[1]);
 | 
								link_ksettings->link_modes.advertising[1]);
 | 
				
			||||||
	ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 | 
						ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 | 
				
			||||||
 | 
						ext_requested &= ext_supported;
 | 
				
			||||||
	/*when ptys_extended_ethernet is set legacy link modes are deprecated */
 | 
					 | 
				
			||||||
	if (ext_requested != ext_supported)
 | 
					 | 
				
			||||||
		return -EPROTONOSUPPORT;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	speed = link_ksettings->base.speed;
 | 
						speed = link_ksettings->base.speed;
 | 
				
			||||||
	ethtool2ptys_adver_func = ext_requested ?
 | 
						ethtool2ptys_adver_func = ext_requested ?
 | 
				
			||||||
				  mlx5e_ethtool2ptys_ext_adver_link :
 | 
									  mlx5e_ethtool2ptys_ext_adver_link :
 | 
				
			||||||
				  mlx5e_ethtool2ptys_adver_link;
 | 
									  mlx5e_ethtool2ptys_adver_link;
 | 
				
			||||||
	err = mlx5_port_query_eth_proto(mdev, 1, ext_supported, &eproto);
 | 
						err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
 | 
				
			||||||
	if (err) {
 | 
						if (err) {
 | 
				
			||||||
		netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
 | 
							netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
 | 
				
			||||||
			   __func__, err);
 | 
								   __func__, err);
 | 
				
			||||||
| 
						 | 
					@ -1038,7 +1053,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
 | 
				
			||||||
	if (!an_changes && link_modes == eproto.admin)
 | 
						if (!an_changes && link_modes == eproto.admin)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_supported);
 | 
						mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
 | 
				
			||||||
	mlx5_toggle_port_link(mdev);
 | 
						mlx5_toggle_port_link(mdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue