LCOV - code coverage report
Current view: top level - drivers/common/cnxk - roc_npc_mcam.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 475 0.0 %
Date: 2024-01-22 15:35:40 Functions: 0 24 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 256 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2021 Marvell.
       3                 :            :  */
       4                 :            : #include "roc_api.h"
       5                 :            : #include "roc_priv.h"
       6                 :            : 
       7                 :            : static int
       8                 :          0 : npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
       9                 :            : {
      10                 :            :         struct npc_mcam_alloc_counter_req *req;
      11                 :            :         struct npc_mcam_alloc_counter_rsp *rsp;
      12                 :            :         int rc = -ENOSPC;
      13                 :            : 
      14                 :          0 :         req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
      15         [ #  # ]:          0 :         if (req == NULL)
      16                 :          0 :                 goto exit;
      17                 :          0 :         req->count = 1;
      18                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
      19         [ #  # ]:          0 :         if (rc)
      20                 :          0 :                 goto exit;
      21                 :          0 :         *ctr = rsp->cntr_list[0];
      22                 :          0 : exit:
      23                 :            :         mbox_put(mbox);
      24                 :          0 :         return rc;
      25                 :            : }
      26                 :            : 
      27                 :            : int
      28                 :          0 : npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
      29                 :            : {
      30                 :            :         struct npc_mcam_oper_counter_req *req;
      31                 :            :         int rc = -ENOSPC;
      32                 :            : 
      33                 :          0 :         req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
      34         [ #  # ]:          0 :         if (req == NULL)
      35                 :          0 :                 goto exit;
      36                 :          0 :         req->cntr = ctr_id;
      37                 :          0 :         rc = mbox_process(mbox);
      38                 :          0 : exit:
      39                 :            :         mbox_put(mbox);
      40                 :          0 :         return rc;
      41                 :            : }
      42                 :            : 
      43                 :            : int
      44                 :          0 : npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
      45                 :            : {
      46                 :            :         struct npc_mcam_oper_counter_req *req;
      47                 :            :         struct npc_mcam_oper_counter_rsp *rsp;
      48                 :            :         int rc = -ENOSPC;
      49                 :            : 
      50                 :          0 :         req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
      51         [ #  # ]:          0 :         if (req == NULL)
      52                 :          0 :                 goto exit;
      53                 :          0 :         req->cntr = ctr_id;
      54                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
      55         [ #  # ]:          0 :         if (rc)
      56                 :          0 :                 goto exit;
      57                 :          0 :         *count = rsp->stat;
      58                 :          0 : exit:
      59                 :            :         mbox_put(mbox);
      60                 :          0 :         return rc;
      61                 :            : }
      62                 :            : 
      63                 :            : int
      64                 :          0 : npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
      65                 :            : {
      66                 :            :         struct npc_mcam_oper_counter_req *req;
      67                 :            :         int rc = -ENOSPC;
      68                 :            : 
      69                 :          0 :         req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
      70         [ #  # ]:          0 :         if (req == NULL)
      71                 :          0 :                 goto exit;
      72                 :          0 :         req->cntr = ctr_id;
      73                 :          0 :         rc = mbox_process(mbox);
      74                 :          0 : exit:
      75                 :            :         mbox_put(mbox);
      76                 :          0 :         return rc;
      77                 :            : }
      78                 :            : 
      79                 :            : int
      80                 :          0 : npc_mcam_free_entry(struct mbox *mbox, uint32_t entry)
      81                 :            : {
      82                 :            :         struct npc_mcam_free_entry_req *req;
      83                 :            :         int rc = -ENOSPC;
      84                 :            : 
      85                 :          0 :         req = mbox_alloc_msg_npc_mcam_free_entry(mbox_get(mbox));
      86         [ #  # ]:          0 :         if (req == NULL)
      87                 :          0 :                 goto exit;
      88                 :          0 :         req->entry = entry;
      89                 :          0 :         rc = mbox_process(mbox);
      90                 :          0 : exit:
      91                 :            :         mbox_put(mbox);
      92                 :          0 :         return rc;
      93                 :            : }
      94                 :            : 
      95                 :            : int
      96                 :          0 : npc_mcam_free_all_entries(struct npc *npc)
      97                 :            : {
      98                 :            :         struct npc_mcam_free_entry_req *req;
      99                 :          0 :         struct mbox *mbox = mbox_get(npc->mbox);
     100                 :            :         int rc = -ENOSPC;
     101                 :            : 
     102                 :          0 :         req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
     103         [ #  # ]:          0 :         if (req == NULL)
     104                 :          0 :                 goto exit;
     105                 :          0 :         req->all = 1;
     106                 :          0 :         rc = mbox_process(mbox);
     107                 :          0 : exit:
     108                 :            :         mbox_put(mbox);
     109                 :          0 :         return rc;
     110                 :            : }
     111                 :            : 
     112                 :            : static int
     113                 :            : npc_supp_key_len(uint32_t supp_mask)
     114                 :            : {
     115                 :            :         int nib_count = 0;
     116                 :            : 
     117   [ #  #  #  # ]:          0 :         while (supp_mask) {
     118                 :          0 :                 nib_count++;
     119                 :          0 :                 supp_mask &= (supp_mask - 1);
     120                 :            :         }
     121                 :          0 :         return nib_count * 4;
     122                 :            : }
     123                 :            : 
     124                 :            : /**
     125                 :            :  * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
     126                 :            :  *
     127                 :            :  * No LFLAG extraction is taken into account.
     128                 :            :  */
     129                 :            : static int
     130                 :            : npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
     131                 :            : {
     132                 :            :         struct npc_xtract_info *x_info;
     133                 :            :         int i;
     134                 :            : 
     135         [ #  # ]:          0 :         for (i = 0; i < NPC_MAX_LD; i++) {
     136                 :            :                 x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
     137                 :            :                 /* Check for LDATA */
     138   [ #  #  #  # ]:          0 :                 if (x_info->enable && x_info->len > 0)
     139                 :            :                         return true;
     140                 :            :         }
     141                 :            : 
     142                 :            :         return false;
     143                 :            : }
     144                 :            : 
     145                 :            : static void
     146                 :          0 : npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid,
     147                 :            :                          uint8_t lt, uint8_t ld)
     148                 :            : {
     149                 :            :         struct npc_xtract_info *x_info, *infoflag;
     150                 :            :         int hdr_off, keylen;
     151                 :            :         npc_dxcfg_t *p;
     152                 :            :         npc_fxcfg_t *q;
     153                 :            :         int i, j;
     154                 :            : 
     155                 :            :         p = &npc->prx_dxcfg;
     156                 :          0 :         x_info = &(*p)[0][lid][lt].xtract[ld];
     157                 :            : 
     158         [ #  # ]:          0 :         if (x_info->enable == 0)
     159                 :            :                 return;
     160                 :            : 
     161                 :          0 :         hdr_off = x_info->hdr_off * 8;
     162                 :          0 :         keylen = x_info->len * 8;
     163         [ #  # ]:          0 :         for (i = hdr_off; i < (hdr_off + keylen); i++)
     164                 :          0 :                 plt_bitmap_set(bmap, i);
     165                 :            : 
     166         [ #  # ]:          0 :         if (x_info->flags_enable == 0)
     167                 :            :                 return;
     168                 :            : 
     169         [ #  # ]:          0 :         if ((npc->prx_lfcfg[0].i & 0x7) != lid)
     170                 :            :                 return;
     171                 :            : 
     172                 :            :         q = &npc->prx_fxcfg;
     173         [ #  # ]:          0 :         for (j = 0; j < NPC_MAX_LFL; j++) {
     174                 :            :                 infoflag = &(*q)[0][ld][j].xtract[0];
     175         [ #  # ]:          0 :                 if (infoflag->enable) {
     176                 :          0 :                         hdr_off = infoflag->hdr_off * 8;
     177                 :          0 :                         keylen = infoflag->len * 8;
     178         [ #  # ]:          0 :                         for (i = hdr_off; i < (hdr_off + keylen); i++)
     179                 :          0 :                                 plt_bitmap_set(bmap, i);
     180                 :            :                 }
     181                 :            :         }
     182                 :            : }
     183                 :            : 
     184                 :            : /**
     185                 :            :  * Check if given LID+LTYPE combination is present in KEX
     186                 :            :  *
     187                 :            :  * len is non-zero, this function will return true if KEX extracts len bytes
     188                 :            :  * at given offset. Otherwise it'll return true if any bytes are extracted
     189                 :            :  * specifically for given LID+LTYPE combination (meaning not LFLAG based).
     190                 :            :  * The second case increases flexibility for custom frames whose extracted
     191                 :            :  * bits may change depending on KEX profile loaded.
     192                 :            :  *
     193                 :            :  * @param npc NPC context structure
     194                 :            :  * @param lid Layer ID to check for
     195                 :            :  * @param lt Layer Type to check for
     196                 :            :  * @param offset offset into the layer header to match
     197                 :            :  * @param len length of the match
     198                 :            :  */
     199                 :            : static bool
     200                 :          0 : npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset,
     201                 :            :                    int len)
     202                 :            : {
     203                 :            :         struct plt_bitmap *bmap;
     204                 :            :         uint32_t bmap_sz;
     205                 :            :         uint8_t *mem;
     206                 :            :         int i;
     207                 :            : 
     208         [ #  # ]:          0 :         if (!len)
     209                 :          0 :                 return npc_lid_lt_in_kex(npc, lid, lt);
     210                 :            : 
     211                 :            :         bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
     212                 :          0 :         mem = plt_zmalloc(bmap_sz, 0);
     213         [ #  # ]:          0 :         if (mem == NULL) {
     214                 :          0 :                 plt_err("mem alloc failed");
     215                 :          0 :                 return false;
     216                 :            :         }
     217                 :          0 :         bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
     218         [ #  # ]:          0 :         if (bmap == NULL) {
     219                 :          0 :                 plt_err("mem alloc failed");
     220                 :          0 :                 plt_free(mem);
     221                 :          0 :                 return false;
     222                 :            :         }
     223                 :            : 
     224                 :          0 :         npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
     225                 :          0 :         npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
     226                 :            : 
     227         [ #  # ]:          0 :         for (i = offset; i < (offset + len); i++) {
     228         [ #  # ]:          0 :                 if (plt_bitmap_get(bmap, i) != 0x1) {
     229                 :          0 :                         plt_free(mem);
     230                 :          0 :                         return false;
     231                 :            :                 }
     232                 :            :         }
     233                 :            : 
     234                 :          0 :         plt_free(mem);
     235                 :          0 :         return true;
     236                 :            : }
     237                 :            : 
     238                 :            : uint64_t
     239                 :          0 : npc_get_kex_capability(struct npc *npc)
     240                 :            : {
     241                 :            :         npc_kex_cap_terms_t kex_cap;
     242                 :            : 
     243                 :            :         memset(&kex_cap, 0, sizeof(kex_cap));
     244                 :            : 
     245                 :            :         /* Ethtype: Offset 12B, len 2B */
     246                 :          0 :         kex_cap.bit.ethtype_0 = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
     247                 :            :         /* QINQ VLAN Ethtype: offset 8B, len 2B */
     248                 :          0 :         kex_cap.bit.ethtype_x =
     249                 :          0 :                 npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
     250                 :            :         /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
     251                 :          0 :         kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
     252                 :            :         /* VLAN PCP0 : Outer VLAN: Offset 2B, len 1B */
     253                 :          0 :         kex_cap.bit.vlan_pcp_0 = npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 1);
     254                 :            :         /* VLAN IDX : Inner VLAN: offset 6B, len 2B */
     255                 :          0 :         kex_cap.bit.vlan_id_x =
     256                 :          0 :                 npc_is_kex_enabled(npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
     257                 :            :         /* DMCA: offset 0B, len 6B */
     258                 :          0 :         kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER, 0 * 8, 6 * 8);
     259                 :            :         /* IP proto: offset 9B, len 1B */
     260                 :          0 :         kex_cap.bit.ip_proto = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
     261                 :            :         /* IPv4 dscp: offset 1B, len 1B, IPv6 dscp: offset 0B, len 2B */
     262   [ #  #  #  # ]:          0 :         kex_cap.bit.ip_dscp = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 1 * 8, 1 * 8) &&
     263                 :          0 :                               npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 0, 2 * 8);
     264                 :            :         /* UDP dport: offset 2B, len 2B */
     265                 :          0 :         kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 2 * 8, 2 * 8);
     266                 :            :         /* UDP sport: offset 0B, len 2B */
     267                 :          0 :         kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_UDP, 0 * 8, 2 * 8);
     268                 :            :         /* TCP dport: offset 2B, len 2B */
     269                 :          0 :         kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 2 * 8, 2 * 8);
     270                 :            :         /* TCP sport: offset 0B, len 2B */
     271                 :          0 :         kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_TCP, 0 * 8, 2 * 8);
     272                 :            :         /* IP SIP: offset 12B, len 4B */
     273                 :          0 :         kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 12 * 8, 4 * 8);
     274                 :            :         /* IP DIP: offset 14B, len 4B */
     275                 :          0 :         kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 14 * 8, 4 * 8);
     276                 :            :         /* IP6 SIP: offset 8B, len 16B */
     277                 :          0 :         kex_cap.bit.sip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
     278                 :            :         /* IP6 DIP: offset 24B, len 16B */
     279                 :          0 :         kex_cap.bit.dip6_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
     280                 :            :         /* ESP SPI: offset 0B, len 4B */
     281                 :          0 :         kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_ESP, 0 * 8, 4 * 8);
     282                 :            :         /* VXLAN VNI: offset 4B, len 3B */
     283                 :          0 :         kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
     284                 :            : 
     285                 :            :         /* Custom L3 frame: varied offset and lengths */
     286                 :          0 :         kex_cap.bit.custom_l3 = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
     287                 :          0 :         kex_cap.bit.custom_l3 |=
     288                 :          0 :                 (uint64_t)npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
     289                 :            :         /* SCTP sport : offset 0B, len 2B */
     290                 :          0 :         kex_cap.bit.sctp_sport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
     291                 :            :         /* SCTP dport : offset 2B, len 2B */
     292                 :          0 :         kex_cap.bit.sctp_dport = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
     293                 :            :         /* ICMP type : offset 0B, len 1B */
     294                 :          0 :         kex_cap.bit.icmp_type = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
     295                 :            :         /* ICMP code : offset 1B, len 1B */
     296                 :          0 :         kex_cap.bit.icmp_code = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
     297                 :            :         /* ICMP id : offset 4B, len 2B */
     298                 :          0 :         kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
     299                 :            :         /* IGMP grp_addr : offset 4B, len 4B */
     300                 :          0 :         kex_cap.bit.igmp_grp_addr =
     301                 :          0 :                 npc_is_kex_enabled(npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
     302                 :            :         /* GTPU teid : offset 4B, len 4B */
     303                 :          0 :         kex_cap.bit.gtpv1_teid = npc_is_kex_enabled(npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
     304                 :          0 :         return kex_cap.all_bits;
     305                 :            : }
     306                 :            : 
     307                 :            : #define BYTESM1_SHIFT 16
     308                 :            : #define HDR_OFF_SHIFT 8
     309                 :            : static void
     310                 :            : npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
     311                 :            : {
     312                 :          0 :         xtract_info->use_hash = ((val >> 20) & 0x1);
     313                 :          0 :         xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
     314                 :          0 :         xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
     315                 :          0 :         xtract_info->key_off = val & 0x3f;
     316                 :          0 :         xtract_info->enable = ((val >> 7) & 0x1);
     317                 :          0 :         xtract_info->flags_enable = ((val >> 6) & 0x1);
     318                 :            : }
     319                 :            : 
     320                 :            : int
     321                 :          0 : npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int req_count, int prio,
     322                 :            :                        int *resp_count, bool is_conti)
     323                 :            : {
     324                 :            :         struct npc_mcam_alloc_entry_req *req;
     325                 :            :         struct npc_mcam_alloc_entry_rsp *rsp;
     326                 :            :         int rc = -ENOSPC;
     327                 :            :         int i;
     328                 :            : 
     329                 :          0 :         req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
     330         [ #  # ]:          0 :         if (req == NULL)
     331                 :          0 :                 goto exit;
     332                 :          0 :         req->contig = is_conti;
     333                 :          0 :         req->count = req_count;
     334                 :          0 :         req->priority = prio;
     335                 :          0 :         req->ref_entry = ref_mcam;
     336                 :            : 
     337                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
     338         [ #  # ]:          0 :         if (rc)
     339                 :          0 :                 goto exit;
     340         [ #  # ]:          0 :         for (i = 0; i < rsp->count; i++)
     341                 :          0 :                 alloc_entry[i] = rsp->entry_list[i];
     342                 :          0 :         *resp_count = rsp->count;
     343         [ #  # ]:          0 :         if (is_conti)
     344                 :          0 :                 alloc_entry[0] = rsp->entry;
     345                 :            :         rc = 0;
     346                 :          0 : exit:
     347                 :            :         mbox_put(mbox);
     348                 :          0 :         return rc;
     349                 :            : }
     350                 :            : 
     351                 :            : int
     352                 :          0 : npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
     353                 :            :                      struct roc_npc_flow *ref_mcam, int prio, int *resp_count)
     354                 :            : {
     355                 :            :         struct npc_mcam_alloc_entry_req *req;
     356                 :            :         struct npc_mcam_alloc_entry_rsp *rsp;
     357                 :          0 :         struct mbox *mbox = mbox_get(npc->mbox);
     358                 :            :         int rc = -ENOSPC;
     359                 :            : 
     360                 :          0 :         req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
     361         [ #  # ]:          0 :         if (req == NULL)
     362                 :          0 :                 goto exit;
     363                 :          0 :         req->contig = 1;
     364                 :          0 :         req->count = 1;
     365                 :          0 :         req->priority = prio;
     366                 :          0 :         req->ref_entry = ref_mcam->mcam_id;
     367                 :            : 
     368                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
     369         [ #  # ]:          0 :         if (rc)
     370                 :          0 :                 goto exit;
     371                 :            :         memset(mcam, 0, sizeof(struct roc_npc_flow));
     372                 :          0 :         mcam->mcam_id = rsp->entry;
     373                 :          0 :         mcam->nix_intf = ref_mcam->nix_intf;
     374                 :          0 :         *resp_count = rsp->count;
     375                 :            :         rc = 0;
     376                 :          0 : exit:
     377                 :            :         mbox_put(mbox);
     378                 :          0 :         return rc;
     379                 :            : }
     380                 :            : 
     381                 :            : int
     382                 :          0 : npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
     383                 :            : {
     384                 :            :         struct npc_mcam_ena_dis_entry_req *req;
     385                 :          0 :         struct mbox *mbox = mbox_get(npc->mbox);
     386                 :            :         int rc = -ENOSPC;
     387                 :            : 
     388         [ #  # ]:          0 :         if (enable)
     389                 :          0 :                 req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
     390                 :            :         else
     391                 :          0 :                 req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
     392                 :            : 
     393         [ #  # ]:          0 :         if (req == NULL)
     394                 :          0 :                 goto exit;
     395                 :          0 :         req->entry = mcam->mcam_id;
     396                 :          0 :         mcam->enable = enable;
     397                 :          0 :         rc = mbox_process(mbox);
     398                 :          0 : exit:
     399                 :            :         mbox_put(mbox);
     400                 :          0 :         return rc;
     401                 :            : }
     402                 :            : 
     403                 :            : int
     404                 :          0 : npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
     405                 :            : {
     406                 :            :         struct npc_mcam_write_entry_req *req;
     407                 :            :         struct mbox_msghdr *rsp;
     408                 :            :         int rc = -ENOSPC;
     409                 :          0 :         uint16_t ctr = 0;
     410                 :            :         int i;
     411                 :            : 
     412   [ #  #  #  # ]:          0 :         if (mcam->use_ctr && mcam->ctr_id == NPC_COUNTER_NONE) {
     413                 :          0 :                 rc = npc_mcam_alloc_counter(mbox, &ctr);
     414         [ #  # ]:          0 :                 if (rc)
     415                 :            :                         return rc;
     416                 :          0 :                 mcam->ctr_id = ctr;
     417                 :            : 
     418                 :          0 :                 rc = npc_mcam_clear_counter(mbox, mcam->ctr_id);
     419         [ #  # ]:          0 :                 if (rc)
     420                 :            :                         return rc;
     421                 :            :         }
     422                 :            : 
     423                 :          0 :         req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
     424         [ #  # ]:          0 :         if (req == NULL) {
     425                 :            :                 mbox_put(mbox);
     426         [ #  # ]:          0 :                 if (mcam->use_ctr)
     427                 :          0 :                         npc_mcam_free_counter(mbox, ctr);
     428                 :            : 
     429                 :          0 :                 return rc;
     430                 :            :         }
     431                 :          0 :         req->entry = mcam->mcam_id;
     432                 :          0 :         req->intf = mcam->nix_intf;
     433                 :          0 :         req->enable_entry = mcam->enable;
     434                 :          0 :         req->entry_data.action = mcam->npc_action;
     435                 :          0 :         req->entry_data.vtag_action = mcam->vtag_action;
     436         [ #  # ]:          0 :         if (mcam->use_ctr) {
     437                 :          0 :                 req->set_cntr = 1;
     438                 :          0 :                 req->cntr = mcam->ctr_id;
     439                 :            :         }
     440                 :            : 
     441         [ #  # ]:          0 :         for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
     442                 :          0 :                 req->entry_data.kw[i] = mcam->mcam_data[i];
     443                 :          0 :                 req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
     444                 :            :         }
     445                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
     446                 :            :         mbox_put(mbox);
     447                 :          0 :         return rc;
     448                 :            : }
     449                 :            : 
     450                 :            : static void
     451                 :          0 : npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
     452                 :            : {
     453                 :            :         volatile uint64_t(
     454                 :            :                 *q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
     455                 :            :         struct npc_xtract_info *x_info = NULL;
     456                 :            :         int lid, lt, ld, fl, ix;
     457                 :            :         npc_dxcfg_t *p;
     458                 :            :         uint64_t keyw;
     459                 :            :         uint64_t val;
     460                 :            : 
     461                 :          0 :         npc->keyx_supp_nmask[NPC_MCAM_RX] =
     462                 :          0 :                 kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
     463                 :          0 :         npc->keyx_supp_nmask[NPC_MCAM_TX] =
     464                 :          0 :                 kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
     465                 :          0 :         npc->keyx_len[NPC_MCAM_RX] =
     466                 :          0 :                 npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
     467                 :          0 :         npc->keyx_len[NPC_MCAM_TX] =
     468                 :          0 :                 npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
     469                 :            : 
     470                 :          0 :         keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
     471                 :          0 :         npc->keyw[NPC_MCAM_RX] = keyw;
     472                 :          0 :         keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
     473                 :          0 :         npc->keyw[NPC_MCAM_TX] = keyw;
     474                 :            : 
     475                 :            :         /* Update KEX_LD_FLAG */
     476         [ #  # ]:          0 :         for (ix = 0; ix < NPC_MAX_INTF; ix++) {
     477         [ #  # ]:          0 :                 for (ld = 0; ld < NPC_MAX_LD; ld++) {
     478         [ #  # ]:          0 :                         for (fl = 0; fl < NPC_MAX_LFL; fl++) {
     479                 :            :                                 x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
     480                 :          0 :                                 val = kex_rsp->intf_ld_flags[ix][ld][fl];
     481                 :            :                                 npc_update_kex_info(x_info, val);
     482                 :            :                         }
     483                 :            :                 }
     484                 :            :         }
     485                 :            : 
     486                 :            :         /* Update LID, LT and LDATA cfg */
     487                 :            :         p = &npc->prx_dxcfg;
     488                 :            :         q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(
     489                 :            :                 &kex_rsp->intf_lid_lt_ld);
     490         [ #  # ]:          0 :         for (ix = 0; ix < NPC_MAX_INTF; ix++) {
     491         [ #  # ]:          0 :                 for (lid = 0; lid < NPC_MAX_LID; lid++) {
     492         [ #  # ]:          0 :                         for (lt = 0; lt < NPC_MAX_LT; lt++) {
     493         [ #  # ]:          0 :                                 for (ld = 0; ld < NPC_MAX_LD; ld++) {
     494                 :            :                                         x_info = &(*p)[ix][lid][lt].xtract[ld];
     495                 :          0 :                                         val = (*q)[ix][lid][lt][ld];
     496                 :            :                                         npc_update_kex_info(x_info, val);
     497                 :            :                                 }
     498                 :            :                         }
     499                 :            :                 }
     500                 :            :         }
     501                 :            :         /* Update LDATA Flags cfg */
     502                 :          0 :         npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
     503                 :          0 :         npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
     504                 :          0 : }
     505                 :            : 
     506                 :            : int
     507                 :          0 : npc_mcam_fetch_hw_cap(struct npc *npc, uint8_t *npc_hw_cap)
     508                 :            : {
     509                 :            :         struct get_hw_cap_rsp *hw_cap_rsp;
     510                 :          0 :         struct mbox *mbox = mbox_get(npc->mbox);
     511                 :            :         int rc = 0;
     512                 :            : 
     513                 :          0 :         *npc_hw_cap = 0;
     514                 :            : 
     515                 :          0 :         mbox_alloc_msg_get_hw_cap(mbox);
     516                 :            :         rc = mbox_process_msg(mbox, (void *)&hw_cap_rsp);
     517         [ #  # ]:          0 :         if (rc) {
     518                 :          0 :                 plt_err("Failed to fetch NPC HW capability");
     519                 :          0 :                 goto done;
     520                 :            :         }
     521                 :            : 
     522                 :          0 :         *npc_hw_cap = hw_cap_rsp->npc_hash_extract;
     523                 :          0 : done:
     524                 :            :         mbox_put(mbox);
     525                 :          0 :         return rc;
     526                 :            : }
     527                 :            : 
     528                 :            : int
     529                 :          0 : npc_mcam_fetch_kex_cfg(struct npc *npc)
     530                 :            : {
     531                 :            :         struct npc_get_kex_cfg_rsp *kex_rsp;
     532                 :          0 :         struct mbox *mbox = mbox_get(npc->mbox);
     533                 :            :         int rc = 0;
     534                 :            : 
     535                 :          0 :         mbox_alloc_msg_npc_get_kex_cfg(mbox);
     536                 :            :         rc = mbox_process_msg(mbox, (void *)&kex_rsp);
     537         [ #  # ]:          0 :         if (rc) {
     538                 :          0 :                 plt_err("Failed to fetch NPC KEX config");
     539                 :          0 :                 goto done;
     540                 :            :         }
     541                 :            : 
     542                 :          0 :         mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name,
     543                 :            :                     MKEX_NAME_LEN);
     544                 :            : 
     545                 :          0 :         npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
     546                 :          0 :         npc_mcam_process_mkex_cfg(npc, kex_rsp);
     547                 :            : 
     548                 :          0 : done:
     549                 :            :         mbox_put(mbox);
     550                 :          0 :         return rc;
     551                 :            : }
     552                 :            : 
     553                 :            : static void
     554                 :          0 : npc_mcam_set_channel(struct roc_npc_flow *flow,
     555                 :            :                      struct npc_mcam_write_entry_req *req, uint16_t channel,
     556                 :            :                      uint16_t chan_mask, bool is_second_pass)
     557                 :            : {
     558                 :            :         uint16_t chan = 0, mask = 0;
     559                 :            : 
     560                 :          0 :         req->entry_data.kw[0] &= ~(GENMASK(11, 0));
     561                 :          0 :         req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
     562                 :          0 :         flow->mcam_data[0] &= ~(GENMASK(11, 0));
     563         [ #  # ]:          0 :         flow->mcam_mask[0] &= ~(GENMASK(11, 0));
     564                 :            :         chan = channel;
     565                 :            :         mask = chan_mask;
     566                 :            : 
     567         [ #  # ]:          0 :         if (roc_model_runtime_is_cn10k()) {
     568         [ #  # ]:          0 :                 if (is_second_pass) {
     569                 :          0 :                         chan = (channel | NIX_CHAN_CPT_CH_START);
     570                 :          0 :                         mask = (chan_mask | NIX_CHAN_CPT_CH_START);
     571                 :            :                 } else {
     572         [ #  # ]:          0 :                         if (!(flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
     573                 :            :                                 /*
     574                 :            :                                  * Clear bits 10 & 11 corresponding to CPT
     575                 :            :                                  * channel. By default, rules should match
     576                 :            :                                  * both first pass packets and second pass
     577                 :            :                                  * packets from CPT.
     578                 :            :                                  */
     579                 :          0 :                                 chan = (channel & NIX_CHAN_CPT_X2P_MASK);
     580                 :          0 :                                 mask = (chan_mask & NIX_CHAN_CPT_X2P_MASK);
     581                 :            :                         }
     582                 :            :                 }
     583                 :            :         }
     584                 :            : 
     585                 :          0 :         req->entry_data.kw[0] |= (uint64_t)chan;
     586                 :          0 :         req->entry_data.kw_mask[0] |= (uint64_t)mask;
     587                 :          0 :         flow->mcam_data[0] |= (uint64_t)chan;
     588                 :          0 :         flow->mcam_mask[0] |= (uint64_t)mask;
     589                 :          0 : }
     590                 :            : 
     591                 :            : static int
     592                 :          0 : npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
     593                 :            : {
     594                 :            : #define NPC_PF_FUNC_WIDTH    2
     595                 :            : #define NPC_KEX_PF_FUNC_MASK 0xFFFF
     596                 :            :         uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
     597                 :            :         uint8_t *flow_mcam_data, *flow_mcam_mask;
     598                 :            :         struct npc_lid_lt_xtract_info *xinfo;
     599                 :            :         bool pffunc_found = false;
     600                 :          0 :         uint16_t mask = 0xFFFF;
     601                 :            :         int i;
     602                 :            : 
     603                 :          0 :         flow_mcam_data = (uint8_t *)flow->mcam_data;
     604                 :          0 :         flow_mcam_mask = (uint8_t *)flow->mcam_mask;
     605                 :            : 
     606                 :            :         xinfo = &npc->prx_dxcfg[NIX_INTF_TX][NPC_LID_LA][NPC_LT_LA_IH_NIX_ETHER];
     607                 :            : 
     608         [ #  # ]:          0 :         for (i = 0; i < NPC_MAX_LD; i++) {
     609                 :          0 :                 nr_bytes = xinfo->xtract[i].len;
     610                 :          0 :                 hdr_offset = xinfo->xtract[i].hdr_off;
     611                 :          0 :                 key_offset = xinfo->xtract[i].key_off;
     612                 :            : 
     613         [ #  # ]:          0 :                 if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
     614                 :          0 :                         continue;
     615                 :            :                 else
     616                 :            :                         pffunc_found = true;
     617                 :            : 
     618                 :          0 :                 pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
     619                 :          0 :                 memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
     620                 :            :                        NPC_PF_FUNC_WIDTH);
     621                 :          0 :                 memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
     622                 :            :                        NPC_PF_FUNC_WIDTH);
     623                 :            :         }
     624         [ #  # ]:          0 :         if (!pffunc_found)
     625                 :          0 :                 return -EINVAL;
     626                 :            : 
     627                 :            :         return 0;
     628                 :            : }
     629                 :            : 
     630                 :            : int
     631                 :          0 : npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
     632                 :            : {
     633                 :            :         struct npc_mcam_write_entry_req *req;
     634                 :            :         struct nix_inl_dev *inl_dev = NULL;
     635                 :          0 :         struct mbox *mbox = npc->mbox;
     636                 :            :         struct mbox_msghdr *rsp;
     637                 :            :         struct idev_cfg *idev;
     638                 :            :         uint16_t pf_func = 0;
     639                 :          0 :         uint16_t ctr = ~(0);
     640                 :            :         uint32_t la_offset;
     641                 :            :         uint64_t mask;
     642                 :            :         int rc, idx;
     643                 :            :         int entry;
     644                 :            : 
     645                 :            :         PLT_SET_USED(pst);
     646                 :            : 
     647                 :          0 :         idev = idev_get_cfg();
     648         [ #  # ]:          0 :         if (idev)
     649                 :          0 :                 inl_dev = idev->nix_inl_dev;
     650                 :            : 
     651   [ #  #  #  # ]:          0 :         if (inl_dev && inl_dev->ipsec_index) {
     652         [ #  # ]:          0 :                 if (flow->is_inline_dev)
     653                 :          0 :                         mbox = inl_dev->dev.mbox;
     654                 :            :         }
     655                 :            : 
     656         [ #  # ]:          0 :         if (flow->use_ctr) {
     657                 :          0 :                 rc = npc_mcam_alloc_counter(mbox, &ctr);
     658         [ #  # ]:          0 :                 if (rc)
     659                 :            :                         return rc;
     660                 :            : 
     661                 :          0 :                 flow->ctr_id = ctr;
     662                 :          0 :                 rc = npc_mcam_clear_counter(mbox, flow->ctr_id);
     663         [ #  # ]:          0 :                 if (rc)
     664                 :            :                         return rc;
     665                 :            :         }
     666                 :            : 
     667   [ #  #  #  #  :          0 :         if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
                   #  # ]
     668   [ #  #  #  # ]:          0 :             inl_dev->ipsec_index && inl_dev->is_multi_channel) {
     669         [ #  # ]:          0 :                 if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
     670                 :            :                         return NPC_ERR_MCAM_ALLOC;
     671                 :          0 :                 entry = inl_dev->ipsec_index[inl_dev->curr_ipsec_idx];
     672                 :          0 :                 inl_dev->curr_ipsec_idx++;
     673                 :          0 :                 flow->use_pre_alloc = 1;
     674                 :            :         } else {
     675                 :          0 :                 entry = npc_get_free_mcam_entry(mbox, flow, npc);
     676         [ #  # ]:          0 :                 if (entry < 0) {
     677         [ #  # ]:          0 :                         if (flow->use_ctr)
     678                 :          0 :                                 npc_mcam_free_counter(mbox, ctr);
     679                 :          0 :                         return NPC_ERR_MCAM_ALLOC;
     680                 :            :                 }
     681                 :            :         }
     682                 :            : 
     683                 :          0 :         req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
     684         [ #  # ]:          0 :         if (req == NULL) {
     685                 :            :                 rc = -ENOSPC;
     686                 :          0 :                 goto exit;
     687                 :            :         }
     688                 :          0 :         req->set_cntr = flow->use_ctr;
     689                 :          0 :         req->cntr = flow->ctr_id;
     690                 :          0 :         req->entry = entry;
     691                 :            : 
     692                 :          0 :         req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
     693                 :          0 :         req->enable_entry = 1;
     694                 :          0 :         req->entry_data.action = flow->npc_action;
     695                 :            : 
     696                 :            :         /*
     697                 :            :          * Driver sets vtag action on per interface basis, not
     698                 :            :          * per flow basis. It is a matter of how we decide to support
     699                 :            :          * this pmd specific behavior. There are two ways:
     700                 :            :          *      1. Inherit the vtag action from the one configured
     701                 :            :          *         for this interface. This can be read from the
     702                 :            :          *         vtag_action configured for default mcam entry of
     703                 :            :          *         this pf_func.
     704                 :            :          *      2. Do not support vtag action with npc_flow.
     705                 :            :          *
     706                 :            :          * Second approach is used now.
     707                 :            :          */
     708                 :          0 :         req->entry_data.vtag_action = flow->vtag_action;
     709                 :            : 
     710         [ #  # ]:          0 :         if (flow->nix_intf == NIX_INTF_TX) {
     711                 :          0 :                 uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
     712                 :            : 
     713         [ #  # ]:          0 :                 pf_func = plt_cpu_to_be_16(pf_func);
     714                 :            : 
     715                 :          0 :                 rc = npc_mcam_set_pf_func(npc, flow, pf_func);
     716         [ #  # ]:          0 :                 if (rc)
     717                 :            :                         return rc;
     718                 :            :         }
     719                 :            : 
     720         [ #  # ]:          0 :         for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
     721                 :          0 :                 req->entry_data.kw[idx] = flow->mcam_data[idx];
     722                 :          0 :                 req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
     723                 :            :         }
     724                 :            : 
     725         [ #  # ]:          0 :         if (flow->nix_intf == NIX_INTF_RX) {
     726   [ #  #  #  # ]:          0 :                 if (inl_dev && inl_dev->is_multi_channel &&
     727         [ #  # ]:          0 :                     (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
     728                 :          0 :                         pf_func = nix_inl_dev_pffunc_get();
     729                 :          0 :                         req->entry_data.action &= ~(GENMASK(19, 4));
     730                 :          0 :                         req->entry_data.action |= (uint64_t)pf_func << 4;
     731                 :          0 :                         flow->npc_action &= ~(GENMASK(19, 4));
     732                 :          0 :                         flow->npc_action |= (uint64_t)pf_func << 4;
     733                 :            : 
     734                 :          0 :                         npc_mcam_set_channel(flow, req, inl_dev->channel, inl_dev->chan_mask,
     735                 :            :                                              false);
     736         [ #  # ]:          0 :                 } else if (npc->is_sdp_link) {
     737                 :          0 :                         npc_mcam_set_channel(flow, req, npc->sdp_channel, npc->sdp_channel_mask,
     738                 :          0 :                                              pst->is_second_pass_rule);
     739                 :            :                 } else {
     740                 :          0 :                         npc_mcam_set_channel(flow, req, npc->channel, (BIT_ULL(12) - 1),
     741                 :          0 :                                              pst->is_second_pass_rule);
     742                 :            :                 }
     743                 :            :                 /*
     744                 :            :                  * For second pass rule, set LA LTYPE to CPT_HDR.
     745                 :            :                  * For all other rules, set LA LTYPE to match both 1st pass and 2nd pass ltypes.
     746                 :            :                  */
     747   [ #  #  #  # ]:          0 :                 if (pst->is_second_pass_rule || (!pst->is_second_pass_rule && pst->has_eth_type)) {
     748         [ #  # ]:          0 :                         la_offset = plt_popcount32(npc->keyx_supp_nmask[flow->nix_intf] &
     749                 :            :                                                        ((1ULL << 9 /* LA offset */) - 1));
     750                 :          0 :                         la_offset *= 4;
     751                 :            : 
     752                 :          0 :                         mask = ~((0xfULL << la_offset));
     753                 :          0 :                         req->entry_data.kw[0] &= mask;
     754                 :          0 :                         req->entry_data.kw_mask[0] &= mask;
     755                 :          0 :                         flow->mcam_data[0] &= mask;
     756                 :          0 :                         flow->mcam_mask[0] &= mask;
     757         [ #  # ]:          0 :                         if (pst->is_second_pass_rule) {
     758                 :          0 :                                 req->entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
     759                 :          0 :                                 req->entry_data.kw_mask[0] |= (0xFULL << la_offset);
     760                 :          0 :                                 flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
     761                 :          0 :                                 flow->mcam_mask[0] |= (0xFULL << la_offset);
     762                 :            :                         } else {
     763                 :            :                                 /* Mask ltype ETHER (0x2) and CPT_HDR (0xa)  */
     764                 :          0 :                                 req->entry_data.kw[0] |= (0x2ULL << la_offset);
     765                 :          0 :                                 req->entry_data.kw_mask[0] |= (0x7ULL << la_offset);
     766                 :          0 :                                 flow->mcam_data[0] |= (0x2ULL << la_offset);
     767                 :          0 :                                 flow->mcam_mask[0] |= (0x7ULL << la_offset);
     768                 :            :                         }
     769                 :            :                 }
     770                 :            :         }
     771                 :            : 
     772                 :            :         rc = mbox_process_msg(mbox, (void *)&rsp);
     773         [ #  # ]:          0 :         if (rc != 0)
     774                 :          0 :                 goto exit;
     775                 :            : 
     776                 :          0 :         flow->mcam_id = entry;
     777                 :            : 
     778         [ #  # ]:          0 :         if (flow->use_ctr)
     779                 :          0 :                 flow->ctr_id = ctr;
     780                 :            :         rc = 0;
     781                 :          0 : exit:
     782                 :            :         mbox_put(mbox);
     783                 :          0 :         return rc;
     784                 :            : }
     785                 :            : 
     786                 :            : static void
     787                 :          0 : npc_set_vlan_ltype(struct npc_parse_state *pst)
     788                 :            : {
     789                 :            :         uint64_t val, mask;
     790                 :            :         uint8_t lb_offset;
     791                 :            : 
     792                 :          0 :         lb_offset =
     793                 :          0 :                 plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
     794                 :            :                                    ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
     795                 :          0 :         lb_offset *= 4;
     796                 :            : 
     797                 :          0 :         mask = ~((0xfULL << lb_offset));
     798                 :          0 :         pst->flow->mcam_data[0] &= mask;
     799                 :          0 :         pst->flow->mcam_mask[0] &= mask;
     800                 :            :         /* NPC_LT_LB_CTAG: 0b0010, NPC_LT_LB_STAG_QINQ: 0b0011
     801                 :            :          * Set LB layertype/mask as 0b0010/0b1110 to match both.
     802                 :            :          */
     803                 :          0 :         val = ((uint64_t)(NPC_LT_LB_CTAG & NPC_LT_LB_STAG_QINQ)) << lb_offset;
     804                 :          0 :         pst->flow->mcam_data[0] |= val;
     805                 :          0 :         pst->flow->mcam_mask[0] |= (0xeULL << lb_offset);
     806                 :          0 : }
     807                 :            : 
     808                 :            : static void
     809                 :          0 : npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
     810                 :            : {
     811                 :            :         uint8_t lc_offset, lcflag_offset;
     812                 :            :         uint64_t val, mask;
     813                 :            : 
     814                 :          0 :         lc_offset =
     815         [ #  # ]:          0 :                 plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
     816                 :            :                                    ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
     817                 :          0 :         lc_offset *= 4;
     818                 :            : 
     819                 :          0 :         mask = ~((0xfULL << lc_offset));
     820                 :          0 :         pst->flow->mcam_data[0] &= mask;
     821                 :          0 :         pst->flow->mcam_mask[0] &= mask;
     822                 :            :         /* NPC_LT_LC_IP6: 0b0100, NPC_LT_LC_IP6_EXT: 0b0101
     823                 :            :          * Set LC layertype/mask as 0b0100/0b1110 to match both.
     824                 :            :          */
     825                 :          0 :         val = ((uint64_t)(NPC_LT_LC_IP6 & NPC_LT_LC_IP6_EXT)) << lc_offset;
     826                 :          0 :         pst->flow->mcam_data[0] |= val;
     827                 :          0 :         pst->flow->mcam_mask[0] |= (0xeULL << lc_offset);
     828                 :            : 
     829                 :            :         /* If LC LFLAG is non-zero, set the LC LFLAG mask to 0xF. In general
     830                 :            :          * case flag mask is set same as the value in data. For example, to
     831                 :            :          * match 3 VLANs, flags have to match a range of values. But, for IPv6
     832                 :            :          * extended attributes matching, we need an exact match. Hence, set the
     833                 :            :          * mask as 0xF. This is done only if LC LFLAG value is non-zero,
     834                 :            :          * because for AH and ESP, LC LFLAG is zero and we don't want to match
     835                 :            :          * zero in LFLAG.
     836                 :            :          */
     837         [ #  # ]:          0 :         if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
     838         [ #  # ]:          0 :                 lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
     839                 :            :                                                    ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
     840                 :          0 :                 lcflag_offset *= 4;
     841                 :            : 
     842                 :          0 :                 mask = (0xfULL << lcflag_offset);
     843                 :          0 :                 val = pst->flow->mcam_data[0] & mask;
     844         [ #  # ]:          0 :                 if (val)
     845                 :          0 :                         pst->flow->mcam_mask[0] |= mask;
     846                 :            :         }
     847                 :          0 : }
     848                 :            : 
     849                 :            : int
     850                 :          0 : npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
     851                 :            : {
     852                 :            :         struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
     853                 :            :         /* This is non-LDATA part in search key */
     854                 :          0 :         uint64_t key_data[2] = {0ULL, 0ULL};
     855                 :          0 :         uint64_t key_mask[2] = {0ULL, 0ULL};
     856                 :            :         int key_len, bit = 0, index, rc = 0;
     857                 :            :         struct nix_inl_dev *inl_dev = NULL;
     858                 :          0 :         int intf = pst->flow->nix_intf;
     859                 :            :         struct mcam_entry *base_entry;
     860                 :            :         bool skip_base_rule = false;
     861                 :            :         int off, idx, data_off = 0;
     862                 :            :         uint8_t lid, mask, data;
     863                 :            :         struct idev_cfg *idev;
     864                 :            :         uint16_t layer_info;
     865                 :            :         uint64_t lt, flags;
     866                 :            :         struct mbox *mbox;
     867                 :            : 
     868                 :            :         /* Skip till Layer A data start */
     869         [ #  # ]:          0 :         while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
     870         [ #  # ]:          0 :                 if (npc->keyx_supp_nmask[intf] & (1 << bit))
     871                 :          0 :                         data_off++;
     872                 :          0 :                 bit++;
     873                 :            :         }
     874                 :            : 
     875                 :            :         /* Each bit represents 1 nibble */
     876                 :          0 :         data_off *= 4;
     877                 :            : 
     878                 :            :         index = 0;
     879         [ #  # ]:          0 :         for (lid = 0; lid < NPC_MAX_LID; lid++) {
     880                 :            :                 /* Offset in key */
     881                 :          0 :                 off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
     882                 :          0 :                 lt = pst->lt[lid] & 0xf;
     883                 :          0 :                 flags = pst->flags[lid] & 0xff;
     884                 :            : 
     885                 :            :                 /* NPC_LAYER_KEX_S */
     886                 :          0 :                 layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
     887                 :            : 
     888         [ #  # ]:          0 :                 if (layer_info) {
     889         [ #  # ]:          0 :                         for (idx = 0; idx <= 2; idx++) {
     890         [ #  # ]:          0 :                                 if (layer_info & (1 << idx)) {
     891         [ #  # ]:          0 :                                         if (idx == 2) {
     892                 :            :                                                 data = lt;
     893                 :            :                                                 mask = 0xf;
     894         [ #  # ]:          0 :                                         } else if (idx == 1) {
     895                 :          0 :                                                 data = ((flags >> 4) & 0xf);
     896                 :            :                                                 mask = ((flags >> 4) & 0xf);
     897                 :            :                                         } else {
     898                 :          0 :                                                 data = (flags & 0xf);
     899                 :            :                                                 mask = (flags & 0xf);
     900                 :            :                                         }
     901                 :            : 
     902         [ #  # ]:          0 :                                         if (data_off >= 64) {
     903                 :            :                                                 data_off = 0;
     904                 :          0 :                                                 index++;
     905                 :            :                                         }
     906                 :          0 :                                         key_data[index] |=
     907                 :          0 :                                                 ((uint64_t)data << data_off);
     908                 :            : 
     909         [ #  # ]:          0 :                                         if (lt == 0)
     910                 :            :                                                 mask = 0;
     911                 :          0 :                                         key_mask[index] |=
     912                 :          0 :                                                 ((uint64_t)mask << data_off);
     913                 :          0 :                                         data_off += 4;
     914                 :            :                                 }
     915                 :            :                         }
     916                 :            :                 }
     917                 :            :         }
     918                 :            : 
     919                 :            :         /* Copy this into mcam string */
     920                 :          0 :         key_len = (pst->npc->keyx_len[intf] + 7) / 8;
     921         [ #  # ]:          0 :         memcpy(pst->flow->mcam_data, key_data, key_len);
     922                 :          0 :         memcpy(pst->flow->mcam_mask, key_mask, key_len);
     923                 :            : 
     924         [ #  # ]:          0 :         if (pst->set_vlan_ltype_mask)
     925                 :          0 :                 npc_set_vlan_ltype(pst);
     926                 :            : 
     927         [ #  # ]:          0 :         if (pst->set_ipv6ext_ltype_mask)
     928                 :          0 :                 npc_set_ipv6ext_ltype_mask(pst);
     929                 :            : 
     930                 :          0 :         idev = idev_get_cfg();
     931         [ #  # ]:          0 :         if (idev)
     932                 :          0 :                 inl_dev = idev->nix_inl_dev;
     933   [ #  #  #  # ]:          0 :         if (inl_dev && inl_dev->is_multi_channel &&
     934         [ #  # ]:          0 :             (pst->flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC))
     935                 :            :                 skip_base_rule = true;
     936                 :            : 
     937   [ #  #  #  #  :          0 :         if (pst->is_vf && pst->flow->nix_intf == NIX_INTF_RX && !skip_base_rule) {
                   #  # ]
     938                 :          0 :                 mbox = mbox_get(npc->mbox);
     939                 :          0 :                 (void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
     940                 :            :                 rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
     941         [ #  # ]:          0 :                 if (rc) {
     942                 :            :                         mbox_put(mbox);
     943                 :          0 :                         plt_err("Failed to fetch VF's base MCAM entry");
     944                 :          0 :                         return rc;
     945                 :            :                 }
     946                 :            :                 mbox_put(mbox);
     947                 :          0 :                 base_entry = &base_rule_rsp->entry_data;
     948         [ #  # ]:          0 :                 for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
     949                 :          0 :                         pst->flow->mcam_data[idx] |= base_entry->kw[idx];
     950                 :          0 :                         pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
     951                 :            :                 }
     952                 :            :         }
     953                 :            : 
     954                 :            :         /*
     955                 :            :          * Now we have mcam data and mask formatted as
     956                 :            :          * [Key_len/4 nibbles][0 or 1 nibble hole][data]
     957                 :            :          * hole is present if key_len is odd number of nibbles.
     958                 :            :          * mcam data must be split into 64 bits + 48 bits segments
     959                 :            :          * for each back W0, W1.
     960                 :            :          */
     961                 :            : 
     962         [ #  # ]:          0 :         if (mcam_alloc)
     963                 :          0 :                 return npc_mcam_alloc_and_write(npc, pst->flow, pst);
     964                 :            :         else
     965                 :            :                 return 0;
     966                 :            : }
     967                 :            : 
     968                 :            : int
     969                 :          0 : npc_flow_enable_all_entries(struct npc *npc, bool enable)
     970                 :            : {
     971                 :            :         struct nix_inl_dev *inl_dev;
     972                 :            :         struct npc_flow_list *list;
     973                 :            :         struct roc_npc_flow *flow;
     974                 :            :         struct idev_cfg *idev;
     975                 :            :         int rc = 0, idx;
     976                 :            : 
     977                 :            :         /* Free any MCAM counters and delete flow list */
     978         [ #  # ]:          0 :         for (idx = 0; idx < npc->flow_max_priority; idx++) {
     979                 :          0 :                 list = &npc->flow_list[idx];
     980         [ #  # ]:          0 :                 TAILQ_FOREACH(flow, list, next) {
     981                 :          0 :                         flow->enable = enable;
     982                 :          0 :                         rc = npc_mcam_write_entry(npc->mbox, flow);
     983         [ #  # ]:          0 :                         if (rc)
     984                 :          0 :                                 return rc;
     985                 :            :                 }
     986                 :            :         }
     987                 :            : 
     988                 :            :         list = &npc->ipsec_list;
     989                 :          0 :         idev = idev_get_cfg();
     990         [ #  # ]:          0 :         if (!idev)
     991                 :            :                 return 0;
     992                 :          0 :         inl_dev = idev->nix_inl_dev;
     993                 :            : 
     994         [ #  # ]:          0 :         if (inl_dev) {
     995         [ #  # ]:          0 :                 TAILQ_FOREACH(flow, list, next) {
     996                 :          0 :                         flow->enable = enable;
     997                 :          0 :                         rc = npc_mcam_write_entry(inl_dev->dev.mbox, flow);
     998         [ #  # ]:          0 :                         if (rc)
     999                 :          0 :                                 return rc;
    1000                 :            :                 }
    1001                 :            :         }
    1002                 :            :         return rc;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : int
    1006                 :          0 : npc_flow_free_all_resources(struct npc *npc)
    1007                 :            : {
    1008                 :            :         struct roc_npc_flow *flow;
    1009                 :            :         int rc, idx;
    1010                 :            : 
    1011                 :            :         /* Free all MCAM entries allocated */
    1012                 :          0 :         rc = npc_mcam_free_all_entries(npc);
    1013                 :            : 
    1014                 :            :         /* Free any MCAM counters and delete flow list */
    1015         [ #  # ]:          0 :         for (idx = 0; idx < npc->flow_max_priority; idx++) {
    1016         [ #  # ]:          0 :                 while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
    1017                 :          0 :                         npc_rss_group_free(npc, flow);
    1018         [ #  # ]:          0 :                         if (flow->ctr_id != NPC_COUNTER_NONE) {
    1019                 :          0 :                                 rc |= npc_mcam_clear_counter(npc->mbox, flow->ctr_id);
    1020                 :          0 :                                 rc |= npc_mcam_free_counter(npc->mbox, flow->ctr_id);
    1021                 :            :                         }
    1022                 :            : 
    1023                 :          0 :                         npc_delete_prio_list_entry(npc, flow);
    1024                 :            : 
    1025         [ #  # ]:          0 :                         TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
    1026                 :          0 :                         plt_free(flow);
    1027                 :            :                 }
    1028                 :            :         }
    1029                 :          0 :         return rc;
    1030                 :            : }

Generated by: LCOV version 1.14