LCOV - code coverage report
Current view: top level - drivers/net/ice/base - ice_acl_ctrl.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 337 0.0 %
Date: 2024-01-22 16:13:49 Functions: 0 14 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 286 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2001-2023 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "ice_acl.h"
       6                 :            : #include "ice_flow.h"
       7                 :            : 
       8                 :            : /* Determine the TCAM index of entry 'e' within the ACL table */
       9                 :            : #define ICE_ACL_TBL_TCAM_IDX(e) ((u8)((e) / ICE_AQC_ACL_TCAM_DEPTH))
      10                 :            : 
      11                 :            : /* Determine the entry index within the TCAM */
      12                 :            : #define ICE_ACL_TBL_TCAM_ENTRY_IDX(e) ((u16)((e) % ICE_AQC_ACL_TCAM_DEPTH))
      13                 :            : 
      14                 :            : #define ICE_ACL_SCEN_ENTRY_INVAL 0xFFFF
      15                 :            : 
      16                 :            : /**
      17                 :            :  * ice_acl_init_entry
      18                 :            :  * @scen: pointer to the scenario struct
      19                 :            :  *
      20                 :            :  * Initialize the scenario control structure.
      21                 :            :  */
      22                 :            : static void ice_acl_init_entry(struct ice_acl_scen *scen)
      23                 :            : {
      24                 :            :         /* low priority: start from the highest index, 25% of total entries
      25                 :            :          * normal priority: start from the highest index, 50% of total entries
      26                 :            :          * high priority: start from the lowest index, 25% of total entries
      27                 :            :          */
      28                 :          0 :         scen->first_idx[ICE_ACL_PRIO_LOW] = scen->num_entry - 1;
      29                 :          0 :         scen->first_idx[ICE_ACL_PRIO_NORMAL] = scen->num_entry -
      30                 :          0 :                 scen->num_entry / 4 - 1;
      31                 :          0 :         scen->first_idx[ICE_ACL_PRIO_HIGH] = 0;
      32                 :            : 
      33                 :          0 :         scen->last_idx[ICE_ACL_PRIO_LOW] = scen->num_entry -
      34                 :            :                 scen->num_entry / 4;
      35                 :          0 :         scen->last_idx[ICE_ACL_PRIO_NORMAL] = scen->num_entry / 4;
      36                 :          0 :         scen->last_idx[ICE_ACL_PRIO_HIGH] = scen->num_entry / 4 - 1;
      37                 :            : }
      38                 :            : 
      39                 :            : /**
      40                 :            :  * ice_acl_scen_assign_entry_idx
      41                 :            :  * @scen: pointer to the scenario struct
      42                 :            :  * @prio: the priority of the flow entry being allocated
      43                 :            :  *
      44                 :            :  * To find the index of an available entry in scenario
      45                 :            :  *
      46                 :            :  * Returns ICE_ACL_SCEN_ENTRY_INVAL if fails
      47                 :            :  * Returns index on success
      48                 :            :  */
      49                 :            : static u16
      50                 :          0 : ice_acl_scen_assign_entry_idx(struct ice_acl_scen *scen,
      51                 :            :                               enum ice_acl_entry_prio prio)
      52                 :            : {
      53                 :            :         u16 first_idx, last_idx, i;
      54                 :            :         s8 step;
      55                 :            : 
      56         [ #  # ]:          0 :         if (prio >= ICE_ACL_MAX_PRIO)
      57                 :            :                 return ICE_ACL_SCEN_ENTRY_INVAL;
      58                 :            : 
      59                 :          0 :         first_idx = scen->first_idx[prio];
      60                 :          0 :         last_idx = scen->last_idx[prio];
      61         [ #  # ]:          0 :         step = first_idx <= last_idx ? 1 : -1;
      62                 :            : 
      63         [ #  # ]:          0 :         for (i = first_idx; i != last_idx + step; i += step)
      64         [ #  # ]:          0 :                 if (!ice_test_and_set_bit(i, scen->entry_bitmap))
      65                 :          0 :                         return i;
      66                 :            : 
      67                 :            :         return ICE_ACL_SCEN_ENTRY_INVAL;
      68                 :            : }
      69                 :            : 
      70                 :            : /**
      71                 :            :  * ice_acl_scen_free_entry_idx
      72                 :            :  * @scen: pointer to the scenario struct
      73                 :            :  * @idx: the index of the flow entry being de-allocated
      74                 :            :  *
      75                 :            :  * To mark an entry available in scenario
      76                 :            :  */
      77                 :            : static enum ice_status
      78                 :            : ice_acl_scen_free_entry_idx(struct ice_acl_scen *scen, u16 idx)
      79                 :            : {
      80         [ #  # ]:          0 :         if (idx >= scen->num_entry)
      81                 :            :                 return ICE_ERR_MAX_LIMIT;
      82                 :            : 
      83                 :            :         if (!ice_test_and_clear_bit(idx, scen->entry_bitmap))
      84                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
      85                 :            : 
      86                 :            :         return ICE_SUCCESS;
      87                 :            : }
      88                 :            : 
      89                 :            : /**
      90                 :            :  * ice_acl_tbl_calc_end_idx
      91                 :            :  * @start: start index of the TCAM entry of this partition
      92                 :            :  * @num_entries: number of entries in this partition
      93                 :            :  * @width: width of a partition in number of TCAMs
      94                 :            :  *
      95                 :            :  * Calculate the end entry index for a partition with starting entry index
      96                 :            :  * 'start', entries 'num_entries', and width 'width'.
      97                 :            :  */
      98                 :            : static u16 ice_acl_tbl_calc_end_idx(u16 start, u16 num_entries, u16 width)
      99                 :            : {
     100                 :            :         u16 end_idx, add_entries = 0;
     101                 :            : 
     102                 :          0 :         end_idx = start + (num_entries - 1);
     103                 :            : 
     104                 :            :         /* In case that our ACL partition requires cascading TCAMs */
     105                 :          0 :         if (width > 1) {
     106                 :            :                 u16 num_stack_level;
     107                 :            : 
     108                 :            :                 /* Figure out the TCAM stacked level in this ACL scenario */
     109                 :          0 :                 num_stack_level = (start % ICE_AQC_ACL_TCAM_DEPTH) +
     110                 :            :                         num_entries;
     111                 :          0 :                 num_stack_level = DIVIDE_AND_ROUND_UP(num_stack_level,
     112                 :            :                                                       ICE_AQC_ACL_TCAM_DEPTH);
     113                 :            : 
     114                 :            :                 /* In this case, each entries in our ACL partition span
     115                 :            :                  * multiple TCAMs. Thus, we will need to add
     116                 :            :                  * ((width - 1) * num_stack_level) TCAM's entries to
     117                 :            :                  * end_idx.
     118                 :            :                  *
     119                 :            :                  * For example : In our case, our scenario is 2x2:
     120                 :            :                  *      [TCAM 0]        [TCAM 1]
     121                 :            :                  *      [TCAM 2]        [TCAM 3]
     122                 :            :                  * Assuming that a TCAM will have 512 entries. If "start"
     123                 :            :                  * is 500, "num_entries" is 3 and "width" = 2, then end_idx
     124                 :            :                  * should be 1024 (belongs to TCAM 2).
     125                 :            :                  * Before going to this if statement, end_idx will have the
     126                 :            :                  * value of 512. If "width" is 1, then the final value of
     127                 :            :                  * end_idx is 512. However, in our case, width is 2, then we
     128                 :            :                  * will need add (2 - 1) * 1 * 512. As result, end_idx will
     129                 :            :                  * have the value of 1024.
     130                 :            :                  */
     131                 :          0 :                 add_entries = (width - 1) * num_stack_level *
     132                 :            :                         ICE_AQC_ACL_TCAM_DEPTH;
     133                 :            :         }
     134                 :            : 
     135                 :          0 :         return end_idx + add_entries;
     136                 :            : }
     137                 :            : 
     138                 :            : /**
     139                 :            :  * ice_acl_init_tbl
     140                 :            :  * @hw: pointer to the hardware structure
     141                 :            :  *
     142                 :            :  * Initialize the ACL table by invalidating TCAM entries and action pairs.
     143                 :            :  */
     144                 :          0 : static enum ice_status ice_acl_init_tbl(struct ice_hw *hw)
     145                 :            : {
     146                 :            :         struct ice_aqc_actpair act_buf;
     147                 :            :         struct ice_aqc_acl_data buf;
     148                 :            :         enum ice_status status = ICE_SUCCESS;
     149                 :            :         struct ice_acl_tbl *tbl;
     150                 :            :         u8 tcam_idx, i;
     151                 :            :         u16 idx;
     152                 :            : 
     153                 :          0 :         tbl = hw->acl_tbl;
     154         [ #  # ]:          0 :         if (!tbl)
     155                 :            :                 return ICE_ERR_CFG;
     156                 :            : 
     157                 :            :         ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
     158                 :            :         ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);
     159                 :            : 
     160                 :          0 :         tcam_idx = tbl->first_tcam;
     161                 :          0 :         idx = tbl->first_entry;
     162   [ #  #  #  # ]:          0 :         while (tcam_idx < tbl->last_tcam ||
     163         [ #  # ]:          0 :                (tcam_idx == tbl->last_tcam && idx <= tbl->last_entry)) {
     164                 :            :                 /* Use the same value for entry_key and entry_key_inv since
     165                 :            :                  * we are initializing the fields to 0
     166                 :            :                  */
     167                 :          0 :                 status = ice_aq_program_acl_entry(hw, tcam_idx, idx, &buf,
     168                 :            :                                                   NULL);
     169         [ #  # ]:          0 :                 if (status)
     170                 :          0 :                         return status;
     171                 :            : 
     172         [ #  # ]:          0 :                 if (++idx > tbl->last_entry) {
     173                 :          0 :                         tcam_idx++;
     174                 :          0 :                         idx = tbl->first_entry;
     175                 :            :                 }
     176                 :            :         }
     177                 :            : 
     178         [ #  # ]:          0 :         for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) {
     179                 :            :                 u16 act_entry_idx, start, end;
     180                 :            : 
     181         [ #  # ]:          0 :                 if (tbl->act_mems[i].act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL)
     182                 :          0 :                         continue;
     183                 :            : 
     184                 :          0 :                 start = tbl->first_entry;
     185                 :          0 :                 end = tbl->last_entry;
     186                 :            : 
     187         [ #  # ]:          0 :                 for (act_entry_idx = start; act_entry_idx <= end;
     188                 :          0 :                      act_entry_idx++) {
     189                 :            :                         /* Invalidate all allocated action pairs */
     190                 :          0 :                         status = ice_aq_program_actpair(hw, i, act_entry_idx,
     191                 :            :                                                         &act_buf, NULL);
     192         [ #  # ]:          0 :                         if (status)
     193                 :          0 :                                 return status;
     194                 :            :                 }
     195                 :            :         }
     196                 :            : 
     197                 :            :         return status;
     198                 :            : }
     199                 :            : 
     200                 :            : /**
     201                 :            :  * ice_acl_assign_act_mems_to_tcam
     202                 :            :  * @tbl: pointer to ACL table structure
     203                 :            :  * @cur_tcam: Index of current TCAM. Value = 0 to (ICE_AQC_ACL_SLICES - 1)
     204                 :            :  * @cur_mem_idx: Index of current action memory bank. Value = 0 to
     205                 :            :  *               (ICE_AQC_MAX_ACTION_MEMORIES - 1)
     206                 :            :  * @num_mem: Number of action memory banks for this TCAM
     207                 :            :  *
     208                 :            :  * Assign "num_mem" valid action memory banks from "curr_mem_idx" to
     209                 :            :  * "curr_tcam" TCAM.
     210                 :            :  */
     211                 :            : static void
     212                 :            : ice_acl_assign_act_mems_to_tcam(struct ice_acl_tbl *tbl, u8 cur_tcam,
     213                 :            :                                 u8 *cur_mem_idx, u8 num_mem)
     214                 :            : {
     215                 :            :         u8 mem_cnt;
     216                 :            : 
     217                 :          0 :         for (mem_cnt = 0;
     218   [ #  #  #  # ]:          0 :              *cur_mem_idx < ICE_AQC_MAX_ACTION_MEMORIES && mem_cnt < num_mem;
     219                 :          0 :              (*cur_mem_idx)++) {
     220                 :          0 :                 struct ice_acl_act_mem *p_mem = &tbl->act_mems[*cur_mem_idx];
     221                 :            : 
     222         [ #  # ]:          0 :                 if (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL)
     223                 :          0 :                         continue;
     224                 :            : 
     225                 :          0 :                 p_mem->member_of_tcam = cur_tcam;
     226                 :            : 
     227                 :          0 :                 mem_cnt++;
     228                 :            :         }
     229                 :            : }
     230                 :            : 
     231                 :            : /**
     232                 :            :  * ice_acl_divide_act_mems_to_tcams
     233                 :            :  * @tbl: pointer to ACL table structure
     234                 :            :  *
     235                 :            :  * Figure out how to divide given action memory banks to given TCAMs. This
     236                 :            :  * division is for SW book keeping. In the time when scenario is created,
     237                 :            :  * an action memory bank can be used for different TCAM.
     238                 :            :  *
     239                 :            :  * For example, given that we have 2x2 ACL table with each table entry has
     240                 :            :  * 2 action memory pairs. As the result, we will have 4 TCAMs (T1,T2,T3,T4)
     241                 :            :  * and 4 action memory banks (A1,A2,A3,A4)
     242                 :            :  *      [T1 - T2] { A1 - A2 }
     243                 :            :  *      [T3 - T4] { A3 - A4 }
     244                 :            :  * In the time when we need to create a scenario, for example, 2x1 scenario,
     245                 :            :  * we will use [T3,T4] in a cascaded layout. As it is a requirement that all
     246                 :            :  * action memory banks in a cascaded TCAM's row will need to associate with
     247                 :            :  * the last TCAM. Thus, we will associate action memory banks [A3] and [A4]
     248                 :            :  * for TCAM [T4].
     249                 :            :  * For SW book-keeping purpose, we will keep theoretical maps between TCAM
     250                 :            :  * [Tn] to action memory bank [An].
     251                 :            :  */
     252                 :          0 : static void ice_acl_divide_act_mems_to_tcams(struct ice_acl_tbl *tbl)
     253                 :            : {
     254                 :            :         u16 num_cscd, stack_level, stack_idx, max_idx_to_get_extra;
     255                 :          0 :         u8 min_act_mem, tcam_idx = tbl->first_tcam, mem_idx = 0;
     256                 :            : 
     257                 :            :         /* Determine number of stacked TCAMs */
     258                 :          0 :         stack_level = DIVIDE_AND_ROUND_UP(tbl->info.depth,
     259                 :            :                                           ICE_AQC_ACL_TCAM_DEPTH);
     260                 :            : 
     261                 :            :         /* Determine number of cascaded TCAMs */
     262                 :          0 :         num_cscd = DIVIDE_AND_ROUND_UP(tbl->info.width,
     263                 :            :                                        ICE_AQC_ACL_KEY_WIDTH_BYTES);
     264                 :            : 
     265                 :            :         /* In a line of cascaded TCAM, given the number of action memory
     266                 :            :          * banks per ACL table entry, we want to fairly divide these action
     267                 :            :          * memory banks between these TCAMs.
     268                 :            :          *
     269                 :            :          * For example, there are 3 TCAMs (TCAM 3,4,5) in a line of
     270                 :            :          * cascaded TCAM, and there are 7 act_mems for each ACL table entry.
     271                 :            :          * The result is:
     272                 :            :          *      [TCAM_3 will have 3 act_mems]
     273                 :            :          *      [TCAM_4 will have 2 act_mems]
     274                 :            :          *      [TCAM_5 will have 2 act_mems]
     275                 :            :          */
     276                 :          0 :         min_act_mem = tbl->info.entry_act_pairs / num_cscd;
     277                 :          0 :         max_idx_to_get_extra = tbl->info.entry_act_pairs % num_cscd;
     278                 :            : 
     279         [ #  # ]:          0 :         for (stack_idx = 0; stack_idx < stack_level; stack_idx++) {
     280                 :            :                 u16 i;
     281                 :            : 
     282         [ #  # ]:          0 :                 for (i = 0; i < num_cscd; i++) {
     283                 :            :                         u8 total_act_mem = min_act_mem;
     284                 :            : 
     285         [ #  # ]:          0 :                         if (i < max_idx_to_get_extra)
     286                 :          0 :                                 total_act_mem++;
     287                 :            : 
     288                 :            :                         ice_acl_assign_act_mems_to_tcam(tbl, tcam_idx,
     289                 :            :                                                         &mem_idx,
     290                 :            :                                                         total_act_mem);
     291                 :            : 
     292                 :          0 :                         tcam_idx++;
     293                 :            :                 }
     294                 :            :         }
     295                 :          0 : }
     296                 :            : 
     297                 :            : /**
     298                 :            :  * ice_acl_create_tbl
     299                 :            :  * @hw: pointer to the HW struct
     300                 :            :  * @params: parameters for the table to be created
     301                 :            :  *
     302                 :            :  * Create a LEM table for ACL usage. We are currently starting with some fixed
     303                 :            :  * values for the size of the table, but this will need to grow as more flow
     304                 :            :  * entries are added by the user level.
     305                 :            :  */
     306                 :            : enum ice_status
     307                 :          0 : ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params)
     308                 :            : {
     309                 :            :         u16 width, depth, first_e, last_e, i;
     310                 :            :         struct ice_aqc_acl_generic *resp_buf;
     311                 :            :         struct ice_acl_alloc_tbl tbl_alloc;
     312                 :            :         struct ice_acl_tbl *tbl;
     313                 :            :         enum ice_status status;
     314                 :            : 
     315         [ #  # ]:          0 :         if (hw->acl_tbl)
     316                 :            :                 return ICE_ERR_ALREADY_EXISTS;
     317                 :            : 
     318         [ #  # ]:          0 :         if (!params)
     319                 :            :                 return ICE_ERR_PARAM;
     320                 :            : 
     321                 :            :         /* round up the width to the next TCAM width boundary. */
     322                 :          0 :         width = ROUND_UP(params->width, (u16)ICE_AQC_ACL_KEY_WIDTH_BYTES);
     323                 :            :         /* depth should be provided in chunk (64 entry) increments */
     324                 :          0 :         depth = ICE_ALIGN(params->depth, ICE_ACL_ENTRY_ALLOC_UNIT);
     325                 :            : 
     326         [ #  # ]:          0 :         if (params->entry_act_pairs < width / ICE_AQC_ACL_KEY_WIDTH_BYTES) {
     327                 :          0 :                 params->entry_act_pairs =
     328                 :          0 :                         (u8)(width / ICE_AQC_ACL_KEY_WIDTH_BYTES);
     329                 :            : 
     330         [ #  # ]:          0 :                 if (params->entry_act_pairs > ICE_AQC_TBL_MAX_ACTION_PAIRS)
     331                 :          0 :                         params->entry_act_pairs = ICE_AQC_TBL_MAX_ACTION_PAIRS;
     332                 :            :         }
     333                 :            : 
     334                 :            :         /* Validate that width*depth will not exceed the TCAM limit */
     335                 :          0 :         if ((DIVIDE_AND_ROUND_UP(depth, ICE_AQC_ACL_TCAM_DEPTH) *
     336         [ #  # ]:          0 :              (width / ICE_AQC_ACL_KEY_WIDTH_BYTES)) > ICE_AQC_ACL_SLICES)
     337                 :            :                 return ICE_ERR_MAX_LIMIT;
     338                 :            : 
     339                 :            :         ice_memset(&tbl_alloc, 0, sizeof(tbl_alloc), ICE_NONDMA_MEM);
     340                 :          0 :         tbl_alloc.width = width;
     341                 :          0 :         tbl_alloc.depth = depth;
     342                 :          0 :         tbl_alloc.act_pairs_per_entry = params->entry_act_pairs;
     343                 :          0 :         tbl_alloc.concurr = params->concurr;
     344                 :            :         /* Set dependent_alloc_id only for concurrent table type */
     345         [ #  # ]:          0 :         if (params->concurr) {
     346                 :          0 :                 tbl_alloc.num_dependent_alloc_ids =
     347                 :            :                         ICE_AQC_MAX_CONCURRENT_ACL_TBL;
     348                 :            : 
     349         [ #  # ]:          0 :                 for (i = 0; i < ICE_AQC_MAX_CONCURRENT_ACL_TBL; i++)
     350                 :          0 :                         tbl_alloc.buf.data_buf.alloc_ids[i] =
     351                 :          0 :                                 CPU_TO_LE16(params->dep_tbls[i]);
     352                 :            :         }
     353                 :            : 
     354                 :            :         /* call the AQ command to create the ACL table with these values */
     355                 :          0 :         status = ice_aq_alloc_acl_tbl(hw, &tbl_alloc, NULL);
     356         [ #  # ]:          0 :         if (status) {
     357         [ #  # ]:          0 :                 if (LE16_TO_CPU(tbl_alloc.buf.resp_buf.alloc_id) <
     358                 :            :                     ICE_AQC_ALLOC_ID_LESS_THAN_4K)
     359         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "Alloc ACL table failed. Unavailable resource.\n");
     360                 :            :                 else
     361         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "AQ allocation of ACL failed with error. status: %d\n",
     362                 :            :                                   status);
     363                 :          0 :                 return status;
     364                 :            :         }
     365                 :            : 
     366                 :          0 :         tbl = (struct ice_acl_tbl *)ice_malloc(hw, sizeof(*tbl));
     367         [ #  # ]:          0 :         if (!tbl) {
     368                 :            :                 status = ICE_ERR_NO_MEMORY;
     369                 :            : 
     370                 :          0 :                 goto out;
     371                 :            :         }
     372                 :            : 
     373                 :            :         resp_buf = &tbl_alloc.buf.resp_buf;
     374                 :            : 
     375                 :            :         /* Retrieve information of the allocated table */
     376                 :          0 :         tbl->id = LE16_TO_CPU(resp_buf->alloc_id);
     377                 :          0 :         tbl->first_tcam = resp_buf->ops.table.first_tcam;
     378                 :          0 :         tbl->last_tcam = resp_buf->ops.table.last_tcam;
     379                 :          0 :         tbl->first_entry = LE16_TO_CPU(resp_buf->first_entry);
     380                 :          0 :         tbl->last_entry = LE16_TO_CPU(resp_buf->last_entry);
     381                 :            : 
     382                 :          0 :         tbl->info = *params;
     383                 :          0 :         tbl->info.width = width;
     384                 :          0 :         tbl->info.depth = depth;
     385                 :          0 :         hw->acl_tbl = tbl;
     386                 :            : 
     387         [ #  # ]:          0 :         for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)
     388                 :          0 :                 tbl->act_mems[i].act_mem = resp_buf->act_mem[i];
     389                 :            : 
     390                 :            :         /* Figure out which TCAMs that these newly allocated action memories
     391                 :            :          * belong to.
     392                 :            :          */
     393                 :          0 :         ice_acl_divide_act_mems_to_tcams(tbl);
     394                 :            : 
     395                 :            :         /* Initialize the resources allocated by invalidating all TCAM entries
     396                 :            :          * and all the action pairs
     397                 :            :          */
     398                 :          0 :         status = ice_acl_init_tbl(hw);
     399         [ #  # ]:          0 :         if (status) {
     400                 :          0 :                 ice_free(hw, tbl);
     401                 :          0 :                 hw->acl_tbl = NULL;
     402         [ #  # ]:          0 :                 ice_debug(hw, ICE_DBG_ACL, "Initialization of TCAM entries failed. status: %d\n",
     403                 :            :                           status);
     404                 :          0 :                 goto out;
     405                 :            :         }
     406                 :            : 
     407                 :          0 :         first_e = (tbl->first_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +
     408                 :          0 :                 (tbl->first_entry / ICE_ACL_ENTRY_ALLOC_UNIT);
     409                 :          0 :         last_e = (tbl->last_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +
     410                 :          0 :                 (tbl->last_entry / ICE_ACL_ENTRY_ALLOC_UNIT);
     411                 :            : 
     412                 :            :         /* Indicate available entries in the table */
     413                 :          0 :         ice_bitmap_set(tbl->avail, first_e, last_e - first_e + 1);
     414                 :            : 
     415                 :          0 :         INIT_LIST_HEAD(&tbl->scens);
     416                 :            : out:
     417                 :            : 
     418                 :            :         return status;
     419                 :            : }
     420                 :            : 
     421                 :            : /**
     422                 :            :  * ice_acl_alloc_partition - Allocate a partition from the ACL table
     423                 :            :  * @hw: pointer to the hardware structure
     424                 :            :  * @req: info of partition being allocated
     425                 :            :  */
     426                 :            : static enum ice_status
     427                 :          0 : ice_acl_alloc_partition(struct ice_hw *hw, struct ice_acl_scen *req)
     428                 :            : {
     429                 :            :         u16 start = 0, cnt = 0, off = 0;
     430                 :            :         u16 width, r_entries, row;
     431                 :            :         bool done = false;
     432                 :            :         int dir;
     433                 :            : 
     434                 :            :         /* Determine the number of TCAMs each entry overlaps */
     435                 :          0 :         width = DIVIDE_AND_ROUND_UP(req->width, ICE_AQC_ACL_KEY_WIDTH_BYTES);
     436                 :            : 
     437                 :            :         /* Check if we have enough TCAMs to accommodate the width */
     438         [ #  # ]:          0 :         if (width > hw->acl_tbl->last_tcam - hw->acl_tbl->first_tcam + 1)
     439                 :            :                 return ICE_ERR_MAX_LIMIT;
     440                 :            : 
     441                 :            :         /* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */
     442                 :          0 :         r_entries = ICE_ALIGN(req->num_entry, ICE_ACL_ENTRY_ALLOC_UNIT);
     443                 :            : 
     444                 :            :         /* To look for an available partition that can accommodate the request,
     445                 :            :          * the process first logically arranges available TCAMs in rows such
     446                 :            :          * that each row produces entries with the requested width. It then
     447                 :            :          * scans the TCAMs' available bitmap, one bit at a time, and
     448                 :            :          * accumulates contiguous available 64-entry chunks until there are
     449                 :            :          * enough of them or when all TCAM configurations have been checked.
     450                 :            :          *
     451                 :            :          * For width of 1 TCAM, the scanning process starts from the top most
     452                 :            :          * TCAM, and goes downward. Available bitmaps are examined from LSB
     453                 :            :          * to MSB.
     454                 :            :          *
     455                 :            :          * For width of multiple TCAMs, the process starts from the bottom-most
     456                 :            :          * row of TCAMs, and goes upward. Available bitmaps are examined from
     457                 :            :          * the MSB to the LSB.
     458                 :            :          *
     459                 :            :          * To make sure that adjacent TCAMs can be logically arranged in the
     460                 :            :          * same row, the scanning process may have multiple passes. In each
     461                 :            :          * pass, the first TCAM of the bottom-most row is displaced by one
     462                 :            :          * additional TCAM. The width of the row and the number of the TCAMs
     463                 :            :          * available determine the number of passes. When the displacement is
     464                 :            :          * more than the size of width, the TCAM row configurations will
     465                 :            :          * repeat. The process will terminate when the configurations repeat.
     466                 :            :          *
     467                 :            :          * Available partitions can span more than one row of TCAMs.
     468                 :            :          */
     469         [ #  # ]:          0 :         if (width == 1) {
     470                 :          0 :                 row = hw->acl_tbl->first_tcam;
     471                 :            :                 dir = 1;
     472                 :            :         } else {
     473                 :            :                 /* Start with the bottom-most row, and scan for available
     474                 :            :                  * entries upward
     475                 :            :                  */
     476                 :          0 :                 row = hw->acl_tbl->last_tcam + 1 - width;
     477                 :            :                 dir = -1;
     478                 :            :         }
     479                 :            : 
     480                 :            :         do {
     481                 :            :                 u16 i;
     482                 :            : 
     483                 :            :                 /* Scan all 64-entry chunks, one chunk at a time, in the
     484                 :            :                  * current TCAM row
     485                 :            :                  */
     486                 :          0 :                 for (i = 0;
     487         [ #  # ]:          0 :                      i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries;
     488                 :          0 :                      i++) {
     489                 :            :                         bool avail = true;
     490                 :            :                         u16 w, p;
     491                 :            : 
     492                 :            :                         /* Compute the cumulative available mask across the
     493                 :            :                          * TCAM row to determine if the current 64-entry chunk
     494                 :            :                          * is available.
     495                 :            :                          */
     496         [ #  # ]:          0 :                         p = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1;
     497   [ #  #  #  # ]:          0 :                         for (w = row; w < row + width && avail; w++) {
     498                 :            :                                 u16 b;
     499                 :            : 
     500                 :          0 :                                 b = (w * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + p;
     501                 :          0 :                                 avail &= ice_is_bit_set(hw->acl_tbl->avail, b);
     502                 :            :                         }
     503                 :            : 
     504         [ #  # ]:          0 :                         if (!avail) {
     505                 :            :                                 cnt = 0;
     506                 :            :                         } else {
     507                 :            :                                 /* Compute the starting index of the newly
     508                 :            :                                  * found partition. When 'dir' is negative, the
     509                 :            :                                  * scan processes is going upward. If so, the
     510                 :            :                                  * starting index needs to be updated for every
     511                 :            :                                  * available 64-entry chunk found.
     512                 :            :                                  */
     513         [ #  # ]:          0 :                                 if (!cnt || dir < 0)
     514                 :          0 :                                         start = (row * ICE_AQC_ACL_TCAM_DEPTH) +
     515                 :            :                                                 (p * ICE_ACL_ENTRY_ALLOC_UNIT);
     516                 :          0 :                                 cnt += ICE_ACL_ENTRY_ALLOC_UNIT;
     517                 :            :                         }
     518                 :            :                 }
     519                 :            : 
     520         [ #  # ]:          0 :                 if (cnt >= r_entries) {
     521                 :          0 :                         req->start = start;
     522         [ #  # ]:          0 :                         req->num_entry = r_entries;
     523                 :          0 :                         req->end = ice_acl_tbl_calc_end_idx(start, r_entries,
     524                 :            :                                                             width);
     525                 :          0 :                         break;
     526                 :            :                 }
     527                 :            : 
     528         [ #  # ]:          0 :                 row = dir > 0 ? row + width : row - width;
     529         [ #  # ]:          0 :                 if (row > hw->acl_tbl->last_tcam ||
     530         [ #  # ]:          0 :                     row < hw->acl_tbl->first_tcam) {
     531                 :            :                         /* All rows have been checked. Increment 'off' that
     532                 :            :                          * will help yield a different TCAM configuration in
     533                 :            :                          * which adjacent TCAMs can be alternatively in the
     534                 :            :                          * same row.
     535                 :            :                          */
     536                 :          0 :                         off++;
     537                 :            : 
     538                 :            :                         /* However, if the new 'off' value yields previously
     539                 :            :                          * checked configurations, then exit.
     540                 :            :                          */
     541         [ #  # ]:          0 :                         if (off >= width)
     542                 :            :                                 done = true;
     543                 :            :                         else
     544         [ #  # ]:          0 :                                 row = dir > 0 ? off :
     545                 :          0 :                                         hw->acl_tbl->last_tcam + 1 - off -
     546                 :            :                                         width;
     547                 :            :                 }
     548         [ #  # ]:          0 :         } while (!done);
     549                 :            : 
     550         [ #  # ]:          0 :         return cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT;
     551                 :            : }
     552                 :            : 
     553                 :            : /**
     554                 :            :  * ice_acl_fill_tcam_select
     555                 :            :  * @scen_buf: Pointer to the scenario buffer that needs to be populated
     556                 :            :  * @scen: Pointer to the available space for the scenario
     557                 :            :  * @tcam_idx: Index of the TCAM used for this scenario
     558                 :            :  * @tcam_idx_in_cascade : Local index of the TCAM in the cascade scenario
     559                 :            :  *
     560                 :            :  * For all TCAM that participate in this scenario, fill out the tcam_select
     561                 :            :  * value.
     562                 :            :  */
     563                 :            : static void
     564                 :          0 : ice_acl_fill_tcam_select(struct ice_aqc_acl_scen *scen_buf,
     565                 :            :                          struct ice_acl_scen *scen, u16 tcam_idx,
     566                 :            :                          u16 tcam_idx_in_cascade)
     567                 :            : {
     568                 :            :         u16 cascade_cnt, idx;
     569                 :            :         u8 j;
     570                 :            : 
     571                 :          0 :         idx = tcam_idx_in_cascade * ICE_AQC_ACL_KEY_WIDTH_BYTES;
     572                 :          0 :         cascade_cnt = DIVIDE_AND_ROUND_UP(scen->width,
     573                 :            :                                           ICE_AQC_ACL_KEY_WIDTH_BYTES);
     574                 :            : 
     575                 :            :         /* For each scenario, we reserved last three bytes of scenario width for
     576                 :            :          * profile ID, range checker, and packet direction. Thus, the last three
     577                 :            :          * bytes of the last cascaded TCAMs will have value of 1st, 31st and
     578                 :            :          * 32nd byte location of BYTE selection base.
     579                 :            :          *
     580                 :            :          * For other bytes in the TCAMs:
     581                 :            :          * For non-cascade mode (1 TCAM wide) scenario, TCAM[x]'s Select {0-1}
     582                 :            :          * select indices 0-1 of the Byte Selection Base
     583                 :            :          * For cascade mode, the leftmost TCAM of the first cascade row selects
     584                 :            :          * indices 0-4 of the Byte Selection Base; the second TCAM in the
     585                 :            :          * cascade row selects indices starting with 5-n
     586                 :            :          */
     587         [ #  # ]:          0 :         for (j = 0; j < ICE_AQC_ACL_KEY_WIDTH_BYTES; j++) {
     588                 :            :                 /* PKT DIR uses the 1st location of Byte Selection Base: + 1 */
     589                 :          0 :                 u8 val = (u8)(ICE_AQC_ACL_BYTE_SEL_BASE + 1 + idx);
     590                 :            : 
     591         [ #  # ]:          0 :                 if (tcam_idx_in_cascade == cascade_cnt - 1) {
     592                 :            :                         if (j == ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM)
     593                 :            :                                 val = ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK;
     594                 :            :                         else if (j == ICE_ACL_SCEN_PID_IDX_IN_TCAM)
     595                 :            :                                 val = ICE_AQC_ACL_BYTE_SEL_BASE_PID;
     596                 :            :                         else if (j == ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM)
     597                 :            :                                 val = ICE_AQC_ACL_BYTE_SEL_BASE_PKT_DIR;
     598                 :            :                 }
     599                 :            : 
     600                 :            :                 /* In case that scenario's width is greater than the width of
     601                 :            :                  * the Byte selection base, we will not assign a value to the
     602                 :            :                  * tcam_select[j]. As a result, the tcam_select[j] will have
     603                 :            :                  * default value which is zero.
     604                 :            :                  */
     605         [ #  # ]:          0 :                 if (val > ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK)
     606                 :          0 :                         continue;
     607                 :            : 
     608                 :          0 :                 scen_buf->tcam_cfg[tcam_idx].tcam_select[j] = val;
     609                 :            : 
     610                 :          0 :                 idx++;
     611                 :            :         }
     612                 :          0 : }
     613                 :            : 
     614                 :            : /**
     615                 :            :  * ice_acl_set_scen_chnk_msk
     616                 :            :  * @scen_buf: Pointer to the scenario buffer that needs to be populated
     617                 :            :  * @scen: pointer to the available space for the scenario
     618                 :            :  *
     619                 :            :  * Set the chunk mask for the entries that will be used by this scenario
     620                 :            :  */
     621                 :            : static void
     622                 :          0 : ice_acl_set_scen_chnk_msk(struct ice_aqc_acl_scen *scen_buf,
     623                 :            :                           struct ice_acl_scen *scen)
     624                 :            : {
     625                 :            :         u16 tcam_idx, num_cscd, units, cnt;
     626                 :            :         u8 chnk_offst;
     627                 :            : 
     628                 :            :         /* Determine the starting TCAM index and offset of the start entry */
     629                 :          0 :         tcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start);
     630                 :          0 :         chnk_offst = (u8)((scen->start % ICE_AQC_ACL_TCAM_DEPTH) /
     631                 :            :                           ICE_ACL_ENTRY_ALLOC_UNIT);
     632                 :            : 
     633                 :            :         /* Entries are allocated and tracked in multiple of 64's */
     634                 :          0 :         units = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT;
     635                 :            : 
     636                 :            :         /* Determine number of cascaded TCAMs */
     637                 :          0 :         num_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES;
     638                 :            : 
     639         [ #  # ]:          0 :         for (cnt = 0; cnt < units; cnt++) {
     640                 :            :                 u16 i;
     641                 :            : 
     642                 :            :                 /* Set the corresponding bitmap of individual 64-entry
     643                 :            :                  * chunk spans across a cascade of 1 or more TCAMs
     644                 :            :                  * For each TCAM, there will be (ICE_AQC_ACL_TCAM_DEPTH
     645                 :            :                  * / ICE_ACL_ENTRY_ALLOC_UNIT) or 8 chunks.
     646                 :            :                  */
     647         [ #  # ]:          0 :                 for (i = tcam_idx; i < tcam_idx + num_cscd; i++)
     648                 :          0 :                         scen_buf->tcam_cfg[i].chnk_msk |= BIT(chnk_offst);
     649                 :            : 
     650                 :          0 :                 chnk_offst = (chnk_offst + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS;
     651         [ #  # ]:          0 :                 if (!chnk_offst)
     652                 :          0 :                         tcam_idx += num_cscd;
     653                 :            :         }
     654                 :          0 : }
     655                 :            : 
     656                 :            : /**
     657                 :            :  * ice_acl_assign_act_mem_for_scen
     658                 :            :  * @tbl: pointer to ACL table structure
     659                 :            :  * @scen: pointer to the scenario struct
     660                 :            :  * @scen_buf: pointer to the available space for the scenario
     661                 :            :  * @current_tcam_idx: theoretical index of the TCAM that we associated those
     662                 :            :  *                    action memory banks with, at the table creation time.
     663                 :            :  * @target_tcam_idx: index of the TCAM that we want to associate those action
     664                 :            :  *                   memory banks with.
     665                 :            :  */
     666                 :            : static void
     667                 :            : ice_acl_assign_act_mem_for_scen(struct ice_acl_tbl *tbl,
     668                 :            :                                 struct ice_acl_scen *scen,
     669                 :            :                                 struct ice_aqc_acl_scen *scen_buf,
     670                 :            :                                 u8 current_tcam_idx, u8 target_tcam_idx)
     671                 :            : {
     672                 :            :         u8 i;
     673                 :            : 
     674         [ #  # ]:          0 :         for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) {
     675                 :          0 :                 struct ice_acl_act_mem *p_mem = &tbl->act_mems[i];
     676                 :            : 
     677         [ #  # ]:          0 :                 if (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL ||
     678         [ #  # ]:          0 :                     p_mem->member_of_tcam != current_tcam_idx)
     679                 :          0 :                         continue;
     680                 :            : 
     681                 :            :                 scen_buf->act_mem_cfg[i] = target_tcam_idx;
     682                 :          0 :                 scen_buf->act_mem_cfg[i] |= ICE_AQC_ACL_SCE_ACT_MEM_EN;
     683                 :            :                 ice_set_bit(i, scen->act_mem_bitmap);
     684                 :            :         }
     685                 :            : }
     686                 :            : 
     687                 :            : /**
     688                 :            :  * ice_acl_commit_partition - Indicate if the specified partition is active
     689                 :            :  * @hw: pointer to the hardware structure
     690                 :            :  * @scen: pointer to the scenario struct
     691                 :            :  * @commit: true if the partition is being commit
     692                 :            :  */
     693                 :            : static void
     694                 :          0 : ice_acl_commit_partition(struct ice_hw *hw, struct ice_acl_scen *scen,
     695                 :            :                          bool commit)
     696                 :            : {
     697                 :            :         u16 tcam_idx, off, num_cscd, units, cnt;
     698                 :            : 
     699                 :            :         /* Determine the starting TCAM index and offset of the start entry */
     700                 :          0 :         tcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start);
     701                 :          0 :         off = (scen->start % ICE_AQC_ACL_TCAM_DEPTH) /
     702                 :            :                 ICE_ACL_ENTRY_ALLOC_UNIT;
     703                 :            : 
     704                 :            :         /* Entries are allocated and tracked in multiple of 64's */
     705                 :          0 :         units = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT;
     706                 :            : 
     707                 :            :         /* Determine number of cascaded TCAM */
     708                 :          0 :         num_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES;
     709                 :            : 
     710         [ #  # ]:          0 :         for (cnt = 0; cnt < units; cnt++) {
     711                 :            :                 u16 w;
     712                 :            : 
     713                 :            :                 /* Set/clear the corresponding bitmap of individual 64-entry
     714                 :            :                  * chunk spans across a row of 1 or more TCAMs
     715                 :            :                  */
     716         [ #  # ]:          0 :                 for (w = 0; w < num_cscd; w++) {
     717                 :            :                         u16 b;
     718                 :            : 
     719                 :          0 :                         b = ((tcam_idx + w) * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +
     720                 :            :                                 off;
     721         [ #  # ]:          0 :                         if (commit)
     722                 :          0 :                                 ice_set_bit(b, hw->acl_tbl->avail);
     723                 :            :                         else
     724                 :          0 :                                 ice_clear_bit(b, hw->acl_tbl->avail);
     725                 :            :                 }
     726                 :            : 
     727                 :          0 :                 off = (off + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS;
     728         [ #  # ]:          0 :                 if (!off)
     729                 :          0 :                         tcam_idx += num_cscd;
     730                 :            :         }
     731                 :          0 : }
     732                 :            : 
     733                 :            : /**
     734                 :            :  * ice_acl_create_scen
     735                 :            :  * @hw: pointer to the hardware structure
     736                 :            :  * @match_width: number of bytes to be matched in this scenario
     737                 :            :  * @num_entries: number of entries to be allocated for the scenario
     738                 :            :  * @scen_id: holds returned scenario ID if successful
     739                 :            :  */
     740                 :            : enum ice_status
     741                 :          0 : ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries,
     742                 :            :                     u16 *scen_id)
     743                 :            : {
     744                 :            :         u8 cascade_cnt, first_tcam, last_tcam, i, k;
     745                 :            :         struct ice_aqc_acl_scen scen_buf;
     746                 :            :         struct ice_acl_scen *scen;
     747                 :            :         enum ice_status status;
     748                 :            : 
     749         [ #  # ]:          0 :         if (!hw->acl_tbl)
     750                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
     751                 :            : 
     752                 :          0 :         scen = (struct ice_acl_scen *)ice_malloc(hw, sizeof(*scen));
     753         [ #  # ]:          0 :         if (!scen)
     754                 :            :                 return ICE_ERR_NO_MEMORY;
     755                 :            : 
     756                 :          0 :         scen->start = hw->acl_tbl->first_entry;
     757                 :          0 :         scen->width = ICE_AQC_ACL_KEY_WIDTH_BYTES *
     758                 :          0 :                 DIVIDE_AND_ROUND_UP(match_width, ICE_AQC_ACL_KEY_WIDTH_BYTES);
     759                 :          0 :         scen->num_entry = num_entries;
     760                 :            : 
     761                 :          0 :         status = ice_acl_alloc_partition(hw, scen);
     762         [ #  # ]:          0 :         if (status)
     763                 :          0 :                 goto out;
     764                 :            : 
     765                 :            :         ice_memset(&scen_buf, 0, sizeof(scen_buf), ICE_NONDMA_MEM);
     766                 :            : 
     767                 :            :         /* Determine the number of cascade TCAMs, given the scenario's width */
     768                 :          0 :         cascade_cnt = DIVIDE_AND_ROUND_UP(scen->width,
     769                 :            :                                           ICE_AQC_ACL_KEY_WIDTH_BYTES);
     770                 :          0 :         first_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);
     771                 :          0 :         last_tcam = ICE_ACL_TBL_TCAM_IDX(scen->end);
     772                 :            : 
     773                 :            :         /* For each scenario, we reserved last three bytes of scenario width for
     774                 :            :          * packet direction flag, profile ID and range checker. Thus, we want to
     775                 :            :          * return back to the caller the eff_width, pkt_dir_idx, rng_chk_idx and
     776                 :            :          * pid_idx.
     777                 :            :          */
     778                 :          0 :         scen->eff_width = cascade_cnt * ICE_AQC_ACL_KEY_WIDTH_BYTES -
     779                 :            :                 ICE_ACL_SCEN_MIN_WIDTH;
     780                 :          0 :         scen->rng_chk_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +
     781                 :            :                 ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM;
     782                 :          0 :         scen->pid_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +
     783                 :            :                 ICE_ACL_SCEN_PID_IDX_IN_TCAM;
     784                 :          0 :         scen->pkt_dir_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +
     785                 :            :                 ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM;
     786                 :            : 
     787                 :            :         /* set the chunk mask for the tcams */
     788                 :          0 :         ice_acl_set_scen_chnk_msk(&scen_buf, scen);
     789                 :            : 
     790                 :            :         /* set the TCAM select and start_cmp and start_set bits */
     791                 :            :         k = first_tcam;
     792                 :            :         /* set the START_SET bit at the beginning of the stack */
     793                 :          0 :         scen_buf.tcam_cfg[k].start_cmp_set |= ICE_AQC_ACL_ALLOC_SCE_START_SET;
     794         [ #  # ]:          0 :         while (k <= last_tcam) {
     795                 :          0 :                 u16 last_tcam_idx_cascade = cascade_cnt + k - 1;
     796                 :            : 
     797                 :            :                 /* set start_cmp for the first cascaded TCAM */
     798                 :          0 :                 scen_buf.tcam_cfg[k].start_cmp_set |=
     799                 :            :                         ICE_AQC_ACL_ALLOC_SCE_START_CMP;
     800                 :            : 
     801                 :            :                 /* cascade TCAMs up to the width of the scenario */
     802         [ #  # ]:          0 :                 for (i = k; i < cascade_cnt + k; i++) {
     803                 :          0 :                         ice_acl_fill_tcam_select(&scen_buf, scen, i, i - k);
     804                 :          0 :                         ice_acl_assign_act_mem_for_scen(hw->acl_tbl, scen,
     805                 :            :                                                         &scen_buf,
     806                 :            :                                                         i,
     807                 :            :                                                         last_tcam_idx_cascade);
     808                 :            :                 }
     809                 :            : 
     810                 :            :                 k = i;
     811                 :            :         }
     812                 :            : 
     813                 :            :         /* We need to set the start_cmp bit for the unused TCAMs. */
     814                 :            :         i = 0;
     815         [ #  # ]:          0 :         while (i < first_tcam)
     816                 :          0 :                 scen_buf.tcam_cfg[i++].start_cmp_set =
     817                 :            :                                         ICE_AQC_ACL_ALLOC_SCE_START_CMP;
     818                 :            : 
     819                 :          0 :         i = last_tcam + 1;
     820         [ #  # ]:          0 :         while (i < ICE_AQC_ACL_SLICES)
     821                 :          0 :                 scen_buf.tcam_cfg[i++].start_cmp_set =
     822                 :            :                                         ICE_AQC_ACL_ALLOC_SCE_START_CMP;
     823                 :            : 
     824                 :          0 :         status = ice_aq_alloc_acl_scen(hw, scen_id, &scen_buf, NULL);
     825         [ #  # ]:          0 :         if (status) {
     826         [ #  # ]:          0 :                 ice_debug(hw, ICE_DBG_ACL, "AQ allocation of ACL scenario failed. status: %d\n",
     827                 :            :                           status);
     828                 :          0 :                 goto out;
     829                 :            :         }
     830                 :            : 
     831                 :          0 :         scen->id = *scen_id;
     832                 :          0 :         ice_acl_commit_partition(hw, scen, false);
     833                 :            :         ice_acl_init_entry(scen);
     834         [ #  # ]:          0 :         LIST_ADD(&scen->list_entry, &hw->acl_tbl->scens);
     835                 :            : 
     836                 :          0 : out:
     837         [ #  # ]:          0 :         if (status)
     838                 :          0 :                 ice_free(hw, scen);
     839                 :            : 
     840                 :            :         return status;
     841                 :            : }
     842                 :            : 
     843                 :            : /**
     844                 :            :  * ice_acl_destroy_scen - Destroy an ACL scenario
     845                 :            :  * @hw: pointer to the HW struct
     846                 :            :  * @scen_id: ID of the remove scenario
     847                 :            :  */
     848                 :          0 : static enum ice_status ice_acl_destroy_scen(struct ice_hw *hw, u16 scen_id)
     849                 :            : {
     850                 :            :         struct ice_acl_scen *scen, *tmp_scen;
     851                 :            :         struct ice_flow_prof *p, *tmp;
     852                 :            :         enum ice_status status;
     853                 :            : 
     854         [ #  # ]:          0 :         if (!hw->acl_tbl)
     855                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
     856                 :            : 
     857                 :            :         /* Remove profiles that use "scen_id" scenario */
     858   [ #  #  #  #  :          0 :         LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[ICE_BLK_ACL],
          #  #  #  #  #  
                      # ]
     859                 :            :                                  ice_flow_prof, l_entry)
     860   [ #  #  #  # ]:          0 :                 if (p->cfg.scen && p->cfg.scen->id == scen_id) {
     861                 :          0 :                         status = ice_flow_rem_prof(hw, ICE_BLK_ACL, p->id);
     862         [ #  # ]:          0 :                         if (status) {
     863         [ #  # ]:          0 :                                 ice_debug(hw, ICE_DBG_ACL, "ice_flow_rem_prof failed. status: %d\n",
     864                 :            :                                           status);
     865                 :          0 :                                 return status;
     866                 :            :                         }
     867                 :            :                 }
     868                 :            : 
     869                 :            :         /* Call the AQ command to destroy the targeted scenario */
     870                 :          0 :         status = ice_aq_dealloc_acl_scen(hw, scen_id, NULL);
     871         [ #  # ]:          0 :         if (status) {
     872         [ #  # ]:          0 :                 ice_debug(hw, ICE_DBG_ACL, "AQ de-allocation of scenario failed. status: %d\n",
     873                 :            :                           status);
     874                 :          0 :                 return status;
     875                 :            :         }
     876                 :            : 
     877                 :            :         /* Remove scenario from hw->acl_tbl->scens */
     878   [ #  #  #  #  :          0 :         LIST_FOR_EACH_ENTRY_SAFE(scen, tmp_scen, &hw->acl_tbl->scens,
          #  #  #  #  #  
                      # ]
     879                 :            :                                  ice_acl_scen, list_entry)
     880         [ #  # ]:          0 :                 if (scen->id == scen_id) {
     881         [ #  # ]:          0 :                         LIST_DEL(&scen->list_entry);
     882                 :          0 :                         ice_free(hw, scen);
     883                 :            :                 }
     884                 :            : 
     885                 :            :         return ICE_SUCCESS;
     886                 :            : }
     887                 :            : 
     888                 :            : /**
     889                 :            :  * ice_acl_destroy_tbl - Destroy a previously created LEM table for ACL
     890                 :            :  * @hw: pointer to the HW struct
     891                 :            :  */
     892                 :          0 : enum ice_status ice_acl_destroy_tbl(struct ice_hw *hw)
     893                 :            : {
     894                 :            :         struct ice_acl_scen *pos_scen, *tmp_scen;
     895                 :            :         struct ice_aqc_acl_generic resp_buf;
     896                 :            :         struct ice_aqc_acl_scen buf;
     897                 :            :         enum ice_status status;
     898                 :            :         u8 i;
     899                 :            : 
     900         [ #  # ]:          0 :         if (!hw->acl_tbl)
     901                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
     902                 :            : 
     903                 :            :         /* Mark all the created scenario's TCAM to stop the packet lookup and
     904                 :            :          * delete them afterward
     905                 :            :          */
     906   [ #  #  #  #  :          0 :         LIST_FOR_EACH_ENTRY_SAFE(pos_scen, tmp_scen, &hw->acl_tbl->scens,
          #  #  #  #  #  
                      # ]
     907                 :            :                                  ice_acl_scen, list_entry) {
     908                 :          0 :                 status = ice_aq_query_acl_scen(hw, pos_scen->id, &buf, NULL);
     909         [ #  # ]:          0 :                 if (status) {
     910         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "ice_aq_query_acl_scen() failed. status: %d\n",
     911                 :            :                                   status);
     912                 :          0 :                         return status;
     913                 :            :                 }
     914                 :            : 
     915         [ #  # ]:          0 :                 for (i = 0; i < ICE_AQC_ACL_SLICES; i++) {
     916                 :          0 :                         buf.tcam_cfg[i].chnk_msk = 0;
     917                 :          0 :                         buf.tcam_cfg[i].start_cmp_set =
     918                 :            :                                         ICE_AQC_ACL_ALLOC_SCE_START_CMP;
     919                 :            :                 }
     920                 :            : 
     921         [ #  # ]:          0 :                 for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)
     922                 :          0 :                         buf.act_mem_cfg[i] = 0;
     923                 :            : 
     924                 :          0 :                 status = ice_aq_update_acl_scen(hw, pos_scen->id, &buf, NULL);
     925         [ #  # ]:          0 :                 if (status) {
     926         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "ice_aq_update_acl_scen() failed. status: %d\n",
     927                 :            :                                   status);
     928                 :          0 :                         return status;
     929                 :            :                 }
     930                 :            : 
     931                 :          0 :                 status = ice_acl_destroy_scen(hw, pos_scen->id);
     932         [ #  # ]:          0 :                 if (status) {
     933         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "deletion of scenario failed. status: %d\n",
     934                 :            :                                   status);
     935                 :          0 :                         return status;
     936                 :            :                 }
     937                 :            :         }
     938                 :            : 
     939                 :            :         /* call the AQ command to destroy the ACL table */
     940                 :          0 :         status = ice_aq_dealloc_acl_tbl(hw, hw->acl_tbl->id, &resp_buf, NULL);
     941         [ #  # ]:          0 :         if (status) {
     942         [ #  # ]:          0 :                 ice_debug(hw, ICE_DBG_ACL, "AQ de-allocation of ACL failed. status: %d\n",
     943                 :            :                           status);
     944                 :          0 :                 return status;
     945                 :            :         }
     946                 :            : 
     947                 :          0 :         ice_free(hw, hw->acl_tbl);
     948                 :          0 :         hw->acl_tbl = NULL;
     949                 :            : 
     950                 :          0 :         return ICE_SUCCESS;
     951                 :            : }
     952                 :            : 
     953                 :            : /**
     954                 :            :  * ice_acl_add_entry - Add a flow entry to an ACL scenario
     955                 :            :  * @hw: pointer to the HW struct
     956                 :            :  * @scen: scenario to add the entry to
     957                 :            :  * @prio: priority level of the entry being added
     958                 :            :  * @keys: buffer of the value of the key to be programmed to the ACL entry
     959                 :            :  * @inverts: buffer of the value of the key inverts to be programmed
     960                 :            :  * @acts: pointer to a buffer containing formatted actions
     961                 :            :  * @acts_cnt: indicates the number of actions stored in "acts"
     962                 :            :  * @entry_idx: returned scenario relative index of the added flow entry
     963                 :            :  *
     964                 :            :  * Given an ACL table and a scenario, to add the specified key and key invert
     965                 :            :  * to an available entry in the specified scenario.
     966                 :            :  * The "keys" and "inverts" buffers must be of the size which is the same as
     967                 :            :  * the scenario's width
     968                 :            :  */
     969                 :            : enum ice_status
     970                 :          0 : ice_acl_add_entry(struct ice_hw *hw, struct ice_acl_scen *scen,
     971                 :            :                   enum ice_acl_entry_prio prio, u8 *keys, u8 *inverts,
     972                 :            :                   struct ice_acl_act_entry *acts, u8 acts_cnt, u16 *entry_idx)
     973                 :            : {
     974                 :            :         struct ice_aqc_acl_data buf;
     975                 :            :         u8 entry_tcam, offset;
     976                 :            :         u16 i, num_cscd, idx;
     977                 :            :         enum ice_status status = ICE_SUCCESS;
     978                 :            : 
     979         [ #  # ]:          0 :         if (!scen)
     980                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
     981                 :            : 
     982                 :          0 :         *entry_idx = ice_acl_scen_assign_entry_idx(scen, prio);
     983         [ #  # ]:          0 :         if (*entry_idx >= scen->num_entry) {
     984                 :          0 :                 *entry_idx = 0;
     985                 :          0 :                 return ICE_ERR_MAX_LIMIT;
     986                 :            :         }
     987                 :            : 
     988                 :            :         /* Determine number of cascaded TCAMs */
     989                 :          0 :         num_cscd = DIVIDE_AND_ROUND_UP(scen->width,
     990                 :            :                                        ICE_AQC_ACL_KEY_WIDTH_BYTES);
     991                 :            : 
     992                 :          0 :         entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);
     993                 :          0 :         idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + *entry_idx);
     994                 :            : 
     995                 :            :         ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
     996         [ #  # ]:          0 :         for (i = 0; i < num_cscd; i++) {
     997                 :            :                 /* If the key spans more than one TCAM in the case of cascaded
     998                 :            :                  * TCAMs, the key and key inverts need to be properly split
     999                 :            :                  * among TCAMs.E.g.bytes 0 - 4 go to an index in the first TCAM
    1000                 :            :                  * and bytes 5 - 9 go to the same index in the next TCAM, etc.
    1001                 :            :                  * If the entry spans more than one TCAM in a cascaded TCAM
    1002                 :            :                  * mode, the programming of the entries in the TCAMs must be in
    1003                 :            :                  * reversed order - the TCAM entry of the rightmost TCAM should
    1004                 :            :                  * be programmed first; the TCAM entry of the leftmost TCAM
    1005                 :            :                  * should be programmed last.
    1006                 :            :                  */
    1007                 :          0 :                 offset = (u8)(num_cscd - i - 1);
    1008         [ #  # ]:          0 :                 ice_memcpy(&buf.entry_key.val,
    1009                 :            :                            &keys[offset * sizeof(buf.entry_key.val)],
    1010                 :            :                            sizeof(buf.entry_key.val), ICE_NONDMA_TO_NONDMA);
    1011         [ #  # ]:          0 :                 ice_memcpy(&buf.entry_key_invert.val,
    1012                 :            :                            &inverts[offset * sizeof(buf.entry_key_invert.val)],
    1013                 :            :                            sizeof(buf.entry_key_invert.val),
    1014                 :            :                            ICE_NONDMA_TO_NONDMA);
    1015                 :          0 :                 status = ice_aq_program_acl_entry(hw, entry_tcam + offset, idx,
    1016                 :            :                                                   &buf, NULL);
    1017         [ #  # ]:          0 :                 if (status) {
    1018         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "aq program acl entry failed status: %d\n",
    1019                 :            :                                   status);
    1020                 :          0 :                         goto out;
    1021                 :            :                 }
    1022                 :            :         }
    1023                 :            : 
    1024                 :            :         /* Program the action memory */
    1025                 :          0 :         status = ice_acl_prog_act(hw, scen, acts, acts_cnt, *entry_idx);
    1026                 :            : 
    1027                 :          0 : out:
    1028         [ #  # ]:          0 :         if (status) {
    1029                 :          0 :                 ice_acl_rem_entry(hw, scen, *entry_idx);
    1030                 :          0 :                 *entry_idx = 0;
    1031                 :            :         }
    1032                 :            : 
    1033                 :            :         return status;
    1034                 :            : }
    1035                 :            : 
    1036                 :            : /**
    1037                 :            :  * ice_acl_prog_act - Program a scenario's action memory
    1038                 :            :  * @hw: pointer to the HW struct
    1039                 :            :  * @scen: scenario to add the entry to
    1040                 :            :  * @acts: pointer to a buffer containing formatted actions
    1041                 :            :  * @acts_cnt: indicates the number of actions stored in "acts"
    1042                 :            :  * @entry_idx: scenario relative index of the added flow entry
    1043                 :            :  *
    1044                 :            :  * Program a scenario's action memory
    1045                 :            :  */
    1046                 :            : enum ice_status
    1047                 :          0 : ice_acl_prog_act(struct ice_hw *hw, struct ice_acl_scen *scen,
    1048                 :            :                  struct ice_acl_act_entry *acts, u8 acts_cnt,
    1049                 :            :                  u16 entry_idx)
    1050                 :            : {
    1051                 :            :         u16 idx, entry_tcam, num_cscd, i, actx_idx = 0;
    1052                 :            :         struct ice_aqc_actpair act_buf;
    1053                 :            :         enum ice_status status = ICE_SUCCESS;
    1054                 :            : 
    1055         [ #  # ]:          0 :         if (entry_idx >= scen->num_entry)
    1056                 :            :                 return ICE_ERR_MAX_LIMIT;
    1057                 :            : 
    1058                 :            :         ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);
    1059                 :            : 
    1060                 :            :         /* Determine number of cascaded TCAMs */
    1061                 :          0 :         num_cscd = DIVIDE_AND_ROUND_UP(scen->width,
    1062                 :            :                                        ICE_AQC_ACL_KEY_WIDTH_BYTES);
    1063                 :            : 
    1064                 :          0 :         entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);
    1065                 :          0 :         idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx);
    1066                 :            : 
    1067         [ #  # ]:          0 :         ice_for_each_set_bit(i, scen->act_mem_bitmap,
    1068                 :            :                              ICE_AQC_MAX_ACTION_MEMORIES) {
    1069                 :          0 :                 struct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i];
    1070                 :            : 
    1071         [ #  # ]:          0 :                 if (actx_idx >= acts_cnt)
    1072                 :            :                         break;
    1073         [ #  # ]:          0 :                 if (mem->member_of_tcam >= entry_tcam &&
    1074         [ #  # ]:          0 :                     mem->member_of_tcam < entry_tcam + num_cscd) {
    1075         [ #  # ]:          0 :                         ice_memcpy(&act_buf.act[0], &acts[actx_idx],
    1076                 :            :                                    sizeof(struct ice_acl_act_entry),
    1077                 :            :                                    ICE_NONDMA_TO_NONDMA);
    1078                 :            : 
    1079         [ #  # ]:          0 :                         if (++actx_idx < acts_cnt) {
    1080         [ #  # ]:          0 :                                 ice_memcpy(&act_buf.act[1], &acts[actx_idx],
    1081                 :            :                                            sizeof(struct ice_acl_act_entry),
    1082                 :            :                                            ICE_NONDMA_TO_NONDMA);
    1083                 :            :                         }
    1084                 :            : 
    1085                 :          0 :                         status = ice_aq_program_actpair(hw, i, idx, &act_buf,
    1086                 :            :                                                         NULL);
    1087         [ #  # ]:          0 :                         if (status) {
    1088         [ #  # ]:          0 :                                 ice_debug(hw, ICE_DBG_ACL, "program actpair failed status: %d\n",
    1089                 :            :                                           status);
    1090                 :            :                                 break;
    1091                 :            :                         }
    1092                 :          0 :                         actx_idx++;
    1093                 :            :                 }
    1094                 :            :         }
    1095                 :            : 
    1096   [ #  #  #  # ]:          0 :         if (!status && actx_idx < acts_cnt)
    1097                 :            :                 status = ICE_ERR_MAX_LIMIT;
    1098                 :            : 
    1099                 :            :         return status;
    1100                 :            : }
    1101                 :            : 
    1102                 :            : /**
    1103                 :            :  * ice_acl_rem_entry - Remove a flow entry from an ACL scenario
    1104                 :            :  * @hw: pointer to the HW struct
    1105                 :            :  * @scen: scenario to remove the entry from
    1106                 :            :  * @entry_idx: the scenario-relative index of the flow entry being removed
    1107                 :            :  */
    1108                 :            : enum ice_status
    1109                 :          0 : ice_acl_rem_entry(struct ice_hw *hw, struct ice_acl_scen *scen, u16 entry_idx)
    1110                 :            : {
    1111                 :            :         struct ice_aqc_actpair act_buf;
    1112                 :            :         struct ice_aqc_acl_data buf;
    1113                 :            :         enum ice_status status = ICE_SUCCESS;
    1114                 :            :         u16 num_cscd, idx, i;
    1115                 :            :         u8 entry_tcam;
    1116                 :            : 
    1117         [ #  # ]:          0 :         if (!scen)
    1118                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
    1119                 :            : 
    1120         [ #  # ]:          0 :         if (entry_idx >= scen->num_entry)
    1121                 :            :                 return ICE_ERR_MAX_LIMIT;
    1122                 :            : 
    1123         [ #  # ]:          0 :         if (!ice_is_bit_set(scen->entry_bitmap, entry_idx))
    1124                 :            :                 return ICE_ERR_DOES_NOT_EXIST;
    1125                 :            : 
    1126                 :            :         /* Determine number of cascaded TCAMs */
    1127                 :          0 :         num_cscd = DIVIDE_AND_ROUND_UP(scen->width,
    1128                 :            :                                        ICE_AQC_ACL_KEY_WIDTH_BYTES);
    1129                 :            : 
    1130                 :          0 :         entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);
    1131                 :          0 :         idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx);
    1132                 :            : 
    1133                 :            :         /* invalidate the flow entry */
    1134                 :            :         ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
    1135         [ #  # ]:          0 :         for (i = 0; i < num_cscd; i++) {
    1136                 :          0 :                 status = ice_aq_program_acl_entry(hw, (u8)(entry_tcam + i),
    1137                 :            :                                                   idx, &buf, NULL);
    1138         [ #  # ]:          0 :                 if (status)
    1139         [ #  # ]:          0 :                         ice_debug(hw, ICE_DBG_ACL, "AQ program ACL entry failed status: %d\n",
    1140                 :            :                                   status);
    1141                 :            :         }
    1142                 :            : 
    1143                 :            :         ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);
    1144                 :            : 
    1145         [ #  # ]:          0 :         ice_for_each_set_bit(i, scen->act_mem_bitmap,
    1146                 :            :                              ICE_AQC_MAX_ACTION_MEMORIES) {
    1147                 :          0 :                 struct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i];
    1148                 :            : 
    1149         [ #  # ]:          0 :                 if (mem->member_of_tcam >= entry_tcam &&
    1150         [ #  # ]:          0 :                     mem->member_of_tcam < entry_tcam + num_cscd) {
    1151                 :            :                         /* Invalidate allocated action pairs */
    1152                 :          0 :                         status = ice_aq_program_actpair(hw, i, idx, &act_buf,
    1153                 :            :                                                         NULL);
    1154         [ #  # ]:          0 :                         if (status)
    1155         [ #  # ]:          0 :                                 ice_debug(hw, ICE_DBG_ACL, "program actpair failed status: %d\n",
    1156                 :            :                                           status);
    1157                 :            :                 }
    1158                 :            :         }
    1159                 :            : 
    1160                 :            :         ice_acl_scen_free_entry_idx(scen, entry_idx);
    1161                 :            : 
    1162                 :            :         return status;
    1163                 :            : }

Generated by: LCOV version 1.14