@@ -785,7 +785,7 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
785
785
}
786
786
787
787
static void get_speed_duplex (struct net_device * netdev ,
788
- u32 eth_proto_oper ,
788
+ u32 eth_proto_oper , bool force_legacy ,
789
789
struct ethtool_link_ksettings * link_ksettings )
790
790
{
791
791
struct mlx5e_priv * priv = netdev_priv (netdev );
@@ -795,7 +795,7 @@ static void get_speed_duplex(struct net_device *netdev,
795
795
if (!netif_carrier_ok (netdev ))
796
796
goto out ;
797
797
798
- speed = mlx5e_port_ptys2speed (priv -> mdev , eth_proto_oper );
798
+ speed = mlx5e_port_ptys2speed (priv -> mdev , eth_proto_oper , force_legacy );
799
799
if (!speed ) {
800
800
speed = SPEED_UNKNOWN ;
801
801
goto out ;
@@ -914,8 +914,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
914
914
/* Fields: eth_proto_admin and ext_eth_proto_admin are
915
915
* mutually exclusive. Hence try reading legacy advertising
916
916
* when extended advertising is zero.
917
- * admin_ext indicates how eth_proto_admin should be
918
- * interpreted
917
+ * admin_ext indicates which proto_admin (ext vs. legacy)
918
+ * should be read and interpreted
919
919
*/
920
920
admin_ext = ext ;
921
921
if (ext && !eth_proto_admin ) {
@@ -924,7 +924,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
924
924
admin_ext = false;
925
925
}
926
926
927
- eth_proto_oper = MLX5_GET_ETH_PROTO (ptys_reg , out , ext ,
927
+ eth_proto_oper = MLX5_GET_ETH_PROTO (ptys_reg , out , admin_ext ,
928
928
eth_proto_oper );
929
929
eth_proto_lp = MLX5_GET (ptys_reg , out , eth_proto_lp_advertise );
930
930
an_disable_admin = MLX5_GET (ptys_reg , out , an_disable_admin );
@@ -939,7 +939,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
939
939
get_supported (mdev , eth_proto_cap , link_ksettings );
940
940
get_advertising (eth_proto_admin , tx_pause , rx_pause , link_ksettings ,
941
941
admin_ext );
942
- get_speed_duplex (priv -> netdev , eth_proto_oper , link_ksettings );
942
+ get_speed_duplex (priv -> netdev , eth_proto_oper , !admin_ext ,
943
+ link_ksettings );
943
944
944
945
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap ;
945
946
@@ -1016,45 +1017,69 @@ static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
1016
1017
return ptys_modes ;
1017
1018
}
1018
1019
1020
+ static bool ext_link_mode_requested (const unsigned long * adver )
1021
+ {
1022
+ #define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
1023
+ int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ;
1024
+ __ETHTOOL_DECLARE_LINK_MODE_MASK (modes );
1025
+
1026
+ bitmap_set (modes , MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT , size );
1027
+ return bitmap_intersects (modes , adver , __ETHTOOL_LINK_MODE_MASK_NBITS );
1028
+ }
1029
+
1030
+ static bool ext_speed_requested (u32 speed )
1031
+ {
1032
+ #define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
1033
+ return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED );
1034
+ }
1035
+
1036
+ static bool ext_requested (u8 autoneg , const unsigned long * adver , u32 speed )
1037
+ {
1038
+ bool ext_link_mode = ext_link_mode_requested (adver );
1039
+ bool ext_speed = ext_speed_requested (speed );
1040
+
1041
+ return autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed ;
1042
+ }
1043
+
1019
1044
int mlx5e_ethtool_set_link_ksettings (struct mlx5e_priv * priv ,
1020
1045
const struct ethtool_link_ksettings * link_ksettings )
1021
1046
{
1022
1047
struct mlx5_core_dev * mdev = priv -> mdev ;
1023
1048
struct mlx5e_port_eth_proto eproto ;
1049
+ const unsigned long * adver ;
1024
1050
bool an_changes = false;
1025
1051
u8 an_disable_admin ;
1026
1052
bool ext_supported ;
1027
- bool ext_requested ;
1028
1053
u8 an_disable_cap ;
1029
1054
bool an_disable ;
1030
1055
u32 link_modes ;
1031
1056
u8 an_status ;
1057
+ u8 autoneg ;
1032
1058
u32 speed ;
1059
+ bool ext ;
1033
1060
int err ;
1034
1061
1035
1062
u32 (* ethtool2ptys_adver_func )(const unsigned long * adver );
1036
1063
1037
- #define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
1064
+ adver = link_ksettings -> link_modes .advertising ;
1065
+ autoneg = link_ksettings -> base .autoneg ;
1066
+ speed = link_ksettings -> base .speed ;
1038
1067
1039
- ext_requested = !!(link_ksettings -> link_modes .advertising [0 ] >
1040
- MLX5E_PTYS_EXT ||
1041
- link_ksettings -> link_modes .advertising [1 ]);
1068
+ ext = ext_requested (autoneg , adver , speed ),
1042
1069
ext_supported = MLX5_CAP_PCAM_FEATURE (mdev , ptys_extended_ethernet );
1043
- ext_requested &= ext_supported ;
1070
+ if (!ext_supported && ext )
1071
+ return - EOPNOTSUPP ;
1044
1072
1045
- speed = link_ksettings -> base .speed ;
1046
- ethtool2ptys_adver_func = ext_requested ?
1047
- mlx5e_ethtool2ptys_ext_adver_link :
1073
+ ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
1048
1074
mlx5e_ethtool2ptys_adver_link ;
1049
- err = mlx5_port_query_eth_proto (mdev , 1 , ext_requested , & eproto );
1075
+ err = mlx5_port_query_eth_proto (mdev , 1 , ext , & eproto );
1050
1076
if (err ) {
1051
1077
netdev_err (priv -> netdev , "%s: query port eth proto failed: %d\n" ,
1052
1078
__func__ , err );
1053
1079
goto out ;
1054
1080
}
1055
- link_modes = link_ksettings -> base .autoneg == AUTONEG_ENABLE ?
1056
- ethtool2ptys_adver_func (link_ksettings -> link_modes .advertising ) :
1057
- mlx5e_port_speed2linkmodes (mdev , speed );
1081
+ link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func (adver ) :
1082
+ mlx5e_port_speed2linkmodes (mdev , speed , !ext );
1058
1083
1059
1084
link_modes = link_modes & eproto .cap ;
1060
1085
if (!link_modes ) {
@@ -1067,14 +1092,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
1067
1092
mlx5_port_query_eth_autoneg (mdev , & an_status , & an_disable_cap ,
1068
1093
& an_disable_admin );
1069
1094
1070
- an_disable = link_ksettings -> base . autoneg == AUTONEG_DISABLE ;
1095
+ an_disable = autoneg == AUTONEG_DISABLE ;
1071
1096
an_changes = ((!an_disable && an_disable_admin ) ||
1072
1097
(an_disable && !an_disable_admin ));
1073
1098
1074
1099
if (!an_changes && link_modes == eproto .admin )
1075
1100
goto out ;
1076
1101
1077
- mlx5_port_set_eth_ptys (mdev , an_disable , link_modes , ext_requested );
1102
+ mlx5_port_set_eth_ptys (mdev , an_disable , link_modes , ext );
1078
1103
mlx5_toggle_port_link (mdev );
1079
1104
1080
1105
out :
0 commit comments