root/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlx5_query_port_tun_entropy
  2. mlx5_set_port_tun_entropy_calc
  3. mlx5_set_port_gre_tun_entropy_calc
  4. mlx5_init_port_tun_entropy
  5. mlx5_set_entropy
  6. mlx5_tun_entropy_refcount_inc
  7. mlx5_tun_entropy_refcount_dec

   1 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
   2 /* Copyright (c) 2019 Mellanox Technologies. */
   3 
   4 #include <linux/module.h>
   5 #include <linux/mlx5/driver.h>
   6 #include <linux/mlx5/port.h>
   7 #include <linux/mlx5/cmd.h>
   8 #include "mlx5_core.h"
   9 #include "lib/port_tun.h"
  10 
  11 struct mlx5_port_tun_entropy_flags {
  12         bool force_supported, force_enabled;
  13         bool calc_supported, calc_enabled;
  14         bool gre_calc_supported, gre_calc_enabled;
  15 };
  16 
  17 static void mlx5_query_port_tun_entropy(struct mlx5_core_dev *mdev,
  18                                         struct mlx5_port_tun_entropy_flags *entropy_flags)
  19 {
  20         u32 out[MLX5_ST_SZ_DW(pcmr_reg)];
  21         /* Default values for FW which do not support MLX5_REG_PCMR */
  22         entropy_flags->force_supported = false;
  23         entropy_flags->calc_supported = false;
  24         entropy_flags->gre_calc_supported = false;
  25         entropy_flags->force_enabled = false;
  26         entropy_flags->calc_enabled = true;
  27         entropy_flags->gre_calc_enabled = true;
  28 
  29         if (!MLX5_CAP_GEN(mdev, ports_check))
  30                 return;
  31 
  32         if (mlx5_query_ports_check(mdev, out, sizeof(out)))
  33                 return;
  34 
  35         entropy_flags->force_supported = !!(MLX5_GET(pcmr_reg, out, entropy_force_cap));
  36         entropy_flags->calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_calc_cap));
  37         entropy_flags->gre_calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc_cap));
  38         entropy_flags->force_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_force));
  39         entropy_flags->calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_calc));
  40         entropy_flags->gre_calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc));
  41 }
  42 
  43 static int mlx5_set_port_tun_entropy_calc(struct mlx5_core_dev *mdev, u8 enable,
  44                                           u8 force)
  45 {
  46         u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
  47         int err;
  48 
  49         err = mlx5_query_ports_check(mdev, in, sizeof(in));
  50         if (err)
  51                 return err;
  52         MLX5_SET(pcmr_reg, in, local_port, 1);
  53         MLX5_SET(pcmr_reg, in, entropy_force, force);
  54         MLX5_SET(pcmr_reg, in, entropy_calc, enable);
  55         return mlx5_set_ports_check(mdev, in, sizeof(in));
  56 }
  57 
  58 static int mlx5_set_port_gre_tun_entropy_calc(struct mlx5_core_dev *mdev,
  59                                               u8 enable, u8 force)
  60 {
  61         u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0};
  62         int err;
  63 
  64         err = mlx5_query_ports_check(mdev, in, sizeof(in));
  65         if (err)
  66                 return err;
  67         MLX5_SET(pcmr_reg, in, local_port, 1);
  68         MLX5_SET(pcmr_reg, in, entropy_force, force);
  69         MLX5_SET(pcmr_reg, in, entropy_gre_calc, enable);
  70         return mlx5_set_ports_check(mdev, in, sizeof(in));
  71 }
  72 
  73 void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy *tun_entropy,
  74                                 struct mlx5_core_dev *mdev)
  75 {
  76         struct mlx5_port_tun_entropy_flags entropy_flags;
  77 
  78         tun_entropy->mdev = mdev;
  79         mutex_init(&tun_entropy->lock);
  80         mlx5_query_port_tun_entropy(mdev, &entropy_flags);
  81         tun_entropy->num_enabling_entries = 0;
  82         tun_entropy->num_disabling_entries = 0;
  83         tun_entropy->enabled = entropy_flags.calc_supported ?
  84                                entropy_flags.calc_enabled : true;
  85 }
  86 
  87 static int mlx5_set_entropy(struct mlx5_tun_entropy *tun_entropy,
  88                             int reformat_type, bool enable)
  89 {
  90         struct mlx5_port_tun_entropy_flags entropy_flags;
  91         int err;
  92 
  93         mlx5_query_port_tun_entropy(tun_entropy->mdev, &entropy_flags);
  94         /* Tunnel entropy calculation may be controlled either on port basis
  95          * for all tunneling protocols or specifically for GRE protocol.
  96          * Prioritize GRE protocol control (if capable) over global port
  97          * configuration.
  98          */
  99         if (entropy_flags.gre_calc_supported &&
 100             reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) {
 101                 if (!entropy_flags.force_supported)
 102                         return 0;
 103                 err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev,
 104                                                          enable, !enable);
 105                 if (err)
 106                         return err;
 107         } else if (entropy_flags.calc_supported) {
 108                 /* Other applications may change the global FW entropy
 109                  * calculations settings. Check that the current entropy value
 110                  * is the negative of the updated value.
 111                  */
 112                 if (entropy_flags.force_enabled &&
 113                     enable == entropy_flags.calc_enabled) {
 114                         mlx5_core_warn(tun_entropy->mdev,
 115                                        "Unexpected entropy calc setting - expected %d",
 116                                        !entropy_flags.calc_enabled);
 117                         return -EOPNOTSUPP;
 118                 }
 119                 /* GRE requires disabling entropy calculation. if there are
 120                  * enabling entries (i.e VXLAN) we cannot turn it off for them,
 121                  * thus fail.
 122                  */
 123                 if (tun_entropy->num_enabling_entries)
 124                         return -EOPNOTSUPP;
 125                 err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, enable,
 126                                                      entropy_flags.force_supported);
 127                 if (err)
 128                         return err;
 129                 tun_entropy->enabled = enable;
 130                 /* if we turn on the entropy we don't need to force it anymore */
 131                 if (entropy_flags.force_supported && enable) {
 132                         err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, 1, 0);
 133                         if (err)
 134                                 return err;
 135                 }
 136         }
 137 
 138         return 0;
 139 }
 140 
 141 /* the function manages the refcount for enabling/disabling tunnel types.
 142  * the return value indicates if the inc is successful or not, depending on
 143  * entropy capabilities and configuration.
 144  */
 145 int mlx5_tun_entropy_refcount_inc(struct mlx5_tun_entropy *tun_entropy,
 146                                   int reformat_type)
 147 {
 148         /* the default is error for unknown (non VXLAN/GRE tunnel types) */
 149         int err = -EOPNOTSUPP;
 150 
 151         mutex_lock(&tun_entropy->lock);
 152         if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN &&
 153             tun_entropy->enabled) {
 154                 /* in case entropy calculation is enabled for all tunneling
 155                  * types, it is ok for VXLAN, so approve.
 156                  * otherwise keep the error default.
 157                  */
 158                 tun_entropy->num_enabling_entries++;
 159                 err = 0;
 160         } else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) {
 161                 /* turn off the entropy only for the first GRE rule.
 162                  * for the next rules the entropy was already disabled
 163                  * successfully.
 164                  */
 165                 if (tun_entropy->num_disabling_entries == 0)
 166                         err = mlx5_set_entropy(tun_entropy, reformat_type, 0);
 167                 else
 168                         err = 0;
 169                 if (!err)
 170                         tun_entropy->num_disabling_entries++;
 171         }
 172         mutex_unlock(&tun_entropy->lock);
 173 
 174         return err;
 175 }
 176 
 177 void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy,
 178                                    int reformat_type)
 179 {
 180         mutex_lock(&tun_entropy->lock);
 181         if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN)
 182                 tun_entropy->num_enabling_entries--;
 183         else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE &&
 184                  --tun_entropy->num_disabling_entries == 0)
 185                 mlx5_set_entropy(tun_entropy, reformat_type, 1);
 186         mutex_unlock(&tun_entropy->lock);
 187 }
 188 

/* [<][>][^][v][top][bottom][index][help] */