Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_ethtool.c
index d674cb6..6d703dd 100644 (file)
@@ -357,7 +357,7 @@ int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv,
                goto unlock;
        }
 
-       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
 
 unlock:
        mutex_unlock(&priv->state_lock);
@@ -432,9 +432,7 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                *cur_params = new_channels.params;
-               if (!netif_is_rxfh_configured(priv->netdev))
-                       mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-                                                     MLX5E_INDIR_RQT_SIZE, count);
+               mlx5e_num_channels_changed(priv);
                goto out;
        }
 
@@ -442,12 +440,9 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
-       if (!netif_is_rxfh_configured(priv->netdev))
-               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-                                             MLX5E_INDIR_RQT_SIZE, count);
-
        /* Switch to new channels, set new parameters and close old ones */
-       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       err = mlx5e_safe_switch_channels(priv, &new_channels,
+                                        mlx5e_num_channels_changed_ctx, NULL);
 
        if (arfs_enabled) {
                int err2 = mlx5e_arfs_enable(priv);
@@ -580,7 +575,7 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv,
                goto out;
        }
 
-       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
 
 out:
        mutex_unlock(&priv->state_lock);
@@ -633,6 +628,8 @@ static const u32 pplm_fec_2_ethtool[] = {
        [MLX5E_FEC_NOFEC] = ETHTOOL_FEC_OFF,
        [MLX5E_FEC_FIRECODE] = ETHTOOL_FEC_BASER,
        [MLX5E_FEC_RS_528_514] = ETHTOOL_FEC_RS,
+       [MLX5E_FEC_RS_544_514] = ETHTOOL_FEC_RS,
+       [MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_FEC_LLRS,
 };
 
 static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
@@ -650,45 +647,48 @@ static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
        return 0;
 }
 
-/* we use ETHTOOL_FEC_* offset and apply it to ETHTOOL_LINK_MODE_FEC_*_BIT */
-static u32 ethtool_fec2ethtool_caps(u_long ethtool_fec_code)
-{
-       u32 offset;
-
-       offset = find_first_bit(&ethtool_fec_code, sizeof(u32));
-       offset -= ETHTOOL_FEC_OFF_BIT;
-       offset += ETHTOOL_LINK_MODE_FEC_NONE_BIT;
+#define MLX5E_ADVERTISE_SUPPORTED_FEC(mlx5_fec, ethtool_fec)           \
+       do {                                                            \
+               if (mlx5e_fec_in_caps(dev, 1 << (mlx5_fec)))            \
+                       __set_bit(ethtool_fec,                          \
+                                 link_ksettings->link_modes.supported);\
+       } while (0)
 
-       return offset;
-}
+static const u32 pplm_fec_2_ethtool_linkmodes[] = {
+       [MLX5E_FEC_NOFEC] = ETHTOOL_LINK_MODE_FEC_NONE_BIT,
+       [MLX5E_FEC_FIRECODE] = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
+       [MLX5E_FEC_RS_528_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
+       [MLX5E_FEC_RS_544_514] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
+       [MLX5E_FEC_LLRS_272_257_1] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
+};
 
 static int get_fec_supported_advertised(struct mlx5_core_dev *dev,
                                        struct ethtool_link_ksettings *link_ksettings)
 {
-       u_long fec_caps = 0;
-       u32 active_fec = 0;
-       u32 offset;
+       u_long active_fec = 0;
        u32 bitn;
        int err;
 
-       err = mlx5e_get_fec_caps(dev, (u8 *)&fec_caps);
+       err = mlx5e_get_fec_mode(dev, (u32 *)&active_fec, NULL);
        if (err)
                return (err == -EOPNOTSUPP) ? 0 : err;
 
-       err = mlx5e_get_fec_mode(dev, &active_fec, NULL);
-       if (err)
-               return err;
-
-       for_each_set_bit(bitn, &fec_caps, ARRAY_SIZE(pplm_fec_2_ethtool)) {
-               u_long ethtool_bitmask = pplm_fec_2_ethtool[bitn];
-
-               offset = ethtool_fec2ethtool_caps(ethtool_bitmask);
-               __set_bit(offset, link_ksettings->link_modes.supported);
-       }
-
-       active_fec = pplm2ethtool_fec(active_fec, sizeof(u32) * BITS_PER_BYTE);
-       offset = ethtool_fec2ethtool_caps(active_fec);
-       __set_bit(offset, link_ksettings->link_modes.advertising);
+       MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_NOFEC,
+                                     ETHTOOL_LINK_MODE_FEC_NONE_BIT);
+       MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_FIRECODE,
+                                     ETHTOOL_LINK_MODE_FEC_BASER_BIT);
+       MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_RS_528_514,
+                                     ETHTOOL_LINK_MODE_FEC_RS_BIT);
+       MLX5E_ADVERTISE_SUPPORTED_FEC(MLX5E_FEC_LLRS_272_257_1,
+                                     ETHTOOL_LINK_MODE_FEC_LLRS_BIT);
+
+       /* active fec is a bit set, find out which bit is set and
+        * advertise the corresponding ethtool bit
+        */
+       bitn = find_first_bit(&active_fec, sizeof(u32) * BITS_PER_BYTE);
+       if (bitn < ARRAY_SIZE(pplm_fec_2_ethtool_linkmodes))
+               __set_bit(pplm_fec_2_ethtool_linkmodes[bitn],
+                         link_ksettings->link_modes.advertising);
 
        return 0;
 }
