net/mlx5e: Correctly handle RSS indirection table when changing number of channels
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_main.c
index 6a3e430..02689ca 100644 (file)
@@ -1199,7 +1199,6 @@ static void mlx5e_fill_indir_rqt_rqns(struct mlx5e_priv *priv, void *rqtc)
                        ix = mlx5e_bits_invert(i, MLX5E_LOG_INDIR_RQT_SIZE);
 
                ix = priv->params.indirection_rqt[ix];
-               ix = ix % priv->params.num_channels;
                MLX5_SET(rqtc, rqtc, rq_num[i],
                         test_bit(MLX5E_STATE_OPENED, &priv->state) ?
                         priv->channel[ix]->rq.rqn :
@@ -1317,7 +1316,22 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
                              lro_timer_supported_periods[2]));
 }
 
-static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
+void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
+{
+       MLX5_SET(tirc, tirc, rx_hash_fn,
+                mlx5e_rx_hash_fn(priv->params.rss_hfunc));
+       if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
+               void *rss_key = MLX5_ADDR_OF(tirc, tirc,
+                                            rx_hash_toeplitz_key);
+               size_t len = MLX5_FLD_SZ_BYTES(tirc,
+                                              rx_hash_toeplitz_key);
+
+               MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
+               memcpy(rss_key, priv->params.toeplitz_hash_key, len);
+       }
+}
+
+static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
 
@@ -1325,6 +1339,7 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
        void *tirc;
        int inlen;
        int err;
+       int tt;
 
        inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
        in = mlx5_vzalloc(inlen);
@@ -1336,7 +1351,11 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
 
        mlx5e_build_tir_ctx_lro(tirc, priv);
 
-       err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
+       for (tt = 0; tt < MLX5E_NUM_TT; tt++) {
+               err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
+               if (err)
+                       break;
+       }
 
        kvfree(in);
 
@@ -1672,17 +1691,7 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
        default:
                MLX5_SET(tirc, tirc, indirect_table,
                         priv->rqtn[MLX5E_INDIRECTION_RQT]);
-               MLX5_SET(tirc, tirc, rx_hash_fn,
-                        mlx5e_rx_hash_fn(priv->params.rss_hfunc));
-               if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
-                       void *rss_key = MLX5_ADDR_OF(tirc, tirc,
-                                                    rx_hash_toeplitz_key);
-                       size_t len = MLX5_FLD_SZ_BYTES(tirc,
-                                                      rx_hash_toeplitz_key);
-
-                       MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
-                       memcpy(rss_key, priv->params.toeplitz_hash_key, len);
-               }
+               mlx5e_build_tir_ctx_hash(tirc, priv);
                break;
        }
 
@@ -1885,8 +1894,10 @@ static int mlx5e_set_features(struct net_device *netdev,
                        mlx5e_close_locked(priv->netdev);
 
                priv->params.lro_en = !!(features & NETIF_F_LRO);
-               mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV4_TCP);
-               mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV6_TCP);
+               err = mlx5e_modify_tirs_lro(priv);
+               if (err)
+                       mlx5_core_warn(priv->mdev, "lro modify failed, %d\n",
+                                      err);
 
                if (was_opened)
                        err = mlx5e_open_locked(priv->netdev);
@@ -2024,18 +2035,37 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
                                            vf_stats);
 }
 
-static struct net_device_ops mlx5e_netdev_ops = {
+static const struct net_device_ops mlx5e_netdev_ops_basic = {
        .ndo_open                = mlx5e_open,
        .ndo_stop                = mlx5e_close,
        .ndo_start_xmit          = mlx5e_xmit,
        .ndo_get_stats64         = mlx5e_get_stats,
        .ndo_set_rx_mode         = mlx5e_set_rx_mode,
        .ndo_set_mac_address     = mlx5e_set_mac,
-       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
-       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
+       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
        .ndo_set_features        = mlx5e_set_features,
-       .ndo_change_mtu          = mlx5e_change_mtu,
-       .ndo_do_ioctl            = mlx5e_ioctl,
+       .ndo_change_mtu          = mlx5e_change_mtu,
+       .ndo_do_ioctl            = mlx5e_ioctl,
+};
+
+static const struct net_device_ops mlx5e_netdev_ops_sriov = {
+       .ndo_open                = mlx5e_open,
+       .ndo_stop                = mlx5e_close,
+       .ndo_start_xmit          = mlx5e_xmit,
+       .ndo_get_stats64         = mlx5e_get_stats,
+       .ndo_set_rx_mode         = mlx5e_set_rx_mode,
+       .ndo_set_mac_address     = mlx5e_set_mac,
+       .ndo_vlan_rx_add_vid     = mlx5e_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid    = mlx5e_vlan_rx_kill_vid,
+       .ndo_set_features        = mlx5e_set_features,
+       .ndo_change_mtu          = mlx5e_change_mtu,
+       .ndo_do_ioctl            = mlx5e_ioctl,
+       .ndo_set_vf_mac          = mlx5e_set_vf_mac,
+       .ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
+       .ndo_get_vf_config       = mlx5e_get_vf_config,
+       .ndo_set_vf_link_state   = mlx5e_set_vf_link_state,
+       .ndo_get_vf_stats        = mlx5e_get_vf_stats,
 };
 
 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
@@ -2070,12 +2100,20 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
               2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
 }
 
+void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
+                                  int num_channels)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               indirection_rqt[i] = i % num_channels;
+}
+
 static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
                                    struct net_device *netdev,
                                    int num_channels)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       int i;
 
        priv->params.log_sq_size           =
                MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
@@ -2099,8 +2137,8 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
        netdev_rss_key_fill(priv->params.toeplitz_hash_key,
                            sizeof(priv->params.toeplitz_hash_key));
 
-       for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
-               priv->params.indirection_rqt[i] = i % num_channels;
+       mlx5e_build_default_indir_rqt(priv->params.indirection_rqt,
+                                     MLX5E_INDIR_RQT_SIZE, num_channels);
 
        priv->params.lro_wqe_sz            =
                MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
@@ -2137,18 +2175,11 @@ static void mlx5e_build_netdev(struct net_device *netdev)
 
        SET_NETDEV_DEV(netdev, &mdev->pdev->dev);
 
-       if (priv->params.num_tc > 1)
-               mlx5e_netdev_ops.ndo_select_queue = mlx5e_select_queue;
-
-       if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
-               mlx5e_netdev_ops.ndo_set_vf_mac = mlx5e_set_vf_mac;
-               mlx5e_netdev_ops.ndo_set_vf_vlan = mlx5e_set_vf_vlan;
-               mlx5e_netdev_ops.ndo_get_vf_config = mlx5e_get_vf_config;
-               mlx5e_netdev_ops.ndo_set_vf_link_state = mlx5e_set_vf_link_state;
-               mlx5e_netdev_ops.ndo_get_vf_stats = mlx5e_get_vf_stats;
-       }
+       if (MLX5_CAP_GEN(mdev, vport_group_manager))
+               netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
+       else
+               netdev->netdev_ops = &mlx5e_netdev_ops_basic;
 
-       netdev->netdev_ops        = &mlx5e_netdev_ops;
        netdev->watchdog_timeo    = 15 * HZ;
 
        netdev->ethtool_ops       = &mlx5e_ethtool_ops;