root/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c

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

DEFINITIONS

This source file includes following definitions.
  1. mlx5dr_table_set_miss_action
  2. dr_table_uninit_nic
  3. dr_table_uninit_fdb
  4. dr_table_uninit
  5. dr_table_init_nic
  6. dr_table_init_fdb
  7. dr_table_init
  8. dr_table_destroy_sw_owned_tbl
  9. dr_table_create_sw_owned_tbl
  10. mlx5dr_table_create
  11. mlx5dr_table_destroy
  12. mlx5dr_table_get_id

   1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2 /* Copyright (c) 2019 Mellanox Technologies. */
   3 
   4 #include "dr_types.h"
   5 
   6 int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
   7                                  struct mlx5dr_action *action)
   8 {
   9         struct mlx5dr_matcher *last_matcher = NULL;
  10         struct mlx5dr_htbl_connect_info info;
  11         struct mlx5dr_ste_htbl *last_htbl;
  12         int ret;
  13 
  14         if (action && action->action_type != DR_ACTION_TYP_FT)
  15                 return -EOPNOTSUPP;
  16 
  17         mutex_lock(&tbl->dmn->mutex);
  18 
  19         if (!list_empty(&tbl->matcher_list))
  20                 last_matcher = list_last_entry(&tbl->matcher_list,
  21                                                struct mlx5dr_matcher,
  22                                                matcher_list);
  23 
  24         if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX ||
  25             tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
  26                 if (last_matcher)
  27                         last_htbl = last_matcher->rx.e_anchor;
  28                 else
  29                         last_htbl = tbl->rx.s_anchor;
  30 
  31                 tbl->rx.default_icm_addr = action ?
  32                         action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
  33                         tbl->rx.nic_dmn->default_icm_addr;
  34 
  35                 info.type = CONNECT_MISS;
  36                 info.miss_icm_addr = tbl->rx.default_icm_addr;
  37 
  38                 ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
  39                                                         tbl->rx.nic_dmn,
  40                                                         last_htbl,
  41                                                         &info, true);
  42                 if (ret) {
  43                         mlx5dr_dbg(tbl->dmn, "Failed to set RX miss action, ret %d\n", ret);
  44                         goto out;
  45                 }
  46         }
  47 
  48         if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX ||
  49             tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
  50                 if (last_matcher)
  51                         last_htbl = last_matcher->tx.e_anchor;
  52                 else
  53                         last_htbl = tbl->tx.s_anchor;
  54 
  55                 tbl->tx.default_icm_addr = action ?
  56                         action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr :
  57                         tbl->tx.nic_dmn->default_icm_addr;
  58 
  59                 info.type = CONNECT_MISS;
  60                 info.miss_icm_addr = tbl->tx.default_icm_addr;
  61 
  62                 ret = mlx5dr_ste_htbl_init_and_postsend(tbl->dmn,
  63                                                         tbl->tx.nic_dmn,
  64                                                         last_htbl, &info, true);
  65                 if (ret) {
  66                         mlx5dr_dbg(tbl->dmn, "Failed to set TX miss action, ret %d\n", ret);
  67                         goto out;
  68                 }
  69         }
  70 
  71         /* Release old action */
  72         if (tbl->miss_action)
  73                 refcount_dec(&tbl->miss_action->refcount);
  74 
  75         /* Set new miss action */
  76         tbl->miss_action = action;
  77         if (tbl->miss_action)
  78                 refcount_inc(&action->refcount);
  79 
  80 out:
  81         mutex_unlock(&tbl->dmn->mutex);
  82         return ret;
  83 }
  84 
  85 static void dr_table_uninit_nic(struct mlx5dr_table_rx_tx *nic_tbl)
  86 {
  87         mlx5dr_htbl_put(nic_tbl->s_anchor);
  88 }
  89 
  90 static void dr_table_uninit_fdb(struct mlx5dr_table *tbl)
  91 {
  92         dr_table_uninit_nic(&tbl->rx);
  93         dr_table_uninit_nic(&tbl->tx);
  94 }
  95 
  96 static void dr_table_uninit(struct mlx5dr_table *tbl)
  97 {
  98         mutex_lock(&tbl->dmn->mutex);
  99 
 100         switch (tbl->dmn->type) {
 101         case MLX5DR_DOMAIN_TYPE_NIC_RX:
 102                 dr_table_uninit_nic(&tbl->rx);
 103                 break;
 104         case MLX5DR_DOMAIN_TYPE_NIC_TX:
 105                 dr_table_uninit_nic(&tbl->tx);
 106                 break;
 107         case MLX5DR_DOMAIN_TYPE_FDB:
 108                 dr_table_uninit_fdb(tbl);
 109                 break;
 110         default:
 111                 WARN_ON(true);
 112                 break;
 113         }
 114 
 115         mutex_unlock(&tbl->dmn->mutex);
 116 }
 117 
 118 static int dr_table_init_nic(struct mlx5dr_domain *dmn,
 119                              struct mlx5dr_table_rx_tx *nic_tbl)
 120 {
 121         struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn;
 122         struct mlx5dr_htbl_connect_info info;
 123         int ret;
 124 
 125         nic_tbl->default_icm_addr = nic_dmn->default_icm_addr;
 126 
 127         nic_tbl->s_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
 128                                                   DR_CHUNK_SIZE_1,
 129                                                   MLX5DR_STE_LU_TYPE_DONT_CARE,
 130                                                   0);
 131         if (!nic_tbl->s_anchor)
 132                 return -ENOMEM;
 133 
 134         info.type = CONNECT_MISS;
 135         info.miss_icm_addr = nic_dmn->default_icm_addr;
 136         ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn,
 137                                                 nic_tbl->s_anchor,
 138                                                 &info, true);
 139         if (ret)
 140                 goto free_s_anchor;
 141 
 142         mlx5dr_htbl_get(nic_tbl->s_anchor);
 143 
 144         return 0;
 145 
 146 free_s_anchor:
 147         mlx5dr_ste_htbl_free(nic_tbl->s_anchor);
 148         return ret;
 149 }
 150 
 151 static int dr_table_init_fdb(struct mlx5dr_table *tbl)
 152 {
 153         int ret;
 154 
 155         ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
 156         if (ret)
 157                 return ret;
 158 
 159         ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
 160         if (ret)
 161                 goto destroy_rx;
 162 
 163         return 0;
 164 
 165 destroy_rx:
 166         dr_table_uninit_nic(&tbl->rx);
 167         return ret;
 168 }
 169 
 170 static int dr_table_init(struct mlx5dr_table *tbl)
 171 {
 172         int ret = 0;
 173 
 174         INIT_LIST_HEAD(&tbl->matcher_list);
 175 
 176         mutex_lock(&tbl->dmn->mutex);
 177 
 178         switch (tbl->dmn->type) {
 179         case MLX5DR_DOMAIN_TYPE_NIC_RX:
 180                 tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_RX;
 181                 tbl->rx.nic_dmn = &tbl->dmn->info.rx;
 182                 ret = dr_table_init_nic(tbl->dmn, &tbl->rx);
 183                 break;
 184         case MLX5DR_DOMAIN_TYPE_NIC_TX:
 185                 tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_TX;
 186                 tbl->tx.nic_dmn = &tbl->dmn->info.tx;
 187                 ret = dr_table_init_nic(tbl->dmn, &tbl->tx);
 188                 break;
 189         case MLX5DR_DOMAIN_TYPE_FDB:
 190                 tbl->table_type = MLX5_FLOW_TABLE_TYPE_FDB;
 191                 tbl->rx.nic_dmn = &tbl->dmn->info.rx;
 192                 tbl->tx.nic_dmn = &tbl->dmn->info.tx;
 193                 ret = dr_table_init_fdb(tbl);
 194                 break;
 195         default:
 196                 WARN_ON(true);
 197                 break;
 198         }
 199 
 200         mutex_unlock(&tbl->dmn->mutex);
 201 
 202         return ret;
 203 }
 204 
 205 static int dr_table_destroy_sw_owned_tbl(struct mlx5dr_table *tbl)
 206 {
 207         return mlx5dr_cmd_destroy_flow_table(tbl->dmn->mdev,
 208                                              tbl->table_id,
 209                                              tbl->table_type);
 210 }
 211 
 212 static int dr_table_create_sw_owned_tbl(struct mlx5dr_table *tbl)
 213 {
 214         u64 icm_addr_rx = 0;
 215         u64 icm_addr_tx = 0;
 216         int ret;
 217 
 218         if (tbl->rx.s_anchor)
 219                 icm_addr_rx = tbl->rx.s_anchor->chunk->icm_addr;
 220 
 221         if (tbl->tx.s_anchor)
 222                 icm_addr_tx = tbl->tx.s_anchor->chunk->icm_addr;
 223 
 224         ret = mlx5dr_cmd_create_flow_table(tbl->dmn->mdev,
 225                                            tbl->table_type,
 226                                            icm_addr_rx,
 227                                            icm_addr_tx,
 228                                            tbl->dmn->info.caps.max_ft_level - 1,
 229                                            true, false, NULL,
 230                                            &tbl->table_id);
 231 
 232         return ret;
 233 }
 234 
 235 struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_domain *dmn, u32 level)
 236 {
 237         struct mlx5dr_table *tbl;
 238         int ret;
 239 
 240         refcount_inc(&dmn->refcount);
 241 
 242         tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
 243         if (!tbl)
 244                 goto dec_ref;
 245 
 246         tbl->dmn = dmn;
 247         tbl->level = level;
 248         refcount_set(&tbl->refcount, 1);
 249 
 250         ret = dr_table_init(tbl);
 251         if (ret)
 252                 goto free_tbl;
 253 
 254         ret = dr_table_create_sw_owned_tbl(tbl);
 255         if (ret)
 256                 goto uninit_tbl;
 257 
 258         return tbl;
 259 
 260 uninit_tbl:
 261         dr_table_uninit(tbl);
 262 free_tbl:
 263         kfree(tbl);
 264 dec_ref:
 265         refcount_dec(&dmn->refcount);
 266         return NULL;
 267 }
 268 
 269 int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
 270 {
 271         int ret;
 272 
 273         if (refcount_read(&tbl->refcount) > 1)
 274                 return -EBUSY;
 275 
 276         ret = dr_table_destroy_sw_owned_tbl(tbl);
 277         if (ret)
 278                 return ret;
 279 
 280         dr_table_uninit(tbl);
 281 
 282         if (tbl->miss_action)
 283                 refcount_dec(&tbl->miss_action->refcount);
 284 
 285         refcount_dec(&tbl->dmn->refcount);
 286         kfree(tbl);
 287 
 288         return ret;
 289 }
 290 
 291 u32 mlx5dr_table_get_id(struct mlx5dr_table *tbl)
 292 {
 293         return tbl->table_id;
 294 }

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