@@ -773,6 +773,7 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
 
 static void get_speed_duplex(struct net_device *netdev,
                             u32 eth_proto_oper, bool force_legacy,
+                            u16 data_rate_oper,
                             struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -784,7 +785,10 @@ static void get_speed_duplex(struct net_device *netdev,
 
        speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
        if (!speed) {
-               speed = SPEED_UNKNOWN;
+               if (data_rate_oper)
+                       speed = 100 * data_rate_oper;
+               else
+                       speed = SPEED_UNKNOWN;
                goto out;
        }
 
@@ -873,17 +877,18 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
                                     struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
-       u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
-       u32 rx_pause = 0;
-       u32 tx_pause = 0;
-       u32 eth_proto_cap;
+       u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {};
        u32 eth_proto_admin;
-       u32 eth_proto_lp;
-       u32 eth_proto_oper;
        u8 an_disable_admin;
-       u8 an_status;
+       u16 data_rate_oper;
+       u32 eth_proto_oper;
+       u32 eth_proto_cap;
        u8 connector_type;
+       u32 rx_pause = 0;
+       u32 tx_pause = 0;
+       u32 eth_proto_lp;
        bool admin_ext;
+       u8 an_status;
        bool ext;
        int err;
 
@@ -917,6 +922,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        an_disable_admin    = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status           = MLX5_GET(ptys_reg, out, an_status);
        connector_type      = MLX5_GET(ptys_reg, out, connector_type);
+       data_rate_oper      = MLX5_GET(ptys_reg, out, data_rate_oper);
 
        mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
 
@@ -927,7 +933,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
                        admin_ext);
        get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
-                        link_ksettings);
+                        data_rate_oper, link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 
@@ -1126,8 +1132,8 @@ static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
        return mlx5e_ethtool_get_rxfh_indir_size(priv);
 }
 
-static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
-                         u8 *hfunc)
+int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+                  u8 *hfunc)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5e_rss_params *rss = &priv->rss_params;
@@ -1146,8 +1152,8 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
        return 0;
 }
 
-static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
-                         const u8 *key, const u8 hfunc)
+int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
+                  const u8 *key, const u8 hfunc)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rss_params *rss = &priv->rss_params;
@@ -1511,7 +1517,7 @@ static int mlx5e_get_fecparam(struct net_device *netdev,
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
-       u8 fec_configured = 0;
+       u16 fec_configured = 0;
        u32 fec_active = 0;
        int err;
 
@@ -1527,7 +1533,7 @@ static int mlx5e_get_fecparam(struct net_device *netdev,
                return -EOPNOTSUPP;
 
        fecparam->fec = pplm2ethtool_fec((u_long)fec_configured,
-                                        sizeof(u8) * BITS_PER_BYTE);
+                                        sizeof(u16) * BITS_PER_BYTE);
 
        return 0;
 }
@@ -1537,10 +1543,14 @@ static int mlx5e_set_fecparam(struct net_device *netdev,
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
-       u8 fec_policy = 0;
+       u16 fec_policy = 0;
        int mode;
        int err;
 
+       if (bitmap_weight((unsigned long *)&fecparam->fec,
+                         ETHTOOL_FEC_LLRS_BIT + 1) > 1)
+               return -EOPNOTSUPP;
+
        for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
                if (!(pplm_fec_2_ethtool[mode] & fecparam->fec))
                        continue;
@@ -1739,7 +1749,7 @@ static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
                return 0;
        }
 
-       return mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
 }
 
 static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable)
@@ -1772,7 +1782,7 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
                return 0;
        }
 
-       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
        if (err)
                return err;
 
@@ -1829,7 +1839,7 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
                return 0;
        }
 
-       return mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       return mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
 }
 
 static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
@@ -1873,7 +1883,7 @@ static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable)
                return 0;
        }
 
-       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+       err = mlx5e_safe_switch_channels(priv, &new_channels, NULL, NULL);
        return err;
 }
 
@@ -1938,7 +1948,8 @@ static u32 mlx5e_get_priv_flags(struct net_device *netdev)
        return priv->channels.params.pflags;
 }
 
-static int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *rule_locs)
+int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
+                   u32 *rule_locs)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
 
@@ -1955,12 +1966,15 @@ static int mlx5e_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u
        return mlx5e_ethtool_get_rxnfc(dev, info, rule_locs);
 }
 
-static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 {
        return mlx5e_ethtool_set_rxnfc(dev, cmd);
 }
 
 const struct ethtool_ops mlx5e_ethtool_ops = {
+       .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
+                                    ETHTOOL_COALESCE_MAX_FRAMES |
+                                    ETHTOOL_COALESCE_USE_ADAPTIVE,
        .get_drvinfo       = mlx5e_get_drvinfo,
        .get_link          = ethtool_op_get_link,
        .get_strings       = mlx5e_get_strings,