ethtool.c (8438B)
1/* 2 * Copyright (c) 2017, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include "en.h" 34#include "ipoib.h" 35 36static void mlx5i_get_drvinfo(struct net_device *dev, 37 struct ethtool_drvinfo *drvinfo) 38{ 39 struct mlx5e_priv *priv = mlx5i_epriv(dev); 40 41 mlx5e_ethtool_get_drvinfo(priv, drvinfo); 42 strlcpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]", 43 sizeof(drvinfo->driver)); 44} 45 46static void mlx5i_get_strings(struct net_device *dev, u32 stringset, u8 *data) 47{ 48 struct mlx5e_priv *priv = mlx5i_epriv(dev); 49 50 mlx5e_ethtool_get_strings(priv, stringset, data); 51} 52 53static int mlx5i_get_sset_count(struct net_device *dev, int sset) 54{ 55 struct mlx5e_priv *priv = mlx5i_epriv(dev); 56 57 return mlx5e_ethtool_get_sset_count(priv, sset); 58} 59 60static void mlx5i_get_ethtool_stats(struct net_device *dev, 61 struct ethtool_stats *stats, 62 u64 *data) 63{ 64 struct mlx5e_priv *priv = mlx5i_epriv(dev); 65 66 mlx5e_ethtool_get_ethtool_stats(priv, stats, data); 67} 68 69static int mlx5i_set_ringparam(struct net_device *dev, 70 struct ethtool_ringparam *param, 71 struct kernel_ethtool_ringparam *kernel_param, 72 struct netlink_ext_ack *extack) 73{ 74 struct mlx5e_priv *priv = mlx5i_epriv(dev); 75 76 return mlx5e_ethtool_set_ringparam(priv, param); 77} 78 79static void mlx5i_get_ringparam(struct net_device *dev, 80 struct ethtool_ringparam *param, 81 struct kernel_ethtool_ringparam *kernel_param, 82 struct netlink_ext_ack *extack) 83{ 84 struct mlx5e_priv *priv = mlx5i_epriv(dev); 85 86 mlx5e_ethtool_get_ringparam(priv, param); 87} 88 89static int mlx5i_set_channels(struct net_device *dev, 90 struct ethtool_channels *ch) 91{ 92 struct mlx5e_priv *priv = mlx5i_epriv(dev); 93 94 return mlx5e_ethtool_set_channels(priv, ch); 95} 96 97static void mlx5i_get_channels(struct net_device *dev, 98 struct ethtool_channels *ch) 99{ 100 struct mlx5e_priv *priv = mlx5i_epriv(dev); 101 102 mlx5e_ethtool_get_channels(priv, ch); 103} 104 105static int mlx5i_set_coalesce(struct net_device *netdev, 106 struct ethtool_coalesce *coal, 107 struct kernel_ethtool_coalesce *kernel_coal, 108 struct netlink_ext_ack *extack) 109{ 110 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 111 112 return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack); 113} 114 115static int mlx5i_get_coalesce(struct net_device *netdev, 116 struct ethtool_coalesce *coal, 117 struct kernel_ethtool_coalesce *kernel_coal, 118 struct netlink_ext_ack *extack) 119{ 120 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 121 122 return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); 123} 124 125static int mlx5i_get_ts_info(struct net_device *netdev, 126 struct ethtool_ts_info *info) 127{ 128 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 129 130 return mlx5e_ethtool_get_ts_info(priv, info); 131} 132 133static int mlx5i_flash_device(struct net_device *netdev, 134 struct ethtool_flash *flash) 135{ 136 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 137 138 return mlx5e_ethtool_flash_device(priv, flash); 139} 140 141static inline int mlx5_ptys_width_enum_to_int(enum mlx5_ptys_width width) 142{ 143 switch (width) { 144 case MLX5_PTYS_WIDTH_1X: return 1; 145 case MLX5_PTYS_WIDTH_2X: return 2; 146 case MLX5_PTYS_WIDTH_4X: return 4; 147 case MLX5_PTYS_WIDTH_8X: return 8; 148 case MLX5_PTYS_WIDTH_12X: return 12; 149 default: return -1; 150 } 151} 152 153enum mlx5_ptys_rate { 154 MLX5_PTYS_RATE_SDR = 1 << 0, 155 MLX5_PTYS_RATE_DDR = 1 << 1, 156 MLX5_PTYS_RATE_QDR = 1 << 2, 157 MLX5_PTYS_RATE_FDR10 = 1 << 3, 158 MLX5_PTYS_RATE_FDR = 1 << 4, 159 MLX5_PTYS_RATE_EDR = 1 << 5, 160 MLX5_PTYS_RATE_HDR = 1 << 6, 161 MLX5_PTYS_RATE_NDR = 1 << 7, 162}; 163 164static inline int mlx5_ptys_rate_enum_to_int(enum mlx5_ptys_rate rate) 165{ 166 switch (rate) { 167 case MLX5_PTYS_RATE_SDR: return 2500; 168 case MLX5_PTYS_RATE_DDR: return 5000; 169 case MLX5_PTYS_RATE_QDR: 170 case MLX5_PTYS_RATE_FDR10: return 10000; 171 case MLX5_PTYS_RATE_FDR: return 14000; 172 case MLX5_PTYS_RATE_EDR: return 25000; 173 case MLX5_PTYS_RATE_HDR: return 50000; 174 case MLX5_PTYS_RATE_NDR: return 100000; 175 default: return -1; 176 } 177} 178 179static int mlx5i_get_speed_settings(u16 ib_link_width_oper, u16 ib_proto_oper) 180{ 181 int rate, width; 182 183 rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper); 184 if (rate < 0) 185 return -EINVAL; 186 width = mlx5_ptys_width_enum_to_int(ib_link_width_oper); 187 if (width < 0) 188 return -EINVAL; 189 190 return rate * width; 191} 192 193static int mlx5i_get_link_ksettings(struct net_device *netdev, 194 struct ethtool_link_ksettings *link_ksettings) 195{ 196 struct mlx5e_priv *priv = mlx5i_epriv(netdev); 197 struct mlx5_core_dev *mdev = priv->mdev; 198 u16 ib_link_width_oper; 199 u16 ib_proto_oper; 200 int speed, ret; 201 202 ret = mlx5_query_ib_port_oper(mdev, &ib_link_width_oper, &ib_proto_oper, 203 1); 204 if (ret) 205 return ret; 206 207 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); 208 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); 209 210 speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper); 211 if (speed < 0) 212 return -EINVAL; 213 214 link_ksettings->base.duplex = DUPLEX_FULL; 215 link_ksettings->base.port = PORT_OTHER; 216 217 link_ksettings->base.autoneg = AUTONEG_DISABLE; 218 219 link_ksettings->base.speed = speed; 220 221 return 0; 222} 223 224static u32 mlx5i_flow_type_mask(u32 flow_type) 225{ 226 return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); 227} 228 229static int mlx5i_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 230{ 231 struct mlx5e_priv *priv = mlx5i_epriv(dev); 232 struct ethtool_rx_flow_spec *fs = &cmd->fs; 233 234 if (mlx5i_flow_type_mask(fs->flow_type) == ETHER_FLOW) 235 return -EINVAL; 236 237 return mlx5e_ethtool_set_rxnfc(priv, cmd); 238} 239 240static int mlx5i_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 241 u32 *rule_locs) 242{ 243 struct mlx5e_priv *priv = mlx5i_epriv(dev); 244 245 /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part 246 * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc, 247 * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc 248 * is compiled out via CONFIG_MLX5_EN_RXNFC=n. 249 */ 250 if (info->cmd == ETHTOOL_GRXRINGS) { 251 info->data = priv->channels.params.num_channels; 252 return 0; 253 } 254 255 return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs); 256} 257 258const struct ethtool_ops mlx5i_ethtool_ops = { 259 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 260 ETHTOOL_COALESCE_MAX_FRAMES | 261 ETHTOOL_COALESCE_USE_ADAPTIVE, 262 .get_drvinfo = mlx5i_get_drvinfo, 263 .get_strings = mlx5i_get_strings, 264 .get_sset_count = mlx5i_get_sset_count, 265 .get_ethtool_stats = mlx5i_get_ethtool_stats, 266 .get_ringparam = mlx5i_get_ringparam, 267 .set_ringparam = mlx5i_set_ringparam, 268 .flash_device = mlx5i_flash_device, 269 .get_channels = mlx5i_get_channels, 270 .set_channels = mlx5i_set_channels, 271 .get_coalesce = mlx5i_get_coalesce, 272 .set_coalesce = mlx5i_set_coalesce, 273 .get_ts_info = mlx5i_get_ts_info, 274 .get_rxnfc = mlx5i_get_rxnfc, 275 .set_rxnfc = mlx5i_set_rxnfc, 276 .get_link_ksettings = mlx5i_get_link_ksettings, 277 .get_link = ethtool_op_get_link, 278}; 279 280const struct ethtool_ops mlx5i_pkey_ethtool_ops = { 281 .get_drvinfo = mlx5i_get_drvinfo, 282 .get_link = ethtool_op_get_link, 283 .get_ts_info = mlx5i_get_ts_info, 284};