116359Sasami/* 256711Snyan * Copyright (c) 2017, Mellanox Technologies. All rights reserved. 316359Sasami * 450518Snyan * This software is available to you under a choice of one of two 550518Snyan * licenses. You may choose to be licensed under the terms of the GNU 616359Sasami * General Public License (GPL) Version 2, available from the file 760717Snyan * COPYING in the main directory of this source tree, or the 850518Snyan * OpenIB.org BSD license below: 950518Snyan * 1050518Snyan * Redistribution and use in source and binary forms, with or 1160717Snyan * without modification, are permitted provided that the following 1250518Snyan * conditions are met: 1350518Snyan * 1450518Snyan * - Redistributions of source code must retain the above 1550518Snyan * copyright notice, this list of conditions and the following 1617973Sasami * disclaimer. 1717973Sasami * 1850477Speter * - Redistributions in binary form must reproduce the above 1916359Sasami * copyright notice, this list of conditions and the following 2046044Skato * disclaimer in the documentation and/or other materials 2146044Skato * provided with the distribution. 2246044Skato * 2346044Skato * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2446044Skato * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2560027Snyan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2638832Skato * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2716359Sasami * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2861640Speter * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2961640Speter * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3046044Skato * SOFTWARE. 3145783Skato */ 3250518Snyan 3350518Snyan#include "en.h" 3450518Snyan#include "ipoib.h" 3557655Skato#include "en/fs_ethtool.h" 3650518Snyan 3750518Snyanstatic void mlx5i_get_drvinfo(struct net_device *dev, 3862198Skato struct ethtool_drvinfo *drvinfo) 3954877Skato{ 4053744Snyan struct mlx5e_priv *priv = mlx5i_epriv(dev); 4150518Snyan 4256533Skato mlx5e_ethtool_get_drvinfo(priv, drvinfo); 4350518Snyan strscpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]", 4450518Snyan sizeof(drvinfo->driver)); 4556533Skato} 4650518Snyan 4750518Snyanstatic void mlx5i_get_strings(struct net_device *dev, u32 stringset, u8 *data) 4856711Snyan{ 4950518Snyan struct mlx5e_priv *priv = mlx5i_epriv(dev); 5050518Snyan 5150518Snyan mlx5e_ethtool_get_strings(priv, stringset, data); 5250518Snyan} 5350518Snyan 5450518Snyanstatic int mlx5i_get_sset_count(struct net_device *dev, int sset) 5556533Skato{ 5652833Snyan struct mlx5e_priv *priv = mlx5i_epriv(dev); 5752833Snyan 5856327Snyan return mlx5e_ethtool_get_sset_count(priv, sset); 5959530Snyan} 6056323Skato 6160717Snyanstatic void mlx5i_get_ethtool_stats(struct net_device *dev, 6262198Skato struct ethtool_stats *stats, 6318846Sasami u64 *data) 6442157Skato{ 6550518Snyan struct mlx5e_priv *priv = mlx5i_epriv(dev); 6650518Snyan 6742157Skato mlx5e_ethtool_get_ethtool_stats(priv, stats, data); 6850518Snyan} 6950518Snyan 7050518Snyanstatic int mlx5i_set_ringparam(struct net_device *dev, 7150518Snyan struct ethtool_ringparam *param, 7242157Skato struct kernel_ethtool_ringparam *kernel_param, 7356442Speter struct netlink_ext_ack *extack) 7456442Speter{ 7558290Skato struct mlx5e_priv *priv = mlx5i_epriv(dev); 7658290Skato 7716359Sasami return mlx5e_ethtool_set_ringparam(priv, param); 7850518Snyan} 7961640Speter 8016359Sasamistatic void mlx5i_get_ringparam(struct net_device *dev, 8150518Snyan struct ethtool_ringparam *param, 8261640Speter struct kernel_ethtool_ringparam *kernel_param, 8316359Sasami struct netlink_ext_ack *extack) 8456516Speter{ 8556442Speter struct mlx5e_priv *priv = mlx5i_epriv(dev); 8656442Speter 8756442Speter mlx5e_ethtool_get_ringparam(priv, param, kernel_param); 8816359Sasami} 8950518Snyan 9056442Speterstatic int mlx5i_set_channels(struct net_device *dev, 9156442Speter struct ethtool_channels *ch) 9256442Speter{ 9356442Speter struct mlx5i_priv *ipriv = netdev_priv(dev); 9456442Speter struct mlx5e_priv *epriv = mlx5i_epriv(dev); 9556442Speter 9618846Sasami /* rtnl lock protects from race between this ethtool op and sub 9720128Sasami * interface ndo_init/uninit. 9861750Snyan */ 9961741Skato ASSERT_RTNL(); 10020128Sasami if (ipriv->num_sub_interfaces > 0) { 10158789Snyan mlx5_core_warn(epriv->mdev, 10261750Snyan "can't change number of channels for interfaces with sub interfaces (%u)\n", 10358789Snyan ipriv->num_sub_interfaces); 10450518Snyan return -EINVAL; 10556442Speter } 10656442Speter 10756442Speter return mlx5e_ethtool_set_channels(epriv, ch); 10856442Speter} 10956442Speter 11016359Sasamistatic void mlx5i_get_channels(struct net_device *dev, 11154030Snyan struct ethtool_channels *ch) 11262205Skato{ 11362205Skato struct mlx5e_priv *priv = mlx5i_epriv(dev); 11462205Skato 11554030Snyan mlx5e_ethtool_get_channels(priv, ch); 11642795Skato} 11761741Skato 11816359Sasamistatic int mlx5i_set_coalesce(struct net_device *netdev, 11961640Speter struct ethtool_coalesce *coal, 12042795Skato struct kernel_ethtool_coalesce *kernel_coal, 12145783Skato struct netlink_ext_ack *extack) 12261640Speter{ 12342795Skato struct mlx5e_priv *priv = mlx5i_epriv(netdev); 12453120Snyan 12561640Speter return mlx5e_ethtool_set_coalesce(priv, coal, kernel_coal, extack); 12642795Skato} 12750518Snyan 12861640Speterstatic int mlx5i_get_coalesce(struct net_device *netdev, 12916359Sasami struct ethtool_coalesce *coal, 13050518Snyan struct kernel_ethtool_coalesce *kernel_coal, 13161640Speter struct netlink_ext_ack *extack) 13224432Skato{ 13316359Sasami struct mlx5e_priv *priv = mlx5i_epriv(netdev); 13456442Speter 13561640Speter return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); 13616359Sasami} 13750518Snyan 13853120Snyanstatic int mlx5i_get_ts_info(struct net_device *netdev, 13961750Snyan struct ethtool_ts_info *info) 14061640Speter{ 14116359Sasami struct mlx5e_priv *priv = mlx5i_epriv(netdev); 14261640Speter 14350518Snyan return mlx5e_ethtool_get_ts_info(priv, info); 14448006Skato} 14561640Speter 14656711Snyanstatic int mlx5i_flash_device(struct net_device *netdev, 14756711Snyan struct ethtool_flash *flash) 14856711Snyan{ 14956711Snyan struct mlx5e_priv *priv = mlx5i_epriv(netdev); 15056711Snyan 15148006Skato return mlx5e_ethtool_flash_device(priv, flash); 15248006Skato} 15361741Skato 15416359Sasamistatic inline int mlx5_ptys_width_enum_to_int(enum mlx5_ptys_width width) 15550513Skato{ 15650518Snyan switch (width) { 15756442Speter case MLX5_PTYS_WIDTH_1X: return 1; 15856442Speter case MLX5_PTYS_WIDTH_2X: return 2; 15956442Speter case MLX5_PTYS_WIDTH_4X: return 4; 16056442Speter case MLX5_PTYS_WIDTH_8X: return 8; 16156442Speter case MLX5_PTYS_WIDTH_12X: return 12; 16251222Skato default: return -1; 16351222Skato } 16456442Speter} 16556442Speter 16656442Speterenum mlx5_ptys_rate { 16756442Speter MLX5_PTYS_RATE_SDR = 1 << 0, 16856442Speter MLX5_PTYS_RATE_DDR = 1 << 1, 16956442Speter MLX5_PTYS_RATE_QDR = 1 << 2, 17056442Speter MLX5_PTYS_RATE_FDR10 = 1 << 3, 17156442Speter MLX5_PTYS_RATE_FDR = 1 << 4, 17256442Speter MLX5_PTYS_RATE_EDR = 1 << 5, 17356442Speter MLX5_PTYS_RATE_HDR = 1 << 6, 17416359Sasami MLX5_PTYS_RATE_NDR = 1 << 7, 17553056Snyan MLX5_PTYS_RATE_XDR = 1 << 8, 17661750Snyan}; 17718095Sasami 17862007Skatostatic inline int mlx5_ptys_rate_enum_to_int(enum mlx5_ptys_rate rate) 17961750Snyan{ 18056372Snyan switch (rate) { 18155326Snyan case MLX5_PTYS_RATE_SDR: return 2500; 18261640Speter case MLX5_PTYS_RATE_DDR: return 5000; 18355326Snyan case MLX5_PTYS_RATE_QDR: 18461640Speter case MLX5_PTYS_RATE_FDR10: return 10000; 18561640Speter case MLX5_PTYS_RATE_FDR: return 14000; 18660717Snyan case MLX5_PTYS_RATE_EDR: return 25000; 18755326Snyan case MLX5_PTYS_RATE_HDR: return 50000; 18855086Skato case MLX5_PTYS_RATE_NDR: return 100000; 18954877Skato case MLX5_PTYS_RATE_XDR: return 200000; 19054877Skato default: return -1; 19156711Snyan } 19256323Skato} 19356323Skato 19456323Skatostatic u32 mlx5i_get_speed_settings(u16 ib_link_width_oper, u16 ib_proto_oper) 19556323Skato{ 19656323Skato int rate, width; 19756711Snyan 19860717Snyan rate = mlx5_ptys_rate_enum_to_int(ib_proto_oper); 19960717Snyan if (rate < 0) 20060717Snyan return SPEED_UNKNOWN; 20160717Snyan width = mlx5_ptys_width_enum_to_int(ib_link_width_oper); 20218095Sasami if (width < 0) 20356372Snyan return SPEED_UNKNOWN; 20461750Snyan 20556442Speter return rate * width; 20661640Speter} 20761640Speter 20861640Speterstatic int mlx5i_get_link_ksettings(struct net_device *netdev, 20961640Speter struct ethtool_link_ksettings *link_ksettings) 21061640Speter{ 21161640Speter struct mlx5e_priv *priv = mlx5i_epriv(netdev); 21261640Speter struct mlx5_core_dev *mdev = priv->mdev; 21316359Sasami u16 ib_link_width_oper; 21461640Speter u16 ib_proto_oper; 21558458Snyan int speed, ret; 21660711Snyan 21760711Snyan ret = mlx5_query_ib_port_oper(mdev, &ib_link_width_oper, &ib_proto_oper, 21860711Snyan 1); 21961640Speter if (ret) 22060711Snyan return ret; 22160711Snyan 22260711Snyan ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); 22361640Speter ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); 22460711Snyan 22550518Snyan speed = mlx5i_get_speed_settings(ib_link_width_oper, ib_proto_oper); 22661640Speter link_ksettings->base.speed = speed; 22761640Speter link_ksettings->base.duplex = speed == SPEED_UNKNOWN ? DUPLEX_UNKNOWN : DUPLEX_FULL; 22861640Speter 22961640Speter link_ksettings->base.port = PORT_OTHER; 23061640Speter 23161640Speter link_ksettings->base.autoneg = AUTONEG_DISABLE; 23261640Speter 23361640Speter return 0; 23461640Speter} 23517256Sasami 23661640Speterstatic u32 mlx5i_flow_type_mask(u32 flow_type) 23749519Skato{ 23861640Speter return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS); 23950551Sphk} 24061750Snyan 24155326Snyanstatic int mlx5i_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 24255326Snyan{ 24356442Speter struct mlx5e_priv *priv = mlx5i_epriv(dev); 24456442Speter struct ethtool_rx_flow_spec *fs = &cmd->fs; 24556442Speter 24660717Snyan if (mlx5i_flow_type_mask(fs->flow_type) == ETHER_FLOW) 24756442Speter return -EINVAL; 24856442Speter 24956442Speter return mlx5e_ethtool_set_rxnfc(priv, cmd); 25056442Speter} 25156978Skato 25256442Speterstatic int mlx5i_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 25360717Snyan u32 *rule_locs) 25457655Skato{ 25556442Speter struct mlx5e_priv *priv = mlx5i_epriv(dev); 25656442Speter 25756442Speter /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part 258 * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc, 259 * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc 260 * is compiled out via CONFIG_MLX5_EN_RXNFC=n. 261 */ 262 if (info->cmd == ETHTOOL_GRXRINGS) { 263 info->data = priv->channels.params.num_channels; 264 return 0; 265 } 266 267 return mlx5e_ethtool_get_rxnfc(priv, info, rule_locs); 268} 269 270const struct ethtool_ops mlx5i_ethtool_ops = { 271 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 272 ETHTOOL_COALESCE_MAX_FRAMES | 273 ETHTOOL_COALESCE_USE_ADAPTIVE, 274 .get_drvinfo = mlx5i_get_drvinfo, 275 .get_strings = mlx5i_get_strings, 276 .get_sset_count = mlx5i_get_sset_count, 277 .get_ethtool_stats = mlx5i_get_ethtool_stats, 278 .get_ringparam = mlx5i_get_ringparam, 279 .set_ringparam = mlx5i_set_ringparam, 280 .flash_device = mlx5i_flash_device, 281 .get_channels = mlx5i_get_channels, 282 .set_channels = mlx5i_set_channels, 283 .get_coalesce = mlx5i_get_coalesce, 284 .set_coalesce = mlx5i_set_coalesce, 285 .get_ts_info = mlx5i_get_ts_info, 286 .get_rxnfc = mlx5i_get_rxnfc, 287 .set_rxnfc = mlx5i_set_rxnfc, 288 .get_link_ksettings = mlx5i_get_link_ksettings, 289 .get_link = ethtool_op_get_link, 290}; 291 292const struct ethtool_ops mlx5i_pkey_ethtool_ops = { 293 .get_drvinfo = mlx5i_get_drvinfo, 294 .get_link = ethtool_op_get_link, 295 .get_ts_info = mlx5i_get_ts_info, 296}; 297