Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
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     /* ETHTOOL_GRXRINGS is needed by ethtool -x which is not part
0246      * of rxnfc. We keep this logic out of mlx5e_ethtool_get_rxnfc,
0247      * to avoid breaking "ethtool -x" when mlx5e_ethtool_get_rxnfc
0248      * is compiled out via CONFIG_MLX5_EN_RXNFC=n.
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 };