0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include "en.h"
0034 #include "ipoib.h"
0035
0036 static void mlx5i_get_drvinfo(struct net_device *dev,
0037 struct ethtool_drvinfo *drvinfo)
0038 {
0039 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0040
0041 mlx5e_ethtool_get_drvinfo(priv, drvinfo);
0042 strlcpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
0043 sizeof(drvinfo->driver));
0044 }
0045
0046 static void mlx5i_get_strings(struct net_device *dev, u32 stringset, u8 *data)
0047 {
0048 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0049
0050 mlx5e_ethtool_get_strings(priv, stringset, data);
0051 }
0052
0053 static int mlx5i_get_sset_count(struct net_device *dev, int sset)
0054 {
0055 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0056
0057 return mlx5e_ethtool_get_sset_count(priv, sset);
0058 }
0059
0060 static void mlx5i_get_ethtool_stats(struct net_device *dev,
0061 struct ethtool_stats *stats,
0062 u64 *data)
0063 {
0064 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0065
0066 mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
0067 }
0068
0069 static int mlx5i_set_ringparam(struct net_device *dev,
0070 struct ethtool_ringparam *param,
0071 struct kernel_ethtool_ringparam *kernel_param,
0072 struct netlink_ext_ack *extack)
0073 {
0074 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0075
0076 return mlx5e_ethtool_set_ringparam(priv, param);
0077 }
0078
0079 static void mlx5i_get_ringparam(struct net_device *dev,
0080 struct ethtool_ringparam *param,
0081 struct kernel_ethtool_ringparam *kernel_param,
0082 struct netlink_ext_ack *extack)
0083 {
0084 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0085
0086 mlx5e_ethtool_get_ringparam(priv, param, kernel_param);
0087 }
0088
0089 static int mlx5i_set_channels(struct net_device *dev,
0090 struct ethtool_channels *ch)
0091 {
0092 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0093
0094 return mlx5e_ethtool_set_channels(priv, ch);
0095 }
0096
0097 static void mlx5i_get_channels(struct net_device *dev,
0098 struct ethtool_channels *ch)
0099 {
0100 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0101
0102 mlx5e_ethtool_get_channels(priv, ch);
0103 }
0104
0105 static int mlx5i_set_coalesce(struct net_device *netdev,
0106 struct ethtool_coalesce *coal,
0107 struct kernel_ethtool_coalesce *kernel_coal,
0108 struct netlink_ext_ack *extack)
0109 {
0110 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
0111
0112 return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack);
0113 }
0114
0115 static int mlx5i_get_coalesce(struct net_device *netdev,
0116 struct ethtool_coalesce *coal,
0117 struct kernel_ethtool_coalesce *kernel_coal,
0118 struct netlink_ext_ack *extack)
0119 {
0120 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
0121
0122 return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal);
0123 }
0124
0125 static int mlx5i_get_ts_info(struct net_device *netdev,
0126 struct ethtool_ts_info *info)
0127 {
0128 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
0129
0130 return mlx5e_ethtool_get_ts_info(priv, info);
0131 }
0132
0133 static int mlx5i_flash_device(struct net_device *netdev,
0134 struct ethtool_flash *flash)
0135 {
0136 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
0137
0138 return mlx5e_ethtool_flash_device(priv, flash);
0139 }
0140
0141 static inline int mlx5_ptys_width_enum_to_int(enum mlx5_ptys_width width)
0142 {
0143 switch (width) {
0144 case MLX5_PTYS_WIDTH_1X: return 1;
0145 case MLX5_PTYS_WIDTH_2X: return 2;
0146 case MLX5_PTYS_WIDTH_4X: return 4;
0147 case MLX5_PTYS_WIDTH_8X: return 8;
0148 case MLX5_PTYS_WIDTH_12X: return 12;
0149 default: return -1;
0150 }
0151 }
0152
0153 enum mlx5_ptys_rate {
0154 MLX5_PTYS_RATE_SDR = 1 << 0,
0155 MLX5_PTYS_RATE_DDR = 1 << 1,
0156 MLX5_PTYS_RATE_QDR = 1 << 2,
0157 MLX5_PTYS_RATE_FDR10 = 1 << 3,
0158 MLX5_PTYS_RATE_FDR = 1 << 4,
0159 MLX5_PTYS_RATE_EDR = 1 << 5,
0160 MLX5_PTYS_RATE_HDR = 1 << 6,
0161 MLX5_PTYS_RATE_NDR = 1 << 7,
0162 };
0163
0164 static inline int mlx5_ptys_rate_enum_to_int(enum mlx5_ptys_rate rate)
0165 {
0166 switch (rate) {
0167 case MLX5_PTYS_RATE_SDR: return 2500;
0168 case MLX5_PTYS_RATE_DDR: return 5000;
0169 case MLX5_PTYS_RATE_QDR:
0170 case MLX5_PTYS_RATE_FDR10: return 10000;
0171 case MLX5_PTYS_RATE_FDR: return 14000;
0172 case MLX5_PTYS_RATE_EDR: return 25000;
0173 case MLX5_PTYS_RATE_HDR: return 50000;
0174 case MLX5_PTYS_RATE_NDR: return 100000;
0175 default: return -1;
0176 }
0177 }
0178
0179 static int mlx5i_get_speed_settings(u16 ib_link_width_oper, u16 ib_proto_oper)
0180 {
0181 int rate, width;
0182
0183 rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper);
0184 if (rate < 0)
0185 return -EINVAL;
0186 width = mlx5_ptys_width_enum_to_int(ib_link_width_oper);
0187 if (width < 0)
0188 return -EINVAL;
0189
0190 return rate * width;
0191 }
0192
0193 static int mlx5i_get_link_ksettings(struct net_device *netdev,
0194 struct ethtool_link_ksettings *link_ksettings)
0195 {
0196 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
0197 struct mlx5_core_dev *mdev = priv->mdev;
0198 u16 ib_link_width_oper;
0199 u16 ib_proto_oper;
0200 int speed, ret;
0201
0202 ret = mlx5_query_ib_port_oper(mdev, &ib_link_width_oper, &ib_proto_oper,
0203 1);
0204 if (ret)
0205 return ret;
0206
0207 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
0208 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
0209
0210 speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper);
0211 if (speed < 0)
0212 return -EINVAL;
0213
0214 link_ksettings->base.duplex = DUPLEX_FULL;
0215 link_ksettings->base.port = PORT_OTHER;
0216
0217 link_ksettings->base.autoneg = AUTONEG_DISABLE;
0218
0219 link_ksettings->base.speed = speed;
0220
0221 return 0;
0222 }
0223
0224 static u32 mlx5i_flow_type_mask(u32 flow_type)
0225 {
0226 return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
0227 }
0228
0229 static int mlx5i_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
0230 {
0231 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0232 struct ethtool_rx_flow_spec *fs = &cmd->fs;
0233
0234 if (mlx5i_flow_type_mask(fs->flow_type) == ETHER_FLOW)
0235 return -EINVAL;
0236
0237 return mlx5e_ethtool_set_rxnfc(priv, cmd);
0238 }
0239
0240 static int mlx5i_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
0241 u32 *rule_locs)
0242 {
0243 struct mlx5e_priv *priv = mlx5i_epriv(dev);
0244
0245
0246
0247
0248
0249
0250 if (info->cmd == ETHTOOL_GRXRINGS) {
0251 info->data = priv->channels.params.num_channels;
0252 return 0;
0253 }
0254
0255 return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs);
0256 }
0257
0258 const struct ethtool_ops mlx5i_ethtool_ops = {
0259 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
0260 ETHTOOL_COALESCE_MAX_FRAMES |
0261 ETHTOOL_COALESCE_USE_ADAPTIVE,
0262 .get_drvinfo = mlx5i_get_drvinfo,
0263 .get_strings = mlx5i_get_strings,
0264 .get_sset_count = mlx5i_get_sset_count,
0265 .get_ethtool_stats = mlx5i_get_ethtool_stats,
0266 .get_ringparam = mlx5i_get_ringparam,
0267 .set_ringparam = mlx5i_set_ringparam,
0268 .flash_device = mlx5i_flash_device,
0269 .get_channels = mlx5i_get_channels,
0270 .set_channels = mlx5i_set_channels,
0271 .get_coalesce = mlx5i_get_coalesce,
0272 .set_coalesce = mlx5i_set_coalesce,
0273 .get_ts_info = mlx5i_get_ts_info,
0274 .get_rxnfc = mlx5i_get_rxnfc,
0275 .set_rxnfc = mlx5i_set_rxnfc,
0276 .get_link_ksettings = mlx5i_get_link_ksettings,
0277 .get_link = ethtool_op_get_link,
0278 };
0279
0280 const struct ethtool_ops mlx5i_pkey_ethtool_ops = {
0281 .get_drvinfo = mlx5i_get_drvinfo,
0282 .get_link = ethtool_op_get_link,
0283 .get_ts_info = mlx5i_get_ts_info,
0284 };