LCOV - code coverage report
Current view: top level - drivers/net/mlx5 - mlx5_flow_flex.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 645 0.0 %
Date: 2026-04-01 20:02:27 Functions: 0 37 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 530 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2021 NVIDIA Corporation & Affiliates
       3                 :            :  */
       4                 :            : #include <rte_malloc.h>
       5                 :            : #include <mlx5_devx_cmds.h>
       6                 :            : #include <mlx5_malloc.h>
       7                 :            : #include "mlx5.h"
       8                 :            : #include "mlx5_flow.h"
       9                 :            : 
      10                 :            : static_assert(sizeof(uint32_t) * CHAR_BIT >= MLX5_PORT_FLEX_ITEM_NUM,
      11                 :            :               "Flex item maximal number exceeds uint32_t bit width");
      12                 :            : 
      13                 :            : /**
      14                 :            :  *  Routine called once on port initialization to init flex item
      15                 :            :  *  related infrastructure initialization
      16                 :            :  *
      17                 :            :  * @param dev
      18                 :            :  *   Ethernet device to perform flex item initialization
      19                 :            :  *
      20                 :            :  * @return
      21                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
      22                 :            :  */
      23                 :            : int
      24                 :          0 : mlx5_flex_item_port_init(struct rte_eth_dev *dev)
      25                 :            : {
      26                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      27                 :            : 
      28                 :            :         rte_spinlock_init(&priv->flex_item_sl);
      29                 :            :         MLX5_ASSERT(!priv->flex_item_map);
      30                 :          0 :         return 0;
      31                 :            : }
      32                 :            : 
      33                 :            : /**
      34                 :            :  *  Routine called once on port close to perform flex item
      35                 :            :  *  related infrastructure cleanup.
      36                 :            :  *
      37                 :            :  * @param dev
      38                 :            :  *   Ethernet device to perform cleanup
      39                 :            :  */
      40                 :            : void
      41                 :          0 : mlx5_flex_item_port_cleanup(struct rte_eth_dev *dev)
      42                 :            : {
      43                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
      44                 :            :         uint32_t i;
      45                 :            : 
      46   [ #  #  #  # ]:          0 :         for (i = 0; i < MLX5_PORT_FLEX_ITEM_NUM && priv->flex_item_map ; i++) {
      47         [ #  # ]:          0 :                 if (priv->flex_item_map & (1 << i)) {
      48                 :            :                         struct mlx5_flex_item *flex = &priv->flex_item[i];
      49                 :            : 
      50                 :          0 :                         claim_zero(mlx5_list_unregister
      51                 :            :                                         (priv->sh->flex_parsers_dv,
      52                 :            :                                          &flex->devx_fp->entry));
      53                 :          0 :                         flex->devx_fp = NULL;
      54                 :          0 :                         flex->refcnt = 0;
      55                 :          0 :                         priv->flex_item_map &= ~(1 << i);
      56                 :            :                 }
      57                 :            :         }
      58                 :          0 : }
      59                 :            : 
      60                 :            : static int
      61                 :            : mlx5_flex_index(struct mlx5_priv *priv, struct mlx5_flex_item *item)
      62                 :            : {
      63                 :          0 :         uintptr_t start = (uintptr_t)&priv->flex_item[0];
      64                 :          0 :         uintptr_t entry = (uintptr_t)item;
      65                 :          0 :         uintptr_t idx = (entry - start) / sizeof(struct mlx5_flex_item);
      66                 :            : 
      67                 :          0 :         if (entry < start ||
      68         [ #  # ]:          0 :             idx >= MLX5_PORT_FLEX_ITEM_NUM ||
      69   [ #  #  #  #  :          0 :             (entry - start) % sizeof(struct mlx5_flex_item) ||
                   #  # ]
      70   [ #  #  #  #  :          0 :             !(priv->flex_item_map & (1u << idx)))
                   #  # ]
      71                 :            :                 return -1;
      72                 :          0 :         return (int)idx;
      73                 :            : }
      74                 :            : 
      75                 :            : static struct mlx5_flex_item *
      76                 :          0 : mlx5_flex_alloc(struct mlx5_priv *priv)
      77                 :            : {
      78                 :            :         struct mlx5_flex_item *item = NULL;
      79                 :            : 
      80                 :          0 :         rte_spinlock_lock(&priv->flex_item_sl);
      81         [ #  # ]:          0 :         if (~priv->flex_item_map) {
      82         [ #  # ]:          0 :                 uint32_t idx = rte_bsf32(~priv->flex_item_map);
      83                 :            : 
      84         [ #  # ]:          0 :                 if (idx < MLX5_PORT_FLEX_ITEM_NUM) {
      85                 :          0 :                         item = &priv->flex_item[idx];
      86                 :            :                         MLX5_ASSERT(!item->refcnt);
      87                 :            :                         MLX5_ASSERT(!item->devx_fp);
      88                 :          0 :                         item->devx_fp = NULL;
      89                 :          0 :                         rte_atomic_store_explicit(&item->refcnt, 0, rte_memory_order_release);
      90                 :          0 :                         priv->flex_item_map |= 1u << idx;
      91                 :            :                 }
      92                 :            :         }
      93                 :            :         rte_spinlock_unlock(&priv->flex_item_sl);
      94                 :          0 :         return item;
      95                 :            : }
      96                 :            : 
      97                 :            : static void
      98         [ #  # ]:          0 : mlx5_flex_free(struct mlx5_priv *priv, struct mlx5_flex_item *item)
      99                 :            : {
     100                 :            :         int idx = mlx5_flex_index(priv, item);
     101                 :            : 
     102                 :            :         MLX5_ASSERT(idx >= 0 &&
     103                 :            :                     idx < MLX5_PORT_FLEX_ITEM_NUM &&
     104                 :            :                     (priv->flex_item_map & (1u << idx)));
     105         [ #  # ]:          0 :         if (idx >= 0) {
     106                 :          0 :                 rte_spinlock_lock(&priv->flex_item_sl);
     107                 :            :                 MLX5_ASSERT(!item->refcnt);
     108                 :            :                 MLX5_ASSERT(!item->devx_fp);
     109                 :          0 :                 item->devx_fp = NULL;
     110                 :          0 :                 rte_atomic_store_explicit(&item->refcnt, 0, rte_memory_order_release);
     111                 :          0 :                 priv->flex_item_map &= ~(1u << idx);
     112                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
     113                 :            :         }
     114                 :          0 : }
     115                 :            : 
     116                 :            : static uint32_t
     117                 :          0 : mlx5_flex_get_bitfield(const struct rte_flow_item_flex *item,
     118                 :            :                        uint32_t pos, uint32_t width, uint32_t shift)
     119                 :            : {
     120                 :          0 :         const uint8_t *ptr = item->pattern + pos / CHAR_BIT;
     121                 :          0 :         uint32_t val, vbits, skip = pos % CHAR_BIT;
     122                 :            : 
     123                 :            :         /* Proceed the bitfield start byte. */
     124                 :            :         MLX5_ASSERT(width <= sizeof(uint32_t) * CHAR_BIT && width);
     125                 :            :         MLX5_ASSERT(width + shift <= sizeof(uint32_t) * CHAR_BIT);
     126         [ #  # ]:          0 :         if (item->length <= pos / CHAR_BIT)
     127                 :            :                 return 0;
     128                 :            :         /* Bits are enumerated in byte in network order: 01234567 */
     129                 :          0 :         val = *ptr++;
     130                 :          0 :         vbits = CHAR_BIT - pos % CHAR_BIT;
     131                 :          0 :         pos = RTE_ALIGN_CEIL(pos, CHAR_BIT) / CHAR_BIT;
     132                 :          0 :         vbits = RTE_MIN(vbits, width);
     133                 :            :         /* Load bytes to cover the field width, checking pattern boundary */
     134   [ #  #  #  # ]:          0 :         while (vbits < width && pos < item->length) {
     135                 :          0 :                 uint32_t part = RTE_MIN(width - vbits, (uint32_t)CHAR_BIT);
     136                 :          0 :                 uint32_t tmp = *ptr++;
     137                 :            : 
     138                 :          0 :                 val |= tmp << RTE_ALIGN_CEIL(vbits, CHAR_BIT);
     139                 :          0 :                 vbits += part;
     140                 :          0 :                 pos++;
     141                 :            :         }
     142         [ #  # ]:          0 :         val = rte_cpu_to_be_32(val);
     143                 :          0 :         val <<= skip;
     144                 :          0 :         val >>= shift;
     145                 :          0 :         val &= (RTE_BIT64(width) - 1) << (sizeof(uint32_t) * CHAR_BIT - shift - width);
     146                 :          0 :         return val;
     147                 :            : }
     148                 :            : 
     149                 :            : #define SET_FP_MATCH_SAMPLE_ID(x, def, msk, val, sid) \
     150                 :            :         do { \
     151                 :            :                 uint32_t tmp, out = (def); \
     152                 :            :                 tmp = MLX5_GET(fte_match_set_misc4, misc4_v, \
     153                 :            :                                prog_sample_field_value_##x); \
     154                 :            :                 tmp = (tmp & ~out) | (val); \
     155                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_v, \
     156                 :            :                          prog_sample_field_value_##x, tmp); \
     157                 :            :                 tmp = MLX5_GET(fte_match_set_misc4, misc4_m, \
     158                 :            :                                prog_sample_field_value_##x); \
     159                 :            :                 tmp = (tmp & ~out) | (msk); \
     160                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_m, \
     161                 :            :                          prog_sample_field_value_##x, tmp); \
     162                 :            :                 tmp = tmp ? (sid) : 0; \
     163                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_v, \
     164                 :            :                          prog_sample_field_id_##x, tmp);\
     165                 :            :                 MLX5_SET(fte_match_set_misc4, misc4_m, \
     166                 :            :                          prog_sample_field_id_##x, tmp); \
     167                 :            :         } while (0)
     168                 :            : 
     169                 :            : __rte_always_inline static void
     170                 :            : mlx5_flex_set_match_sample(void *misc4_m, void *misc4_v,
     171                 :            :                            uint32_t def, uint32_t mask, uint32_t value,
     172                 :            :                            uint32_t sample_id, uint32_t id)
     173                 :            : {
     174                 :          0 :         switch (id) {
     175                 :          0 :         case 0:
     176   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(0, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     177                 :          0 :                 break;
     178                 :          0 :         case 1:
     179   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(1, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     180                 :          0 :                 break;
     181                 :          0 :         case 2:
     182   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(2, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     183                 :          0 :                 break;
     184                 :          0 :         case 3:
     185   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(3, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     186                 :          0 :                 break;
     187                 :          0 :         case 4:
     188   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(4, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     189                 :          0 :                 break;
     190                 :          0 :         case 5:
     191   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(5, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     192                 :          0 :                 break;
     193                 :          0 :         case 6:
     194   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(6, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     195                 :          0 :                 break;
     196                 :          0 :         case 7:
     197   [ #  #  #  #  :          0 :                 SET_FP_MATCH_SAMPLE_ID(7, def, mask, value, sample_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     198                 :          0 :                 break;
     199                 :            :         default:
     200                 :            :                 MLX5_ASSERT(false);
     201                 :            :                 break;
     202                 :            :         }
     203                 :            : #undef SET_FP_MATCH_SAMPLE_ID
     204                 :            : }
     205                 :            : 
     206                 :            : /**
     207                 :            :  * Get the flex parser sample id and corresponding mask
     208                 :            :  * per shift and width information.
     209                 :            :  *
     210                 :            :  * @param[in] tp
     211                 :            :  *   Mlx5 flex item sample mapping handle.
     212                 :            :  * @param[in] idx
     213                 :            :  *   Mapping index.
     214                 :            :  * @param[in, out] pos
     215                 :            :  *   Where to search the value and mask.
     216                 :            :  * @param[in] is_inner
     217                 :            :  *   For inner matching or not.
     218                 :            :  *
     219                 :            :  * @return
     220                 :            :  *   0 on success, -1 to ignore.
     221                 :            :  */
     222                 :            : int
     223                 :          0 : mlx5_flex_get_sample_id(const struct mlx5_flex_item *tp,
     224                 :            :                         uint32_t idx, uint32_t *pos, bool is_inner)
     225                 :            : {
     226                 :          0 :         const struct mlx5_flex_pattern_field *map = tp->map + idx;
     227                 :          0 :         uint32_t id = map->reg_id;
     228                 :            : 
     229                 :            :         /* Skip placeholders for DUMMY fields. */
     230         [ #  # ]:          0 :         if (id == MLX5_INVALID_SAMPLE_REG_ID) {
     231                 :          0 :                 *pos += map->width;
     232                 :          0 :                 return -1;
     233                 :            :         }
     234                 :            :         MLX5_ASSERT(map->width);
     235                 :            :         MLX5_ASSERT(id < tp->devx_fp->num_samples);
     236   [ #  #  #  # ]:          0 :         if (tp->tunnel_mode == FLEX_TUNNEL_MODE_MULTI && is_inner) {
     237                 :          0 :                 uint32_t num_samples = tp->devx_fp->num_samples / 2;
     238                 :            : 
     239                 :            :                 MLX5_ASSERT(tp->devx_fp->num_samples % 2 == 0);
     240                 :            :                 MLX5_ASSERT(id < num_samples);
     241                 :          0 :                 id += num_samples;
     242                 :            :         }
     243                 :          0 :         return id;
     244                 :            : }
     245                 :            : 
     246                 :            : /**
     247                 :            :  * Get the flex parser mapping value per definer format_select_dw.
     248                 :            :  *
     249                 :            :  * @param[in] item
     250                 :            :  *   Rte flex item pointer.
     251                 :            :  * @param[in] flex
     252                 :            :  *   Mlx5 flex item sample mapping handle.
     253                 :            :  * @param[in] byte_off
     254                 :            :  *   Mlx5 flex item format_select_dw.
     255                 :            :  * @param[in] tunnel
     256                 :            :  *   Tunnel mode or not.
     257                 :            :  * @param[in, def] value
     258                 :            :  *   Value calculated for this flex parser, either spec or mask.
     259                 :            :  *
     260                 :            :  * @return
     261                 :            :  *   0 on success, -1 for error.
     262                 :            :  */
     263                 :            : int
     264                 :          0 : mlx5_flex_get_parser_value_per_byte_off(const struct rte_flow_item_flex *item,
     265                 :            :                                         void *flex, uint32_t byte_off,
     266                 :            :                                         bool tunnel, uint32_t *value)
     267                 :            : {
     268                 :            :         struct mlx5_flex_pattern_field *map;
     269                 :            :         struct mlx5_flex_item *tp = flex;
     270                 :            :         uint32_t i, pos, val;
     271                 :            :         int id;
     272                 :            : 
     273                 :          0 :         *value = 0;
     274   [ #  #  #  # ]:          0 :         for (i = 0, pos = 0; i < tp->mapnum && pos < item->length * CHAR_BIT; i++) {
     275                 :          0 :                 map = tp->map + i;
     276                 :          0 :                 id = mlx5_flex_get_sample_id(tp, i, &pos, tunnel);
     277         [ #  # ]:          0 :                 if (id == -1)
     278                 :          0 :                         continue;
     279   [ #  #  #  # ]:          0 :                 if (id >= (int)tp->devx_fp->num_samples || id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
     280                 :            :                         return -1;
     281         [ #  # ]:          0 :                 if (byte_off == tp->devx_fp->sample_info[id].sample_dw_data * sizeof(uint32_t)) {
     282                 :          0 :                         val = mlx5_flex_get_bitfield(item, pos, map->width, map->shift);
     283                 :          0 :                         *value |= val;
     284                 :            :                 }
     285                 :          0 :                 pos += map->width;
     286                 :            :         }
     287                 :            :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :            : /**
     291                 :            :  * Get the flex parser tunnel mode.
     292                 :            :  *
     293                 :            :  * @param[in] item
     294                 :            :  *   RTE Flex item.
     295                 :            :  * @param[in, out] tunnel_mode
     296                 :            :  *   Pointer to return tunnel mode.
     297                 :            :  *
     298                 :            :  * @return
     299                 :            :  *   0 on success, otherwise negative error code.
     300                 :            :  */
     301                 :            : int
     302                 :          0 : mlx5_flex_get_tunnel_mode(const struct rte_flow_item *item,
     303                 :            :                           enum rte_flow_item_flex_tunnel_mode *tunnel_mode)
     304                 :            : {
     305   [ #  #  #  #  :          0 :         if (item && item->spec && tunnel_mode) {
                   #  # ]
     306                 :            :                 const struct rte_flow_item_flex *spec = item->spec;
     307                 :          0 :                 struct mlx5_flex_item *flex = (struct mlx5_flex_item *)spec->handle;
     308                 :            : 
     309         [ #  # ]:          0 :                 if (flex) {
     310                 :          0 :                         *tunnel_mode = flex->tunnel_mode;
     311                 :          0 :                         return 0;
     312                 :            :                 }
     313                 :            :         }
     314                 :            :         return -EINVAL;
     315                 :            : }
     316                 :            : 
     317                 :            : /**
     318                 :            :  * Translate item pattern into matcher fields according to translation
     319                 :            :  * array.
     320                 :            :  *
     321                 :            :  * @param dev
     322                 :            :  *   Ethernet device to translate flex item on.
     323                 :            :  * @param[in, out] matcher
     324                 :            :  *   Flow matcher to configure
     325                 :            :  * @param[in, out] key
     326                 :            :  *   Flow matcher value.
     327                 :            :  * @param[in] item
     328                 :            :  *   Flow pattern to translate.
     329                 :            :  * @param[in] is_inner
     330                 :            :  *   Inner Flex Item (follows after tunnel header).
     331                 :            :  *
     332                 :            :  * @return
     333                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
     334                 :            :  */
     335                 :            : void
     336                 :          0 : mlx5_flex_flow_translate_item(struct rte_eth_dev *dev,
     337                 :            :                               void *matcher, void *key,
     338                 :            :                               const struct rte_flow_item *item,
     339                 :            :                               bool is_inner)
     340                 :            : {
     341                 :            :         const struct rte_flow_item_flex *spec, *mask;
     342                 :            :         void *misc4_m = MLX5_ADDR_OF(fte_match_param, matcher,
     343                 :            :                                      misc_parameters_4);
     344                 :            :         void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4);
     345                 :            :         struct mlx5_flex_item *tp;
     346                 :          0 :         uint32_t i, pos = 0;
     347                 :            :         uint32_t sample_id;
     348                 :            : 
     349                 :            :         RTE_SET_USED(dev);
     350                 :            :         MLX5_ASSERT(item->spec && item->mask);
     351                 :          0 :         spec = item->spec;
     352                 :          0 :         mask = item->mask;
     353                 :          0 :         tp = (struct mlx5_flex_item *)spec->handle;
     354                 :            :         /* Validate mapnum to prevent using tainted loop bound */
     355         [ #  # ]:          0 :         if (tp->mapnum > MLX5_FLEX_ITEM_MAPPING_NUM)
     356                 :          0 :                 return;
     357   [ #  #  #  # ]:          0 :         for (i = 0; i < tp->mapnum && pos < (spec->length * CHAR_BIT); i++) {
     358                 :          0 :                 struct mlx5_flex_pattern_field *map = tp->map + i;
     359                 :            :                 uint32_t val, msk, def;
     360                 :          0 :                 int id = mlx5_flex_get_sample_id(tp, i, &pos, is_inner);
     361                 :            : 
     362                 :            :                 /* Validate id to prevent using tainted value as array index */
     363         [ #  # ]:          0 :                 if (id < 0)
     364                 :          0 :                         continue;
     365                 :            :                 MLX5_ASSERT(id < (int)tp->devx_fp->num_samples);
     366   [ #  #  #  # ]:          0 :                 if (id >= (int)tp->devx_fp->num_samples ||
     367                 :            :                     id >= MLX5_GRAPH_NODE_SAMPLE_NUM)
     368                 :            :                         return;
     369                 :            :                 /* Validate width and shift to prevent using tainted values as loop bounds */
     370   [ #  #  #  # ]:          0 :                 if (map->width == 0 || map->width > sizeof(uint32_t) * CHAR_BIT ||
     371         [ #  # ]:          0 :                     (uint32_t)(map->shift + map->width) > sizeof(uint32_t) * CHAR_BIT)
     372                 :            :                         return;
     373                 :          0 :                 def = (uint32_t)(RTE_BIT64(map->width) - 1);
     374                 :          0 :                 def <<= (sizeof(uint32_t) * CHAR_BIT - map->shift - map->width);
     375                 :          0 :                 val = mlx5_flex_get_bitfield(spec, pos, map->width, map->shift);
     376                 :          0 :                 msk = pos < (mask->length * CHAR_BIT) ?
     377         [ #  # ]:          0 :                       mlx5_flex_get_bitfield(mask, pos, map->width, map->shift) : def;
     378                 :          0 :                 sample_id = tp->devx_fp->sample_ids[id];
     379   [ #  #  #  #  :          0 :                 mlx5_flex_set_match_sample(misc4_m, misc4_v,
             #  #  #  # ]
     380                 :            :                                            def, msk, val & msk,
     381                 :            :                                            sample_id, id);
     382                 :          0 :                 pos += map->width;
     383                 :            :         }
     384                 :            : }
     385                 :            : 
     386                 :            : /**
     387                 :            :  * Convert flex item handle (from the RTE flow) to flex item index on port.
     388                 :            :  * Optionally can increment flex item object reference count.
     389                 :            :  *
     390                 :            :  * @param dev
     391                 :            :  *   Ethernet device to acquire flex item on.
     392                 :            :  * @param[in] handle
     393                 :            :  *   Flow item handle from item spec.
     394                 :            :  * @param[in] acquire
     395                 :            :  *   If set - increment reference counter.
     396                 :            :  *
     397                 :            :  * @return
     398                 :            :  *   >=0 - index on success, a negative errno value otherwise
     399                 :            :  *         and rte_errno is set.
     400                 :            :  */
     401                 :            : int
     402                 :          0 : mlx5_flex_acquire_index(struct rte_eth_dev *dev,
     403                 :            :                         struct rte_flow_item_flex_handle *handle,
     404                 :            :                         bool acquire)
     405                 :            : {
     406         [ #  # ]:          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     407                 :            :         struct mlx5_flex_item *flex = (struct mlx5_flex_item *)handle;
     408                 :            :         int ret = mlx5_flex_index(priv, flex);
     409                 :            : 
     410         [ #  # ]:          0 :         if (ret < 0) {
     411                 :          0 :                 errno = -EINVAL;
     412                 :          0 :                 rte_errno = EINVAL;
     413                 :          0 :                 return ret;
     414                 :            :         }
     415         [ #  # ]:          0 :         if (acquire)
     416                 :          0 :                 rte_atomic_fetch_add_explicit(&flex->refcnt, 1, rte_memory_order_release);
     417                 :            :         return ret;
     418                 :            : }
     419                 :            : 
     420                 :            : /**
     421                 :            :  * Release flex item index on port - decrements reference counter by index.
     422                 :            :  *
     423                 :            :  * @param dev
     424                 :            :  *   Ethernet device to acquire flex item on.
     425                 :            :  * @param[in] index
     426                 :            :  *   Flow item index.
     427                 :            :  *
     428                 :            :  * @return
     429                 :            :  *   0 - on success, a negative errno value otherwise and rte_errno is set.
     430                 :            :  */
     431                 :            : int
     432                 :          0 : mlx5_flex_release_index(struct rte_eth_dev *dev,
     433                 :            :                         int index)
     434                 :            : {
     435                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
     436                 :            :         struct mlx5_flex_item *flex;
     437                 :            : 
     438         [ #  # ]:          0 :         if (index >= MLX5_PORT_FLEX_ITEM_NUM ||
     439         [ #  # ]:          0 :             !(priv->flex_item_map & (1u << index))) {
     440                 :          0 :                 errno = EINVAL;
     441                 :          0 :                 rte_errno = -EINVAL;
     442                 :          0 :                 return -EINVAL;
     443                 :            :         }
     444                 :          0 :         flex = priv->flex_item + index;
     445         [ #  # ]:          0 :         if (flex->refcnt <= 1) {
     446                 :            :                 MLX5_ASSERT(false);
     447                 :          0 :                 errno = EINVAL;
     448                 :          0 :                 rte_errno = -EINVAL;
     449                 :          0 :                 return -EINVAL;
     450                 :            :         }
     451                 :          0 :         rte_atomic_fetch_sub_explicit(&flex->refcnt, 1, rte_memory_order_release);
     452                 :          0 :         return 0;
     453                 :            : }
     454                 :            : 
     455                 :            : /*
     456                 :            :  * Calculate largest mask value for a given shift.
     457                 :            :  *
     458                 :            :  *   shift      mask
     459                 :            :  * ------- ---------------
     460                 :            :  *    0     b11111100  0x3C
     461                 :            :  *    1     b01111110  0x3E
     462                 :            :  *    2     b00111111  0x3F
     463                 :            :  *    3     b00011111  0x1F
     464                 :            :  *    4     b00001111  0x0F
     465                 :            :  *    5     b00000111  0x07
     466                 :            :  *    6     b00000011  0x03
     467                 :            :  *    7     b00000001  0x01
     468                 :            :  */
     469                 :            : uint8_t
     470                 :          0 : mlx5_flex_hdr_len_mask(uint8_t shift,
     471                 :            :                        const struct mlx5_hca_flex_attr *attr)
     472                 :            : {
     473                 :            :         uint32_t base_mask;
     474         [ #  # ]:          0 :         int diff = shift - MLX5_PARSE_GRAPH_NODE_HDR_LEN_SHIFT_DWORD;
     475                 :            : 
     476                 :            :         base_mask = mlx5_hca_parse_graph_node_base_hdr_len_mask(attr);
     477         [ #  # ]:          0 :         return diff < 0 ? base_mask << -diff : base_mask >> diff;
     478                 :            : }
     479                 :            : 
     480                 :            : static int
     481                 :          0 : mlx5_flex_translate_length(struct mlx5_hca_flex_attr *attr,
     482                 :            :                            const struct rte_flow_item_flex_conf *conf,
     483                 :            :                            struct mlx5_flex_parser_devx *devx,
     484                 :            :                            struct rte_flow_error *error)
     485                 :            : {
     486                 :            :         const struct rte_flow_item_flex_field *field = &conf->next_header;
     487                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
     488                 :            : 
     489         [ #  # ]:          0 :         if (field->field_base % CHAR_BIT)
     490                 :          0 :                 return rte_flow_error_set
     491                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     492                 :            :                          "not byte aligned header length field");
     493                 :          0 :         node->header_length_field_offset_mode = !attr->header_length_field_mode_wa;
     494   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     495                 :          0 :         case FIELD_MODE_DUMMY:
     496                 :          0 :                 return rte_flow_error_set
     497                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     498                 :            :                          "invalid header length field mode (DUMMY)");
     499                 :          0 :         case FIELD_MODE_FIXED:
     500         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     501                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIXED)))
     502                 :          0 :                         return rte_flow_error_set
     503                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     504                 :            :                                  "unsupported header length field mode (FIXED)");
     505         [ #  # ]:          0 :                 if (field->field_size ||
     506   [ #  #  #  # ]:          0 :                     field->offset_mask || field->offset_shift)
     507                 :          0 :                         return rte_flow_error_set
     508                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     509                 :            :                                  "invalid fields for fixed mode");
     510         [ #  # ]:          0 :                 if (field->field_base < 0)
     511                 :          0 :                         return rte_flow_error_set
     512                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     513                 :            :                                  "negative header length field base (FIXED)");
     514                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIXED;
     515                 :          0 :                 break;
     516                 :          0 :         case FIELD_MODE_OFFSET: {
     517                 :            :                 uint32_t msb, lsb;
     518                 :          0 :                 int32_t shift = field->offset_shift;
     519                 :          0 :                 uint32_t offset = field->offset_base;
     520                 :          0 :                 uint32_t mask = field->offset_mask;
     521                 :          0 :                 uint32_t wmax = attr->header_length_mask_width +
     522                 :            :                                 MLX5_PARSE_GRAPH_NODE_HDR_LEN_SHIFT_DWORD;
     523                 :            : 
     524         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     525                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_FIELD)))
     526                 :          0 :                         return rte_flow_error_set
     527                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     528                 :            :                                  "unsupported header length field mode (OFFSET)");
     529         [ #  # ]:          0 :                 if (!field->field_size)
     530                 :          0 :                         return rte_flow_error_set
     531                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     532                 :            :                                  "field size is a must for offset mode");
     533         [ #  # ]:          0 :                 if ((offset ^ (field->field_size + offset)) >> 5)
     534                 :          0 :                         return rte_flow_error_set
     535                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     536                 :            :                                  "field crosses the 32-bit word boundary");
     537                 :            :                 /* Hardware counts in dwords, all shifts done by offset within mask */
     538         [ #  # ]:          0 :                 if (shift < 0 || (uint32_t)shift >= wmax)
     539                 :          0 :                         return rte_flow_error_set
     540                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     541                 :            :                                  "header length field shift exceeds limits (OFFSET)");
     542         [ #  # ]:          0 :                 if (!mask)
     543                 :          0 :                         return rte_flow_error_set
     544                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     545                 :            :                                  "zero length field offset mask (OFFSET)");
     546         [ #  # ]:          0 :                 msb = rte_fls_u32(mask) - 1;
     547                 :            :                 lsb = rte_bsf32(mask);
     548         [ #  # ]:          0 :                 if (!rte_is_power_of_2((mask >> lsb) + 1))
     549                 :          0 :                         return rte_flow_error_set
     550                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     551                 :            :                                  "length field offset mask not contiguous (OFFSET)");
     552         [ #  # ]:          0 :                 if (msb >= field->field_size)
     553                 :          0 :                         return rte_flow_error_set
     554                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     555                 :            :                                  "length field offset mask exceeds field size (OFFSET)");
     556         [ #  # ]:          0 :                 if (msb >= wmax)
     557                 :          0 :                         return rte_flow_error_set
     558                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     559                 :            :                                  "length field offset mask exceeds supported width (OFFSET)");
     560         [ #  # ]:          0 :                 if (mask & ~mlx5_flex_hdr_len_mask(shift, attr))
     561                 :          0 :                         return rte_flow_error_set
     562                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     563                 :            :                                  "mask and shift combination not supported (OFFSET)");
     564                 :            :                 msb++;
     565                 :          0 :                 offset += field->field_size - msb;
     566   [ #  #  #  # ]:          0 :                 if (attr->header_length_field_mode_wa && msb < attr->header_length_mask_width) {
     567         [ #  # ]:          0 :                         if (attr->header_length_mask_width - msb > offset)
     568                 :          0 :                                 return rte_flow_error_set
     569                 :            :                                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     570                 :            :                                          "field size plus offset_base is too small");
     571                 :          0 :                         offset += msb;
     572                 :            :                         /*
     573                 :            :                          * Here we can move to preceding dword. Hardware does
     574                 :            :                          * cyclic left shift so we should avoid this and stay
     575                 :            :                          * at current dword offset.
     576                 :            :                          */
     577                 :          0 :                         offset = (offset & ~0x1Fu) |
     578                 :          0 :                                  ((offset - attr->header_length_mask_width) & 0x1F);
     579                 :            :                 }
     580                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_FIELD;
     581                 :          0 :                 node->header_length_field_mask = mask;
     582                 :          0 :                 node->header_length_field_shift = shift;
     583                 :          0 :                 node->header_length_field_offset = offset;
     584                 :          0 :                 break;
     585                 :            :         }
     586                 :          0 :         case FIELD_MODE_BITMASK:
     587         [ #  # ]:          0 :                 if (!(attr->header_length_mode &
     588                 :            :                     RTE_BIT32(MLX5_GRAPH_NODE_LEN_BITMASK)))
     589                 :          0 :                         return rte_flow_error_set
     590                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     591                 :            :                                  "unsupported header length field mode (BITMASK)");
     592         [ #  # ]:          0 :                 if (field->offset_shift > 15 || field->offset_shift < 0)
     593                 :          0 :                         return rte_flow_error_set
     594                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     595                 :            :                                  "header length field shift exceeds limit (BITMASK)");
     596                 :          0 :                 node->header_length_mode = MLX5_GRAPH_NODE_LEN_BITMASK;
     597                 :          0 :                 node->header_length_field_mask = field->offset_mask;
     598                 :          0 :                 node->header_length_field_shift = field->offset_shift;
     599                 :          0 :                 node->header_length_field_offset = field->offset_base;
     600                 :          0 :                 break;
     601                 :          0 :         default:
     602                 :          0 :                 return rte_flow_error_set
     603                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     604                 :            :                          "unknown header length field mode");
     605                 :            :         }
     606         [ #  # ]:          0 :         if (field->field_base / CHAR_BIT >= 0 &&
     607         [ #  # ]:          0 :             field->field_base / CHAR_BIT > attr->max_base_header_length)
     608                 :          0 :                 return rte_flow_error_set
     609                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     610                 :            :                          "header length field base exceeds limit");
     611                 :          0 :         node->header_length_base_value = field->field_base / CHAR_BIT;
     612                 :          0 :         return 0;
     613                 :            : }
     614                 :            : 
     615                 :            : static int
     616                 :          0 : mlx5_flex_translate_next(struct mlx5_hca_flex_attr *attr,
     617                 :            :                          const struct rte_flow_item_flex_conf *conf,
     618                 :            :                          struct mlx5_flex_parser_devx *devx,
     619                 :            :                          struct rte_flow_error *error)
     620                 :            : {
     621                 :            :         const struct rte_flow_item_flex_field *field = &conf->next_protocol;
     622                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
     623                 :            : 
     624   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     625                 :          0 :         case FIELD_MODE_DUMMY:
     626         [ #  # ]:          0 :                 if (conf->nb_outputs)
     627                 :          0 :                         return rte_flow_error_set
     628                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     629                 :            :                                  "next protocol field is required (DUMMY)");
     630                 :            :                 return 0;
     631                 :            :         case FIELD_MODE_FIXED:
     632                 :            :                 break;
     633                 :          0 :         case FIELD_MODE_OFFSET:
     634                 :          0 :                 return rte_flow_error_set
     635                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     636                 :            :                          "unsupported next protocol field mode (OFFSET)");
     637                 :            :                 break;
     638                 :          0 :         case FIELD_MODE_BITMASK:
     639                 :          0 :                 return rte_flow_error_set
     640                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     641                 :            :                          "unsupported next protocol field mode (BITMASK)");
     642                 :          0 :         default:
     643                 :          0 :                 return rte_flow_error_set
     644                 :            :                         (error, EINVAL,
     645                 :            :                          RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     646                 :            :                          "unknown next protocol field mode");
     647                 :            :         }
     648                 :            :         MLX5_ASSERT(field->field_mode == FIELD_MODE_FIXED);
     649         [ #  # ]:          0 :         if (!conf->nb_outputs)
     650                 :          0 :                 return rte_flow_error_set
     651                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     652                 :            :                          "out link(s) is required if next field present");
     653         [ #  # ]:          0 :         if (attr->max_next_header_offset < field->field_base)
     654                 :          0 :                 return rte_flow_error_set
     655                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     656                 :            :                          "next protocol field base exceeds limit");
     657         [ #  # ]:          0 :         if (field->offset_shift)
     658                 :          0 :                 return rte_flow_error_set
     659                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     660                 :            :                          "unsupported next protocol field shift");
     661                 :          0 :         node->next_header_field_offset = field->field_base;
     662                 :          0 :         node->next_header_field_size = field->field_size;
     663                 :          0 :         return 0;
     664                 :            : }
     665                 :            : 
     666                 :            : /* Helper structure to handle field bit intervals. */
     667                 :            : struct mlx5_flex_field_cover {
     668                 :            :         uint16_t num;
     669                 :            :         int32_t start[MLX5_FLEX_ITEM_MAPPING_NUM];
     670                 :            :         int32_t end[MLX5_FLEX_ITEM_MAPPING_NUM];
     671                 :            :         uint8_t mapped[MLX5_FLEX_ITEM_MAPPING_NUM / CHAR_BIT + 1];
     672                 :            : };
     673                 :            : 
     674                 :            : static void
     675                 :          0 : mlx5_flex_insert_field(struct mlx5_flex_field_cover *cover,
     676                 :            :                        uint16_t num, int32_t start, int32_t end)
     677                 :            : {
     678                 :            :         MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
     679                 :            :         MLX5_ASSERT(num <= cover->num);
     680         [ #  # ]:          0 :         if (num < cover->num) {
     681                 :          0 :                 memmove(&cover->start[num + 1],  &cover->start[num],
     682                 :          0 :                         (cover->num - num) * sizeof(int32_t));
     683                 :          0 :                 memmove(&cover->end[num + 1],    &cover->end[num],
     684                 :          0 :                         (cover->num - num) * sizeof(int32_t));
     685                 :            :         }
     686                 :          0 :         cover->start[num] = start;
     687                 :          0 :         cover->end[num] = end;
     688                 :          0 :         cover->num++;
     689                 :          0 : }
     690                 :            : 
     691                 :            : static void
     692                 :          0 : mlx5_flex_merge_field(struct mlx5_flex_field_cover *cover, uint16_t num)
     693                 :            : {
     694                 :            :         uint32_t i, del = 0;
     695                 :            :         int32_t end;
     696                 :            : 
     697                 :            :         MLX5_ASSERT(num < MLX5_FLEX_ITEM_MAPPING_NUM);
     698                 :            :         MLX5_ASSERT(num < (cover->num - 1));
     699                 :          0 :         end = cover->end[num];
     700         [ #  # ]:          0 :         for (i = num + 1; i < cover->num; i++) {
     701         [ #  # ]:          0 :                 if (end < cover->start[i])
     702                 :            :                         break;
     703                 :          0 :                 del++;
     704         [ #  # ]:          0 :                 if (end <= cover->end[i]) {
     705                 :          0 :                         cover->end[num] = cover->end[i];
     706                 :          0 :                         break;
     707                 :            :                 }
     708                 :            :         }
     709         [ #  # ]:          0 :         if (del) {
     710                 :            :                 MLX5_ASSERT(del < (cover->num - 1u - num));
     711                 :          0 :                 cover->num -= del;
     712                 :            :                 MLX5_ASSERT(cover->num > num);
     713         [ #  # ]:          0 :                 if ((cover->num - num) > 1) {
     714                 :          0 :                         memmove(&cover->start[num + 1],
     715                 :          0 :                                 &cover->start[num + 1 + del],
     716                 :          0 :                                 (cover->num - num - 1) * sizeof(int32_t));
     717                 :          0 :                         memmove(&cover->end[num + 1],
     718                 :          0 :                                 &cover->end[num + 1 + del],
     719                 :          0 :                                 (cover->num - num - 1) * sizeof(int32_t));
     720                 :            :                 }
     721                 :            :         }
     722                 :          0 : }
     723                 :            : 
     724                 :            : /*
     725                 :            :  * Validate the sample field and update interval array
     726                 :            :  * if parameters match with the 'match" field.
     727                 :            :  * Returns:
     728                 :            :  *    < 0  - error
     729                 :            :  *    == 0 - no match, interval array not updated
     730                 :            :  *    > 0  - match, interval array updated
     731                 :            :  */
     732                 :            : static int
     733                 :          0 : mlx5_flex_cover_sample(struct mlx5_flex_field_cover *cover,
     734                 :            :                        struct rte_flow_item_flex_field *field,
     735                 :            :                        struct rte_flow_item_flex_field *match,
     736                 :            :                        struct mlx5_hca_flex_attr *attr,
     737                 :            :                        struct rte_flow_error *error)
     738                 :            : {
     739                 :            :         int32_t start, end;
     740                 :            :         uint32_t i;
     741                 :            : 
     742   [ #  #  #  #  :          0 :         switch (field->field_mode) {
                      # ]
     743                 :            :         case FIELD_MODE_DUMMY:
     744                 :            :                 return 0;
     745                 :          0 :         case FIELD_MODE_FIXED:
     746         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     747                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIXED)))
     748                 :          0 :                         return rte_flow_error_set
     749                 :            :                                 (error, EINVAL,
     750                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     751                 :            :                                  "unsupported sample field mode (FIXED)");
     752         [ #  # ]:          0 :                 if (field->offset_shift)
     753                 :          0 :                         return rte_flow_error_set
     754                 :            :                                 (error, EINVAL,
     755                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     756                 :            :                                  "invalid sample field shift (FIXED");
     757         [ #  # ]:          0 :                 if (field->field_base < 0)
     758                 :          0 :                         return rte_flow_error_set
     759                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     760                 :            :                                  "invalid sample field base (FIXED)");
     761         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     762                 :          0 :                         return rte_flow_error_set
     763                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     764                 :            :                                  "sample field base exceeds limit (FIXED)");
     765                 :            :                 break;
     766                 :          0 :         case FIELD_MODE_OFFSET:
     767         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     768                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_FIELD)))
     769                 :          0 :                         return rte_flow_error_set
     770                 :            :                                 (error, EINVAL,
     771                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     772                 :            :                                  "unsupported sample field mode (OFFSET)");
     773         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT >= 0 &&
     774         [ #  # ]:          0 :                     field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     775                 :          0 :                         return rte_flow_error_set
     776                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     777                 :            :                                 "sample field base exceeds limit");
     778                 :            :                 break;
     779                 :          0 :         case FIELD_MODE_BITMASK:
     780         [ #  # ]:          0 :                 if (!(attr->sample_offset_mode &
     781                 :            :                     RTE_BIT32(MLX5_GRAPH_SAMPLE_OFFSET_BITMASK)))
     782                 :          0 :                         return rte_flow_error_set
     783                 :            :                                 (error, EINVAL,
     784                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     785                 :            :                                  "unsupported sample field mode (BITMASK)");
     786         [ #  # ]:          0 :                 if (field->field_base / CHAR_BIT >= 0 &&
     787         [ #  # ]:          0 :                     field->field_base / CHAR_BIT > attr->max_sample_base_offset)
     788                 :          0 :                         return rte_flow_error_set
     789                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     790                 :            :                                 "sample field base exceeds limit");
     791                 :            :                 break;
     792                 :          0 :         default:
     793                 :          0 :                 return rte_flow_error_set
     794                 :            :                         (error, EINVAL,
     795                 :            :                          RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     796                 :            :                          "unknown data sample field mode");
     797                 :            :         }
     798         [ #  # ]:          0 :         if (!match) {
     799         [ #  # ]:          0 :                 if (!field->field_size)
     800                 :          0 :                         return rte_flow_error_set
     801                 :            :                                 (error, EINVAL,
     802                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     803                 :            :                                 "zero sample field width");
     804         [ #  # ]:          0 :                 if (field->field_id)
     805                 :          0 :                         DRV_LOG(DEBUG, "sample field id hint ignored");
     806                 :            :         } else {
     807         [ #  # ]:          0 :                 if (field->field_mode != match->field_mode ||
     808         [ #  # ]:          0 :                     field->offset_base | match->offset_base ||
     809         [ #  # ]:          0 :                     field->offset_mask | match->offset_mask ||
     810         [ #  # ]:          0 :                     field->offset_shift | match->offset_shift)
     811                 :            :                         return 0;
     812                 :            :         }
     813                 :          0 :         start = field->field_base;
     814                 :          0 :         end = start + field->field_size;
     815                 :            :         /* Add the new or similar field to interval array. */
     816         [ #  # ]:          0 :         if (!cover->num) {
     817                 :          0 :                 cover->start[cover->num] = start;
     818                 :          0 :                 cover->end[cover->num] = end;
     819                 :          0 :                 cover->num = 1;
     820                 :          0 :                 return 1;
     821                 :            :         }
     822         [ #  # ]:          0 :         for (i = 0; i < cover->num; i++) {
     823         [ #  # ]:          0 :                 if (start > cover->end[i]) {
     824         [ #  # ]:          0 :                         if (i >= (cover->num - 1u)) {
     825                 :          0 :                                 mlx5_flex_insert_field(cover, cover->num,
     826                 :            :                                                        start, end);
     827                 :          0 :                                 break;
     828                 :            :                         }
     829                 :            :                         continue;
     830                 :            :                 }
     831         [ #  # ]:          0 :                 if (end < cover->start[i]) {
     832                 :          0 :                         mlx5_flex_insert_field(cover, i, start, end);
     833                 :          0 :                         break;
     834                 :            :                 }
     835         [ #  # ]:          0 :                 if (start < cover->start[i])
     836                 :          0 :                         cover->start[i] = start;
     837         [ #  # ]:          0 :                 if (end > cover->end[i]) {
     838                 :          0 :                         cover->end[i] = end;
     839         [ #  # ]:          0 :                         if (i < (cover->num - 1u))
     840                 :          0 :                                 mlx5_flex_merge_field(cover, i);
     841                 :            :                 }
     842                 :            :                 break;
     843                 :            :         }
     844                 :            :         return 1;
     845                 :            : }
     846                 :            : 
     847                 :            : static void
     848      [ #  #  # ]:          0 : mlx5_flex_config_sample(struct mlx5_devx_match_sample_attr *na,
     849                 :            :                         struct rte_flow_item_flex_field *field,
     850                 :            :                         enum rte_flow_item_flex_tunnel_mode tunnel_mode)
     851                 :            : {
     852                 :            :         memset(na, 0, sizeof(struct mlx5_devx_match_sample_attr));
     853                 :          0 :         na->flow_match_sample_en = 1;
     854      [ #  #  # ]:          0 :         switch (field->field_mode) {
     855                 :            :         case FIELD_MODE_FIXED:
     856                 :            :                 na->flow_match_sample_offset_mode =
     857                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_FIXED;
     858                 :            :                 break;
     859                 :          0 :         case FIELD_MODE_OFFSET:
     860                 :          0 :                 na->flow_match_sample_offset_mode =
     861                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_FIELD;
     862                 :          0 :                 na->flow_match_sample_field_offset = field->offset_base;
     863                 :          0 :                 na->flow_match_sample_field_offset_mask = field->offset_mask;
     864                 :          0 :                 na->flow_match_sample_field_offset_shift = field->offset_shift;
     865                 :          0 :                 break;
     866                 :          0 :         case FIELD_MODE_BITMASK:
     867                 :          0 :                 na->flow_match_sample_offset_mode =
     868                 :            :                         MLX5_GRAPH_SAMPLE_OFFSET_BITMASK;
     869                 :          0 :                 na->flow_match_sample_field_offset = field->offset_base;
     870                 :          0 :                 na->flow_match_sample_field_offset_mask = field->offset_mask;
     871                 :          0 :                 na->flow_match_sample_field_offset_shift = field->offset_shift;
     872                 :          0 :                 break;
     873                 :            :         default:
     874                 :            :                 MLX5_ASSERT(false);
     875                 :            :                 break;
     876                 :            :         }
     877      [ #  #  # ]:          0 :         switch (tunnel_mode) {
     878                 :          0 :         case FLEX_TUNNEL_MODE_SINGLE:
     879                 :            :                 /* Fallthrough */
     880                 :            :         case FLEX_TUNNEL_MODE_TUNNEL:
     881                 :          0 :                 na->flow_match_sample_tunnel_mode =
     882                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_FIRST;
     883                 :          0 :                 break;
     884                 :            :         case FLEX_TUNNEL_MODE_MULTI:
     885                 :            :                 /* Fallthrough */
     886                 :            :         case FLEX_TUNNEL_MODE_OUTER:
     887                 :            :                 na->flow_match_sample_tunnel_mode =
     888                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_OUTER;
     889                 :            :                 break;
     890                 :          0 :         case FLEX_TUNNEL_MODE_INNER:
     891                 :          0 :                 na->flow_match_sample_tunnel_mode =
     892                 :            :                         MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
     893                 :          0 :                 break;
     894                 :            :         default:
     895                 :            :                 MLX5_ASSERT(false);
     896                 :            :                 break;
     897                 :            :         }
     898                 :          0 : }
     899                 :            : 
     900                 :            : /* Map specified field to set/subset of allocated sample registers. */
     901                 :            : static int
     902                 :          0 : mlx5_flex_map_sample(struct rte_flow_item_flex_field *field,
     903                 :            :                      struct mlx5_flex_parser_devx *parser,
     904                 :            :                      struct mlx5_flex_item *item,
     905                 :            :                      struct rte_flow_error *error)
     906                 :            : {
     907                 :            :         struct mlx5_devx_match_sample_attr node;
     908                 :          0 :         int32_t start = field->field_base;
     909                 :          0 :         int32_t end = start + field->field_size;
     910                 :            :         struct mlx5_flex_pattern_field *trans;
     911                 :            :         uint32_t i, done_bits = 0;
     912                 :            : 
     913         [ #  # ]:          0 :         if (field->field_mode == FIELD_MODE_DUMMY) {
     914                 :            :                 done_bits = field->field_size;
     915         [ #  # ]:          0 :                 while (done_bits) {
     916                 :          0 :                         uint32_t part = RTE_MIN(done_bits,
     917                 :            :                                                 sizeof(uint32_t) * CHAR_BIT);
     918         [ #  # ]:          0 :                         if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
     919                 :          0 :                                 return rte_flow_error_set
     920                 :            :                                         (error,
     921                 :            :                                          EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     922                 :            :                                          "too many flex item pattern translations");
     923                 :            :                         trans = &item->map[item->mapnum];
     924                 :          0 :                         trans->reg_id = MLX5_INVALID_SAMPLE_REG_ID;
     925                 :          0 :                         trans->shift = 0;
     926                 :          0 :                         trans->width = part;
     927                 :          0 :                         item->mapnum++;
     928                 :          0 :                         done_bits -= part;
     929                 :            :                 }
     930                 :            :                 return 0;
     931                 :            :         }
     932                 :          0 :         mlx5_flex_config_sample(&node, field, item->tunnel_mode);
     933         [ #  # ]:          0 :         for (i = 0; i < parser->num_samples; i++) {
     934                 :          0 :                 struct mlx5_devx_match_sample_attr *sample =
     935                 :            :                         &parser->devx_conf.sample[i];
     936                 :            :                 int32_t reg_start, reg_end;
     937                 :            :                 int32_t cov_start, cov_end;
     938                 :            : 
     939                 :            :                 MLX5_ASSERT(sample->flow_match_sample_en);
     940         [ #  # ]:          0 :                 if (!sample->flow_match_sample_en)
     941                 :            :                         break;
     942                 :          0 :                 node.flow_match_sample_field_base_offset =
     943                 :          0 :                         sample->flow_match_sample_field_base_offset;
     944         [ #  # ]:          0 :                 if (memcmp(&node, sample, sizeof(node)))
     945                 :          0 :                         continue;
     946                 :          0 :                 reg_start = (int8_t)sample->flow_match_sample_field_base_offset;
     947                 :          0 :                 reg_start *= CHAR_BIT;
     948                 :          0 :                 reg_end = reg_start + 32;
     949         [ #  # ]:          0 :                 if (end <= reg_start || start >= reg_end)
     950                 :          0 :                         continue;
     951                 :          0 :                 cov_start = RTE_MAX(reg_start, start);
     952                 :          0 :                 cov_end = RTE_MIN(reg_end, end);
     953                 :            :                 MLX5_ASSERT(cov_end > cov_start);
     954                 :          0 :                 done_bits += cov_end - cov_start;
     955         [ #  # ]:          0 :                 if (item->mapnum >= MLX5_FLEX_ITEM_MAPPING_NUM)
     956                 :          0 :                         return rte_flow_error_set
     957                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     958                 :            :                                  "too many flex item pattern translations");
     959                 :            :                 trans = &item->map[item->mapnum];
     960                 :          0 :                 item->mapnum++;
     961                 :          0 :                 trans->reg_id = i;
     962                 :          0 :                 trans->shift = cov_start - reg_start;
     963                 :          0 :                 trans->width = cov_end - cov_start;
     964                 :            :         }
     965         [ #  # ]:          0 :         if (done_bits != field->field_size) {
     966                 :            :                 MLX5_ASSERT(false);
     967                 :          0 :                 return rte_flow_error_set
     968                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     969                 :            :                          "failed to map field to sample register");
     970                 :            :         }
     971                 :            :         return 0;
     972                 :            : }
     973                 :            : 
     974                 :            : /* Allocate sample registers for the specified field type and interval array. */
     975                 :            : static int
     976                 :          0 : mlx5_flex_alloc_sample(struct mlx5_flex_field_cover *cover,
     977                 :            :                        struct mlx5_flex_parser_devx *parser,
     978                 :            :                        struct mlx5_flex_item *item,
     979                 :            :                        struct rte_flow_item_flex_field *field,
     980                 :            :                        struct mlx5_hca_flex_attr *attr,
     981                 :            :                        struct rte_flow_error *error)
     982                 :            : {
     983                 :            :         struct mlx5_devx_match_sample_attr node;
     984                 :            :         uint32_t idx = 0;
     985                 :            : 
     986                 :          0 :         mlx5_flex_config_sample(&node, field, item->tunnel_mode);
     987         [ #  # ]:          0 :         while (idx < cover->num) {
     988                 :            :                 int32_t start, end;
     989                 :            : 
     990                 :            :                 /*
     991                 :            :                  * Sample base offsets are in bytes, should be aligned
     992                 :            :                  * to 32-bit as required by firmware for samples.
     993                 :            :                  */
     994                 :          0 :                 start = RTE_ALIGN_FLOOR(cover->start[idx],
     995                 :            :                                         sizeof(uint32_t) * CHAR_BIT);
     996                 :          0 :                 node.flow_match_sample_field_base_offset =
     997                 :          0 :                                                 (start / CHAR_BIT) & 0xFF;
     998                 :            :                 /* Allocate sample register. */
     999         [ #  # ]:          0 :                 if (parser->num_samples >= MLX5_GRAPH_NODE_SAMPLE_NUM ||
    1000         [ #  # ]:          0 :                     parser->num_samples >= attr->max_num_sample ||
    1001         [ #  # ]:          0 :                     parser->num_samples >= attr->max_num_prog_sample)
    1002                 :          0 :                         return rte_flow_error_set
    1003                 :            :                                 (error, EINVAL,
    1004                 :            :                                  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1005                 :            :                                  "no sample registers to handle all flex item fields");
    1006                 :          0 :                 parser->devx_conf.sample[parser->num_samples] = node;
    1007                 :          0 :                 parser->num_samples++;
    1008                 :            :                 /* Remove or update covered intervals. */
    1009                 :          0 :                 end = start + 32;
    1010         [ #  # ]:          0 :                 while (idx < cover->num) {
    1011         [ #  # ]:          0 :                         if (end >= cover->end[idx]) {
    1012                 :          0 :                                 idx++;
    1013                 :          0 :                                 continue;
    1014                 :            :                         }
    1015         [ #  # ]:          0 :                         if (end > cover->start[idx])
    1016                 :          0 :                                 cover->start[idx] = end;
    1017                 :            :                         break;
    1018                 :            :                 }
    1019                 :            :         }
    1020                 :            :         return 0;
    1021                 :            : }
    1022                 :            : 
    1023                 :            : static int
    1024                 :          0 : mlx5_flex_translate_sample(struct mlx5_hca_flex_attr *attr,
    1025                 :            :                            const struct rte_flow_item_flex_conf *conf,
    1026                 :            :                            struct mlx5_flex_parser_devx *parser,
    1027                 :            :                            struct mlx5_flex_item *item,
    1028                 :            :                            struct rte_flow_error *error)
    1029                 :            : {
    1030                 :            :         struct mlx5_flex_field_cover cover;
    1031                 :            :         uint32_t i, j;
    1032                 :            :         int ret;
    1033                 :            : 
    1034         [ #  # ]:          0 :         switch (conf->tunnel) {
    1035                 :            :         case FLEX_TUNNEL_MODE_SINGLE:
    1036                 :            :                 /* Fallthrough */
    1037                 :            :         case FLEX_TUNNEL_MODE_OUTER:
    1038                 :            :                 /* Fallthrough */
    1039                 :            :         case FLEX_TUNNEL_MODE_INNER:
    1040                 :            :                 /* Fallthrough */
    1041                 :            :         case FLEX_TUNNEL_MODE_MULTI:
    1042                 :            :                 /* Fallthrough */
    1043                 :            :         case FLEX_TUNNEL_MODE_TUNNEL:
    1044                 :            :                 break;
    1045                 :          0 :         default:
    1046                 :          0 :                 return rte_flow_error_set
    1047                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1048                 :            :                          "unrecognized tunnel mode");
    1049                 :            :         }
    1050                 :          0 :         item->tunnel_mode = conf->tunnel;
    1051         [ #  # ]:          0 :         if (conf->nb_samples > MLX5_FLEX_ITEM_MAPPING_NUM)
    1052                 :          0 :                 return rte_flow_error_set
    1053                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1054                 :            :                          "sample field number exceeds limit");
    1055                 :            :         /*
    1056                 :            :          * The application can specify fields smaller or bigger than 32 bits
    1057                 :            :          * covered with single sample register and it can specify field
    1058                 :            :          * offsets in any order.
    1059                 :            :          *
    1060                 :            :          * Gather all similar fields together, build array of bit intervals
    1061                 :            :          * in ascending order and try to cover with the smallest set of sample
    1062                 :            :          * registers.
    1063                 :            :          */
    1064                 :            :         memset(&cover, 0, sizeof(cover));
    1065         [ #  # ]:          0 :         for (i = 0; i < conf->nb_samples; i++) {
    1066                 :          0 :                 struct rte_flow_item_flex_field *fl = conf->sample_data + i;
    1067                 :            : 
    1068                 :            :                 /* Check whether field was covered in the previous iteration. */
    1069         [ #  # ]:          0 :                 if (cover.mapped[i / CHAR_BIT] & (1u << (i % CHAR_BIT)))
    1070                 :          0 :                         continue;
    1071         [ #  # ]:          0 :                 if (fl->field_mode == FIELD_MODE_DUMMY)
    1072                 :          0 :                         continue;
    1073                 :            :                 /* Build an interval array for the field and similar ones */
    1074                 :          0 :                 cover.num = 0;
    1075                 :            :                 /* Add the first field to array unconditionally. */
    1076                 :          0 :                 ret = mlx5_flex_cover_sample(&cover, fl, NULL, attr, error);
    1077         [ #  # ]:          0 :                 if (ret < 0)
    1078                 :          0 :                         return ret;
    1079                 :            :                 MLX5_ASSERT(ret > 0);
    1080                 :          0 :                 cover.mapped[i / CHAR_BIT] |= 1u << (i % CHAR_BIT);
    1081         [ #  # ]:          0 :                 for (j = i + 1; j < conf->nb_samples; j++) {
    1082                 :            :                         struct rte_flow_item_flex_field *ft;
    1083                 :            : 
    1084                 :            :                         /* Add field to array if its type matches. */
    1085                 :          0 :                         ft = conf->sample_data + j;
    1086                 :          0 :                         ret = mlx5_flex_cover_sample(&cover, ft, fl,
    1087                 :            :                                                      attr, error);
    1088         [ #  # ]:          0 :                         if (ret < 0)
    1089                 :          0 :                                 return ret;
    1090         [ #  # ]:          0 :                         if (!ret)
    1091                 :          0 :                                 continue;
    1092                 :          0 :                         cover.mapped[j / CHAR_BIT] |= 1u << (j % CHAR_BIT);
    1093                 :            :                 }
    1094                 :            :                 /* Allocate sample registers to cover array of intervals. */
    1095                 :          0 :                 ret = mlx5_flex_alloc_sample(&cover, parser, item,
    1096                 :            :                                              fl, attr, error);
    1097         [ #  # ]:          0 :                 if (ret)
    1098                 :          0 :                         return ret;
    1099                 :            :         }
    1100                 :            :         /* Build the item pattern translating data on flow creation. */
    1101                 :          0 :         item->mapnum = 0;
    1102                 :          0 :         memset(&item->map, 0, sizeof(item->map));
    1103         [ #  # ]:          0 :         for (i = 0; i < conf->nb_samples; i++) {
    1104                 :          0 :                 struct rte_flow_item_flex_field *fl = conf->sample_data + i;
    1105                 :            : 
    1106                 :          0 :                 ret = mlx5_flex_map_sample(fl, parser, item, error);
    1107         [ #  # ]:          0 :                 if (ret) {
    1108                 :            :                         MLX5_ASSERT(false);
    1109                 :          0 :                         return ret;
    1110                 :            :                 }
    1111                 :            :         }
    1112         [ #  # ]:          0 :         if (conf->tunnel == FLEX_TUNNEL_MODE_MULTI) {
    1113                 :            :                 /*
    1114                 :            :                  * In FLEX_TUNNEL_MODE_MULTI tunnel mode PMD creates 2 sets
    1115                 :            :                  * of samples. The first set is for outer and the second set
    1116                 :            :                  * for inner flex flow item. Outer and inner samples differ
    1117                 :            :                  * only in tunnel_mode.
    1118                 :            :                  */
    1119         [ #  # ]:          0 :                 if (parser->num_samples > MLX5_GRAPH_NODE_SAMPLE_NUM / 2)
    1120                 :          0 :                         return rte_flow_error_set
    1121                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1122                 :            :                                  "no sample registers for inner");
    1123                 :          0 :                 rte_memcpy(parser->devx_conf.sample + parser->num_samples,
    1124                 :          0 :                            parser->devx_conf.sample,
    1125         [ #  # ]:          0 :                            parser->num_samples *
    1126                 :            :                                         sizeof(parser->devx_conf.sample[0]));
    1127         [ #  # ]:          0 :                 for (i = 0; i < parser->num_samples; i++) {
    1128                 :          0 :                         struct mlx5_devx_match_sample_attr *sm = i +
    1129                 :          0 :                                 parser->devx_conf.sample + parser->num_samples;
    1130                 :            : 
    1131                 :          0 :                         sm->flow_match_sample_tunnel_mode =
    1132                 :            :                                                 MLX5_GRAPH_SAMPLE_TUNNEL_INNER;
    1133                 :            :                 }
    1134                 :          0 :                 parser->num_samples *= 2;
    1135                 :            :         }
    1136                 :            :         return 0;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : static int
    1140                 :          0 : mlx5_flex_arc_type(enum rte_flow_item_type type, int in)
    1141                 :            : {
    1142   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
                   #  # ]
    1143                 :            :         case RTE_FLOW_ITEM_TYPE_ETH:
    1144                 :            :                 return  MLX5_GRAPH_ARC_NODE_MAC;
    1145                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV4:
    1146         [ #  # ]:          0 :                 return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV4;
    1147                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6:
    1148         [ #  # ]:          0 :                 return in ? MLX5_GRAPH_ARC_NODE_IP : MLX5_GRAPH_ARC_NODE_IPV6;
    1149                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
    1150                 :          0 :                 return MLX5_GRAPH_ARC_NODE_UDP;
    1151                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
    1152                 :          0 :                 return MLX5_GRAPH_ARC_NODE_TCP;
    1153                 :          0 :         case RTE_FLOW_ITEM_TYPE_MPLS:
    1154                 :          0 :                 return MLX5_GRAPH_ARC_NODE_MPLS;
    1155                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
    1156                 :          0 :                 return MLX5_GRAPH_ARC_NODE_GRE;
    1157                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
    1158                 :          0 :                 return MLX5_GRAPH_ARC_NODE_GENEVE;
    1159                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
    1160                 :          0 :                 return MLX5_GRAPH_ARC_NODE_VXLAN_GPE;
    1161                 :          0 :         case RTE_FLOW_ITEM_TYPE_ESP:
    1162                 :          0 :                 return MLX5_GRAPH_ARC_NODE_IPSEC_ESP;
    1163                 :          0 :         default:
    1164                 :          0 :                 return -EINVAL;
    1165                 :            :         }
    1166                 :            : }
    1167                 :            : 
    1168                 :            : static int
    1169                 :          0 : mlx5_flex_arc_in_eth(const struct rte_flow_item *item,
    1170                 :            :                      struct rte_flow_error *error)
    1171                 :            : {
    1172                 :          0 :         const struct rte_flow_item_eth *spec = item->spec;
    1173                 :          0 :         const struct rte_flow_item_eth *mask = item->mask;
    1174                 :          0 :         struct rte_flow_item_eth eth = { .hdr.ether_type = RTE_BE16(0xFFFF) };
    1175                 :            : 
    1176         [ #  # ]:          0 :         if (memcmp(mask, &eth, sizeof(struct rte_flow_item_eth))) {
    1177                 :          0 :                 return rte_flow_error_set
    1178                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1179                 :            :                          "invalid eth item mask");
    1180                 :            :         }
    1181         [ #  # ]:          0 :         return rte_be_to_cpu_16(spec->hdr.ether_type);
    1182                 :            : }
    1183                 :            : 
    1184                 :            : static int
    1185                 :          0 : mlx5_flex_arc_in_udp(const struct rte_flow_item *item,
    1186                 :            :                      struct rte_flow_error *error)
    1187                 :            : {
    1188                 :          0 :         const struct rte_flow_item_udp *spec = item->spec;
    1189                 :          0 :         const struct rte_flow_item_udp *mask = item->mask;
    1190                 :          0 :         struct rte_flow_item_udp udp = { .hdr.dst_port = RTE_BE16(0xFFFF) };
    1191                 :            : 
    1192         [ #  # ]:          0 :         if (memcmp(mask, &udp, sizeof(struct rte_flow_item_udp))) {
    1193                 :          0 :                 return rte_flow_error_set
    1194                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1195                 :            :                          "invalid eth item mask");
    1196                 :            :         }
    1197         [ #  # ]:          0 :         return rte_be_to_cpu_16(spec->hdr.dst_port);
    1198                 :            : }
    1199                 :            : 
    1200                 :            : static int
    1201                 :          0 : mlx5_flex_arc_in_ipv4(const struct rte_flow_item *item,
    1202                 :            :                       struct rte_flow_error *error)
    1203                 :            : {
    1204                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
    1205                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
    1206                 :          0 :         struct rte_flow_item_ipv4 ip = { .hdr.next_proto_id = 0xff };
    1207                 :            : 
    1208         [ #  # ]:          0 :         if (memcmp(mask, &ip, sizeof(struct rte_flow_item_ipv4))) {
    1209                 :          0 :                 return rte_flow_error_set
    1210                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1211                 :            :                          "invalid ipv4 item mask, full mask is desired");
    1212                 :            :         }
    1213                 :          0 :         return spec->hdr.next_proto_id;
    1214                 :            : }
    1215                 :            : 
    1216                 :            : static int
    1217                 :          0 : mlx5_flex_arc_in_ipv6(const struct rte_flow_item *item,
    1218                 :            :                       struct rte_flow_error *error)
    1219                 :            : {
    1220                 :          0 :         const struct rte_flow_item_ipv6 *spec = item->spec;
    1221                 :          0 :         const struct rte_flow_item_ipv6 *mask = item->mask;
    1222                 :          0 :         struct rte_flow_item_ipv6 ip = { .hdr.proto = 0xff };
    1223                 :            : 
    1224         [ #  # ]:          0 :         if (memcmp(mask, &ip, sizeof(struct rte_flow_item_ipv6))) {
    1225                 :          0 :                 return rte_flow_error_set
    1226                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
    1227                 :            :                          "invalid ipv6 item mask, full mask is desired");
    1228                 :            :         }
    1229                 :          0 :         return spec->hdr.proto;
    1230                 :            : }
    1231                 :            : 
    1232                 :            : static int
    1233                 :          0 : mlx5_flex_translate_arc_in(struct mlx5_hca_flex_attr *attr,
    1234                 :            :                            const struct rte_flow_item_flex_conf *conf,
    1235                 :            :                            struct mlx5_flex_parser_devx *devx,
    1236                 :            :                            struct mlx5_flex_item *item,
    1237                 :            :                            struct rte_flow_error *error)
    1238                 :            : {
    1239                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
    1240                 :            :         uint32_t i;
    1241                 :            : 
    1242                 :            :         RTE_SET_USED(item);
    1243         [ #  # ]:          0 :         if (conf->nb_inputs > attr->max_num_arc_in)
    1244                 :          0 :                 return rte_flow_error_set
    1245                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1246                 :            :                          "too many input links");
    1247         [ #  # ]:          0 :         for (i = 0; i < conf->nb_inputs; i++) {
    1248                 :          0 :                 struct mlx5_devx_graph_arc_attr *arc = node->in + i;
    1249                 :          0 :                 struct rte_flow_item_flex_link *link = conf->input_link + i;
    1250                 :          0 :                 const struct rte_flow_item *rte_item = &link->item;
    1251                 :            :                 int arc_type;
    1252                 :            :                 int ret;
    1253                 :            : 
    1254   [ #  #  #  #  :          0 :                 if (!rte_item->spec || !rte_item->mask || rte_item->last)
                   #  # ]
    1255                 :          0 :                         return rte_flow_error_set
    1256                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1257                 :            :                                  "invalid flex item IN arc format");
    1258                 :          0 :                 arc_type = mlx5_flex_arc_type(rte_item->type, true);
    1259   [ #  #  #  # ]:          0 :                 if (arc_type < 0 || !(attr->node_in & RTE_BIT32(arc_type)))
    1260                 :          0 :                         return rte_flow_error_set
    1261                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1262                 :            :                                  "unsupported flex item IN arc type");
    1263                 :          0 :                 arc->arc_parse_graph_node = arc_type;
    1264                 :          0 :                 arc->start_inner_tunnel = 0;
    1265                 :            :                 /*
    1266                 :            :                  * Configure arc IN condition value. The value location depends
    1267                 :            :                  * on protocol. Current FW version supports IP & UDP for IN
    1268                 :            :                  * arcs only, and locations for these protocols are defined.
    1269                 :            :                  * Add more protocols when available.
    1270                 :            :                  */
    1271   [ #  #  #  #  :          0 :                 switch (rte_item->type) {
                      # ]
    1272                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    1273                 :          0 :                         ret = mlx5_flex_arc_in_eth(rte_item, error);
    1274                 :          0 :                         break;
    1275                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    1276                 :          0 :                         ret = mlx5_flex_arc_in_udp(rte_item, error);
    1277                 :          0 :                         break;
    1278                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    1279                 :          0 :                         ret = mlx5_flex_arc_in_ipv4(rte_item, error);
    1280                 :          0 :                         break;
    1281                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    1282                 :          0 :                         ret = mlx5_flex_arc_in_ipv6(rte_item, error);
    1283                 :          0 :                         break;
    1284                 :          0 :                 default:
    1285                 :            :                         MLX5_ASSERT(false);
    1286                 :          0 :                         return rte_flow_error_set
    1287                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1288                 :            :                                  "unsupported flex item IN arc type");
    1289                 :            :                 }
    1290         [ #  # ]:          0 :                 if (ret < 0)
    1291                 :          0 :                         return ret;
    1292                 :          0 :                 arc->compare_condition_value = (uint16_t)ret;
    1293                 :            :         }
    1294                 :            :         return 0;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : static int
    1298                 :          0 : mlx5_flex_translate_arc_out(struct mlx5_hca_flex_attr *attr,
    1299                 :            :                             const struct rte_flow_item_flex_conf *conf,
    1300                 :            :                             struct mlx5_flex_parser_devx *devx,
    1301                 :            :                             struct mlx5_flex_item *item,
    1302                 :            :                             struct rte_flow_error *error)
    1303                 :            : {
    1304                 :            :         struct mlx5_devx_graph_node_attr *node = &devx->devx_conf;
    1305                 :          0 :         bool is_tunnel = conf->tunnel == FLEX_TUNNEL_MODE_TUNNEL;
    1306                 :            :         uint32_t i;
    1307                 :            : 
    1308                 :            :         RTE_SET_USED(item);
    1309         [ #  # ]:          0 :         if (conf->nb_outputs > attr->max_num_arc_out)
    1310                 :          0 :                 return rte_flow_error_set
    1311                 :            :                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1312                 :            :                          "too many output links");
    1313         [ #  # ]:          0 :         for (i = 0; i < conf->nb_outputs; i++) {
    1314                 :          0 :                 struct mlx5_devx_graph_arc_attr *arc = node->out + i;
    1315                 :          0 :                 struct rte_flow_item_flex_link *link = conf->output_link + i;
    1316                 :            :                 const struct rte_flow_item *rte_item = &link->item;
    1317                 :            :                 int arc_type;
    1318                 :            : 
    1319   [ #  #  #  #  :          0 :                 if (rte_item->spec || rte_item->mask || rte_item->last)
                   #  # ]
    1320                 :          0 :                         return rte_flow_error_set
    1321                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1322                 :            :                                  "flex node: invalid OUT arc format");
    1323                 :          0 :                 arc_type = mlx5_flex_arc_type(rte_item->type, false);
    1324   [ #  #  #  # ]:          0 :                 if (arc_type < 0 || !(attr->node_out & RTE_BIT32(arc_type)))
    1325                 :          0 :                         return rte_flow_error_set
    1326                 :            :                                 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1327                 :            :                                  "unsupported flex item OUT arc type");
    1328                 :          0 :                 arc->arc_parse_graph_node = arc_type;
    1329                 :          0 :                 arc->start_inner_tunnel = !!is_tunnel;
    1330                 :          0 :                 arc->compare_condition_value = link->next;
    1331                 :            :         }
    1332                 :            :         return 0;
    1333                 :            : }
    1334                 :            : 
    1335                 :            : /* Translate RTE flex item API configuration into flaex parser settings. */
    1336                 :            : static int
    1337                 :          0 : mlx5_flex_translate_conf(struct rte_eth_dev *dev,
    1338                 :            :                          const struct rte_flow_item_flex_conf *conf,
    1339                 :            :                          struct mlx5_flex_parser_devx *devx,
    1340                 :            :                          struct mlx5_flex_item *item,
    1341                 :            :                          struct rte_flow_error *error)
    1342                 :            : {
    1343                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1344                 :          0 :         struct mlx5_hca_flex_attr *attr = &priv->sh->cdev->config.hca_attr.flex;
    1345                 :            :         int ret;
    1346                 :            : 
    1347                 :          0 :         ret = mlx5_flex_translate_length(attr, conf, devx, error);
    1348         [ #  # ]:          0 :         if (ret)
    1349                 :            :                 return ret;
    1350                 :          0 :         ret = mlx5_flex_translate_next(attr, conf, devx, error);
    1351         [ #  # ]:          0 :         if (ret)
    1352                 :            :                 return ret;
    1353                 :          0 :         ret = mlx5_flex_translate_sample(attr, conf, devx, item, error);
    1354         [ #  # ]:          0 :         if (ret)
    1355                 :            :                 return ret;
    1356                 :          0 :         ret = mlx5_flex_translate_arc_in(attr, conf, devx, item, error);
    1357         [ #  # ]:          0 :         if (ret)
    1358                 :            :                 return ret;
    1359                 :          0 :         ret = mlx5_flex_translate_arc_out(attr, conf, devx, item, error);
    1360         [ #  # ]:          0 :         if (ret)
    1361                 :          0 :                 return ret;
    1362                 :            :         return 0;
    1363                 :            : }
    1364                 :            : 
    1365                 :            : /**
    1366                 :            :  * Create the flex item with specified configuration over the Ethernet device.
    1367                 :            :  *
    1368                 :            :  * @param dev
    1369                 :            :  *   Ethernet device to create flex item on.
    1370                 :            :  * @param[in] conf
    1371                 :            :  *   Flex item configuration.
    1372                 :            :  * @param[out] error
    1373                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
    1374                 :            :  *   structure in case of error only.
    1375                 :            :  *
    1376                 :            :  * @return
    1377                 :            :  *   Non-NULL opaque pointer on success, NULL otherwise and rte_errno is set.
    1378                 :            :  */
    1379                 :            : struct rte_flow_item_flex_handle *
    1380                 :          0 : mlx5_flow_dv_item_create(struct rte_eth_dev *dev,
    1381                 :            :                          const struct rte_flow_item_flex_conf *conf,
    1382                 :            :                          struct rte_flow_error *error)
    1383                 :            : {
    1384                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1385                 :          0 :         struct mlx5_flex_parser_devx devx_config = { .devx_obj = NULL };
    1386                 :            :         struct mlx5_flex_item *flex;
    1387                 :            :         struct mlx5_list_entry *ent;
    1388                 :            : 
    1389                 :            :         MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
    1390                 :          0 :         flex = mlx5_flex_alloc(priv);
    1391         [ #  # ]:          0 :         if (!flex) {
    1392                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    1393                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1394                 :            :                                    "too many flex items created on the port");
    1395                 :          0 :                 return NULL;
    1396                 :            :         }
    1397         [ #  # ]:          0 :         if (mlx5_flex_translate_conf(dev, conf, &devx_config, flex, error))
    1398                 :          0 :                 goto error;
    1399                 :          0 :         ent = mlx5_list_register(priv->sh->flex_parsers_dv, &devx_config);
    1400         [ #  # ]:          0 :         if (!ent) {
    1401                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    1402                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1403                 :            :                                    "flex item creation failure");
    1404                 :          0 :                 goto error;
    1405                 :            :         }
    1406                 :          0 :         flex->devx_fp = container_of(ent, struct mlx5_flex_parser_devx, entry);
    1407                 :            :         /* Mark initialized flex item valid. */
    1408                 :          0 :         rte_atomic_fetch_add_explicit(&flex->refcnt, 1, rte_memory_order_release);
    1409                 :          0 :         return (struct rte_flow_item_flex_handle *)flex;
    1410                 :            : 
    1411                 :          0 : error:
    1412                 :          0 :         mlx5_flex_free(priv, flex);
    1413                 :          0 :         return NULL;
    1414                 :            : }
    1415                 :            : 
    1416                 :            : /**
    1417                 :            :  * Release the flex item on the specified Ethernet device.
    1418                 :            :  *
    1419                 :            :  * @param dev
    1420                 :            :  *   Ethernet device to destroy flex item on.
    1421                 :            :  * @param[in] handle
    1422                 :            :  *   Handle of the item existing on the specified device.
    1423                 :            :  * @param[out] error
    1424                 :            :  *   Perform verbose error reporting if not NULL. PMDs initialize this
    1425                 :            :  *   structure in case of error only.
    1426                 :            :  *
    1427                 :            :  * @return
    1428                 :            :  *   0 on success, a negative errno value otherwise and rte_errno is set.
    1429                 :            :  */
    1430                 :            : int
    1431                 :          0 : mlx5_flow_dv_item_release(struct rte_eth_dev *dev,
    1432                 :            :                           const struct rte_flow_item_flex_handle *handle,
    1433                 :            :                           struct rte_flow_error *error)
    1434                 :            : {
    1435                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1436                 :            :         struct mlx5_flex_item *flex =
    1437                 :            :                 (struct mlx5_flex_item *)(uintptr_t)handle;
    1438                 :            :         uint32_t old_refcnt = 1;
    1439                 :            :         int rc;
    1440                 :            : 
    1441                 :            :         MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
    1442                 :          0 :         rte_spinlock_lock(&priv->flex_item_sl);
    1443         [ #  # ]:          0 :         if (mlx5_flex_index(priv, flex) < 0) {
    1444                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
    1445                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    1446                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1447                 :            :                                           "invalid flex item handle value");
    1448                 :            :         }
    1449         [ #  # ]:          0 :         if (!rte_atomic_compare_exchange_strong_explicit(&flex->refcnt, &old_refcnt, 0,
    1450                 :            :                                          rte_memory_order_acquire, rte_memory_order_relaxed)) {
    1451                 :            :                 rte_spinlock_unlock(&priv->flex_item_sl);
    1452                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    1453                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1454                 :            :                                           "flex item has flow references");
    1455                 :            :         }
    1456                 :            :         /* Flex item is marked as invalid, we can leave locked section. */
    1457                 :            :         rte_spinlock_unlock(&priv->flex_item_sl);
    1458                 :            :         MLX5_ASSERT(flex->devx_fp);
    1459                 :          0 :         rc = mlx5_list_unregister(priv->sh->flex_parsers_dv,
    1460                 :          0 :                                   &flex->devx_fp->entry);
    1461                 :          0 :         flex->devx_fp = NULL;
    1462                 :          0 :         mlx5_flex_free(priv, flex);
    1463         [ #  # ]:          0 :         if (rc < 0)
    1464                 :          0 :                 return rte_flow_error_set(error, EBUSY,
    1465                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    1466                 :            :                                           "flex item release failure");
    1467                 :            :         return 0;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : /* DevX flex parser list callbacks. */
    1471                 :            : struct mlx5_list_entry *
    1472                 :          0 : mlx5_flex_parser_create_cb(void *list_ctx, void *ctx)
    1473                 :            : {
    1474                 :            :         struct mlx5_dev_ctx_shared *sh = list_ctx;
    1475                 :            :         struct mlx5_flex_parser_devx *fp, *conf = ctx;
    1476                 :            :         uint32_t i;
    1477                 :          0 :         uint8_t sample_info = sh->cdev->config.hca_attr.flex.query_match_sample_info;
    1478                 :            :         int ret;
    1479                 :            : 
    1480                 :          0 :         fp = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_flex_parser_devx),
    1481                 :            :                          0, SOCKET_ID_ANY);
    1482         [ #  # ]:          0 :         if (!fp)
    1483                 :            :                 return NULL;
    1484                 :            :         /* Copy the requested configurations. */
    1485                 :          0 :         fp->num_samples = conf->num_samples;
    1486                 :          0 :         memcpy(&fp->devx_conf, &conf->devx_conf, sizeof(fp->devx_conf));
    1487                 :            :         /* Create DevX flex parser. */
    1488                 :          0 :         fp->devx_obj = mlx5_devx_cmd_create_flex_parser(sh->cdev->ctx,
    1489                 :            :                                                         &fp->devx_conf);
    1490         [ #  # ]:          0 :         if (!fp->devx_obj)
    1491                 :          0 :                 goto error;
    1492                 :            :         /* Query the firmware assigned sample ids. */
    1493                 :          0 :         ret = mlx5_devx_cmd_query_parse_samples(fp->devx_obj,
    1494                 :          0 :                                                 fp->sample_ids,
    1495                 :            :                                                 fp->num_samples,
    1496                 :            :                                                 &fp->anchor_id);
    1497         [ #  # ]:          0 :         if (ret)
    1498                 :          0 :                 goto error;
    1499                 :            :         /* Query sample information per ID. */
    1500   [ #  #  #  # ]:          0 :         for (i = 0; i < fp->num_samples && sample_info; i++) {
    1501                 :          0 :                 ret = mlx5_devx_cmd_match_sample_info_query(sh->cdev->ctx, fp->sample_ids[i],
    1502                 :            :                                                             &fp->sample_info[i]);
    1503         [ #  # ]:          0 :                 if (ret)
    1504                 :          0 :                         goto error;
    1505                 :            :         }
    1506                 :          0 :         DRV_LOG(DEBUG, "DEVx flex parser %p created, samples num: %u",
    1507                 :            :                 (const void *)fp, fp->num_samples);
    1508                 :          0 :         return &fp->entry;
    1509                 :          0 : error:
    1510         [ #  # ]:          0 :         if (fp->devx_obj)
    1511                 :          0 :                 mlx5_devx_cmd_destroy((void *)(uintptr_t)fp->devx_obj);
    1512                 :            :         if (fp)
    1513                 :          0 :                 mlx5_free(fp);
    1514                 :          0 :         return NULL;
    1515                 :            : }
    1516                 :            : 
    1517                 :            : int
    1518                 :          0 : mlx5_flex_parser_match_cb(void *list_ctx,
    1519                 :            :                           struct mlx5_list_entry *iter, void *ctx)
    1520                 :            : {
    1521                 :            :         struct mlx5_flex_parser_devx *fp =
    1522                 :            :                 container_of(iter, struct mlx5_flex_parser_devx, entry);
    1523                 :            :         struct mlx5_flex_parser_devx *org =
    1524                 :            :                 container_of(ctx, struct mlx5_flex_parser_devx, entry);
    1525                 :            : 
    1526                 :            :         RTE_SET_USED(list_ctx);
    1527         [ #  # ]:          0 :         return !iter || !ctx || memcmp(&fp->devx_conf,
    1528         [ #  # ]:          0 :                                        &org->devx_conf,
    1529                 :            :                                        sizeof(fp->devx_conf));
    1530                 :            : }
    1531                 :            : 
    1532                 :            : void
    1533                 :          0 : mlx5_flex_parser_remove_cb(void *list_ctx, struct mlx5_list_entry *entry)
    1534                 :            : {
    1535                 :            :         struct mlx5_flex_parser_devx *fp =
    1536                 :            :                 container_of(entry, struct mlx5_flex_parser_devx, entry);
    1537                 :            : 
    1538                 :            :         RTE_SET_USED(list_ctx);
    1539                 :            :         MLX5_ASSERT(fp->devx_obj);
    1540                 :          0 :         claim_zero(mlx5_devx_cmd_destroy(fp->devx_obj));
    1541                 :          0 :         DRV_LOG(DEBUG, "DEVx flex parser %p destroyed", (const void *)fp);
    1542                 :          0 :         mlx5_free(entry);
    1543                 :          0 : }
    1544                 :            : 
    1545                 :            : struct mlx5_list_entry *
    1546                 :          0 : mlx5_flex_parser_clone_cb(void *list_ctx,
    1547                 :            :                           struct mlx5_list_entry *entry, void *ctx)
    1548                 :            : {
    1549                 :            :         struct mlx5_flex_parser_devx *fp;
    1550                 :            : 
    1551                 :            :         RTE_SET_USED(list_ctx);
    1552                 :            :         RTE_SET_USED(entry);
    1553                 :          0 :         fp = mlx5_malloc(0, sizeof(struct mlx5_flex_parser_devx),
    1554                 :            :                          0, SOCKET_ID_ANY);
    1555         [ #  # ]:          0 :         if (!fp)
    1556                 :            :                 return NULL;
    1557                 :            :         memcpy(fp, ctx, sizeof(struct mlx5_flex_parser_devx));
    1558                 :          0 :         return &fp->entry;
    1559                 :            : }
    1560                 :            : 
    1561                 :            : void
    1562                 :          0 : mlx5_flex_parser_clone_free_cb(void *list_ctx, struct mlx5_list_entry *entry)
    1563                 :            : {
    1564                 :            :         struct mlx5_flex_parser_devx *fp =
    1565                 :            :                 container_of(entry, struct mlx5_flex_parser_devx, entry);
    1566                 :            :         RTE_SET_USED(list_ctx);
    1567                 :          0 :         mlx5_free(fp);
    1568                 :          0 : }
    1569                 :            : 
    1570                 :            : /*
    1571                 :            :  * Destroy the flex parser node, including the parser itself, input / output
    1572                 :            :  * arcs and DW samples. Resources could be reused then.
    1573                 :            :  *
    1574                 :            :  * @param dev
    1575                 :            :  *   Pointer to Ethernet device structure.
    1576                 :            :  */
    1577                 :            : void
    1578                 :          0 : mlx5_flex_parser_ecpri_release(struct rte_eth_dev *dev)
    1579                 :            : {
    1580                 :          0 :         struct mlx5_priv *priv = dev->data->dev_private;
    1581                 :          0 :         struct mlx5_ecpri_parser_profile *prf = &priv->sh->ecpri_parser;
    1582                 :            : 
    1583         [ #  # ]:          0 :         if (prf->obj)
    1584                 :          0 :                 mlx5_devx_cmd_destroy(prf->obj);
    1585                 :          0 :         prf->obj = NULL;
    1586                 :          0 : }

Generated by: LCOV version 1.14