dpdk/drivers/common/cnxk/roc_npc_mcam.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(C) 2021 Marvell.
   3 */
   4#include "roc_api.h"
   5#include "roc_priv.h"
   6
   7static int
   8npc_mcam_alloc_counter(struct npc *npc, uint16_t *ctr)
   9{
  10        struct npc_mcam_alloc_counter_req *req;
  11        struct npc_mcam_alloc_counter_rsp *rsp;
  12        struct mbox *mbox = npc->mbox;
  13        int rc = -ENOSPC;
  14
  15        req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox);
  16        if (req == NULL)
  17                return rc;
  18        req->count = 1;
  19        rc = mbox_process_msg(mbox, (void *)&rsp);
  20        if (rc)
  21                return rc;
  22        *ctr = rsp->cntr_list[0];
  23        return rc;
  24}
  25
  26int
  27npc_mcam_free_counter(struct npc *npc, uint16_t ctr_id)
  28{
  29        struct npc_mcam_oper_counter_req *req;
  30        struct mbox *mbox = npc->mbox;
  31        int rc = -ENOSPC;
  32
  33        req = mbox_alloc_msg_npc_mcam_free_counter(mbox);
  34        if (req == NULL)
  35                return rc;
  36        req->cntr = ctr_id;
  37        return mbox_process(mbox);
  38}
  39
  40int
  41npc_mcam_read_counter(struct npc *npc, uint32_t ctr_id, uint64_t *count)
  42{
  43        struct npc_mcam_oper_counter_req *req;
  44        struct npc_mcam_oper_counter_rsp *rsp;
  45        struct mbox *mbox = npc->mbox;
  46        int rc = -ENOSPC;
  47
  48        req = mbox_alloc_msg_npc_mcam_counter_stats(mbox);
  49        if (req == NULL)
  50                return rc;
  51        req->cntr = ctr_id;
  52        rc = mbox_process_msg(mbox, (void *)&rsp);
  53        if (rc)
  54                return rc;
  55        *count = rsp->stat;
  56        return rc;
  57}
  58
  59int
  60npc_mcam_clear_counter(struct npc *npc, uint32_t ctr_id)
  61{
  62        struct npc_mcam_oper_counter_req *req;
  63        struct mbox *mbox = npc->mbox;
  64        int rc = -ENOSPC;
  65
  66        req = mbox_alloc_msg_npc_mcam_clear_counter(mbox);
  67        if (req == NULL)
  68                return rc;
  69        req->cntr = ctr_id;
  70        return mbox_process(mbox);
  71}
  72
  73int
  74npc_mcam_free_entry(struct npc *npc, uint32_t entry)
  75{
  76        struct npc_mcam_free_entry_req *req;
  77        struct mbox *mbox = npc->mbox;
  78        int rc = -ENOSPC;
  79
  80        req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
  81        if (req == NULL)
  82                return rc;
  83        req->entry = entry;
  84        return mbox_process(mbox);
  85}
  86
  87int
  88npc_mcam_free_all_entries(struct npc *npc)
  89{
  90        struct npc_mcam_free_entry_req *req;
  91        struct mbox *mbox = npc->mbox;
  92        int rc = -ENOSPC;
  93
  94        req = mbox_alloc_msg_npc_mcam_free_entry(mbox);
  95        if (req == NULL)
  96                return rc;
  97        req->all = 1;
  98        return mbox_process(mbox);
  99}
 100
 101static int
 102npc_supp_key_len(uint32_t supp_mask)
 103{
 104        int nib_count = 0;
 105
 106        while (supp_mask) {
 107                nib_count++;
 108                supp_mask &= (supp_mask - 1);
 109        }
 110        return nib_count * 4;
 111}
 112
 113/**
 114 * Returns true if any LDATA bits are extracted for specific LID+LTYPE.
 115 *
 116 * No LFLAG extraction is taken into account.
 117 */
 118static int
 119npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
 120{
 121        struct npc_xtract_info *x_info;
 122        int i;
 123
 124        for (i = 0; i < NPC_MAX_LD; i++) {
 125                x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
 126                /* Check for LDATA */
 127                if (x_info->enable && x_info->len > 0)
 128                        return true;
 129        }
 130
 131        return false;
 132}
 133
 134static void
 135npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid,
 136                         uint8_t lt, uint8_t ld)
 137{
 138        struct npc_xtract_info *x_info, *infoflag;
 139        int hdr_off, keylen;
 140        npc_dxcfg_t *p;
 141        npc_fxcfg_t *q;
 142        int i, j;
 143
 144        p = &npc->prx_dxcfg;
 145        x_info = &(*p)[0][lid][lt].xtract[ld];
 146
 147        if (x_info->enable == 0)
 148                return;
 149
 150        hdr_off = x_info->hdr_off * 8;
 151        keylen = x_info->len * 8;
 152        for (i = hdr_off; i < (hdr_off + keylen); i++)
 153                plt_bitmap_set(bmap, i);
 154
 155        if (x_info->flags_enable == 0)
 156                return;
 157
 158        if ((npc->prx_lfcfg[0].i & 0x7) != lid)
 159                return;
 160
 161        q = &npc->prx_fxcfg;
 162        for (j = 0; j < NPC_MAX_LFL; j++) {
 163                infoflag = &(*q)[0][ld][j].xtract[0];
 164                if (infoflag->enable) {
 165                        hdr_off = infoflag->hdr_off * 8;
 166                        keylen = infoflag->len * 8;
 167                        for (i = hdr_off; i < (hdr_off + keylen); i++)
 168                                plt_bitmap_set(bmap, i);
 169                }
 170        }
 171}
 172
 173/**
 174 * Check if given LID+LTYPE combination is present in KEX
 175 *
 176 * len is non-zero, this function will return true if KEX extracts len bytes
 177 * at given offset. Otherwise it'll return true if any bytes are extracted
 178 * specifically for given LID+LTYPE combination (meaning not LFLAG based).
 179 * The second case increases flexibility for custom frames whose extracted
 180 * bits may change depending on KEX profile loaded.
 181 *
 182 * @param npc NPC context structure
 183 * @param lid Layer ID to check for
 184 * @param lt Layer Type to check for
 185 * @param offset offset into the layer header to match
 186 * @param len length of the match
 187 */
 188static bool
 189npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset,
 190                   int len)
 191{
 192        struct plt_bitmap *bmap;
 193        uint32_t bmap_sz;
 194        uint8_t *mem;
 195        int i;
 196
 197        if (!len)
 198                return npc_lid_lt_in_kex(npc, lid, lt);
 199
 200        bmap_sz = plt_bitmap_get_memory_footprint(300 * 8);
 201        mem = plt_zmalloc(bmap_sz, 0);
 202        if (mem == NULL) {
 203                plt_err("mem alloc failed");
 204                return false;
 205        }
 206        bmap = plt_bitmap_init(300 * 8, mem, bmap_sz);
 207        if (bmap == NULL) {
 208                plt_err("mem alloc failed");
 209                plt_free(mem);
 210                return false;
 211        }
 212
 213        npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
 214        npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
 215
 216        for (i = offset; i < (offset + len); i++) {
 217                if (plt_bitmap_get(bmap, i) != 0x1) {
 218                        plt_free(mem);
 219                        return false;
 220                }
 221        }
 222
 223        plt_free(mem);
 224        return true;
 225}
 226
 227uint64_t
 228npc_get_kex_capability(struct npc *npc)
 229{
 230        npc_kex_cap_terms_t kex_cap;
 231
 232        memset(&kex_cap, 0, sizeof(kex_cap));
 233
 234        /* Ethtype: Offset 12B, len 2B */
 235        kex_cap.bit.ethtype_0 = npc_is_kex_enabled(
 236                npc, NPC_LID_LA, NPC_LT_LA_ETHER, 12 * 8, 2 * 8);
 237        /* QINQ VLAN Ethtype: ofset 8B, len 2B */
 238        kex_cap.bit.ethtype_x = npc_is_kex_enabled(
 239                npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8 * 8, 2 * 8);
 240        /* VLAN ID0 : Outer VLAN: Offset 2B, len 2B */
 241        kex_cap.bit.vlan_id_0 = npc_is_kex_enabled(
 242                npc, NPC_LID_LB, NPC_LT_LB_CTAG, 2 * 8, 2 * 8);
 243        /* VLAN ID0 : Inner VLAN: offset 6B, len 2B */
 244        kex_cap.bit.vlan_id_x = npc_is_kex_enabled(
 245                npc, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6 * 8, 2 * 8);
 246        /* DMCA: offset 0B, len 6B */
 247        kex_cap.bit.dmac = npc_is_kex_enabled(npc, NPC_LID_LA, NPC_LT_LA_ETHER,
 248                                              0 * 8, 6 * 8);
 249        /* IP proto: offset 9B, len 1B */
 250        kex_cap.bit.ip_proto =
 251                npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP, 9 * 8, 1 * 8);
 252        /* UDP dport: offset 2B, len 2B */
 253        kex_cap.bit.udp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
 254                                                   NPC_LT_LD_UDP, 2 * 8, 2 * 8);
 255        /* UDP sport: offset 0B, len 2B */
 256        kex_cap.bit.udp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
 257                                                   NPC_LT_LD_UDP, 0 * 8, 2 * 8);
 258        /* TCP dport: offset 2B, len 2B */
 259        kex_cap.bit.tcp_dport = npc_is_kex_enabled(npc, NPC_LID_LD,
 260                                                   NPC_LT_LD_TCP, 2 * 8, 2 * 8);
 261        /* TCP sport: offset 0B, len 2B */
 262        kex_cap.bit.tcp_sport = npc_is_kex_enabled(npc, NPC_LID_LD,
 263                                                   NPC_LT_LD_TCP, 0 * 8, 2 * 8);
 264        /* IP SIP: offset 12B, len 4B */
 265        kex_cap.bit.sip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
 266                                                  12 * 8, 4 * 8);
 267        /* IP DIP: offset 14B, len 4B */
 268        kex_cap.bit.dip_addr = npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_IP,
 269                                                  14 * 8, 4 * 8);
 270        /* IP6 SIP: offset 8B, len 16B */
 271        kex_cap.bit.sip6_addr = npc_is_kex_enabled(
 272                npc, NPC_LID_LC, NPC_LT_LC_IP6, 8 * 8, 16 * 8);
 273        /* IP6 DIP: offset 24B, len 16B */
 274        kex_cap.bit.dip6_addr = npc_is_kex_enabled(
 275                npc, NPC_LID_LC, NPC_LT_LC_IP6, 24 * 8, 16 * 8);
 276        /* ESP SPI: offset 0B, len 4B */
 277        kex_cap.bit.ipsec_spi = npc_is_kex_enabled(npc, NPC_LID_LE,
 278                                                   NPC_LT_LE_ESP, 0 * 8, 4 * 8);
 279        /* VXLAN VNI: offset 4B, len 3B */
 280        kex_cap.bit.ld_vni = npc_is_kex_enabled(npc, NPC_LID_LE,
 281                                                NPC_LT_LE_VXLAN, 0 * 8, 3 * 8);
 282
 283        /* Custom L3 frame: varied offset and lengths */
 284        kex_cap.bit.custom_l3 =
 285                npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM0, 0, 0);
 286        kex_cap.bit.custom_l3 |=
 287                npc_is_kex_enabled(npc, NPC_LID_LC, NPC_LT_LC_CUSTOM1, 0, 0);
 288        /* SCTP sport : offset 0B, len 2B */
 289        kex_cap.bit.sctp_sport = npc_is_kex_enabled(
 290                npc, NPC_LID_LD, NPC_LT_LD_SCTP, 0 * 8, 2 * 8);
 291        /* SCTP dport : offset 2B, len 2B */
 292        kex_cap.bit.sctp_dport = npc_is_kex_enabled(
 293                npc, NPC_LID_LD, NPC_LT_LD_SCTP, 2 * 8, 2 * 8);
 294        /* ICMP type : offset 0B, len 1B */
 295        kex_cap.bit.icmp_type = npc_is_kex_enabled(
 296                npc, NPC_LID_LD, NPC_LT_LD_ICMP, 0 * 8, 1 * 8);
 297        /* ICMP code : offset 1B, len 1B */
 298        kex_cap.bit.icmp_code = npc_is_kex_enabled(
 299                npc, NPC_LID_LD, NPC_LT_LD_ICMP, 1 * 8, 1 * 8);
 300        /* ICMP id : offset 4B, len 2B */
 301        kex_cap.bit.icmp_id = npc_is_kex_enabled(npc, NPC_LID_LD,
 302                                                 NPC_LT_LD_ICMP, 4 * 8, 2 * 8);
 303        /* IGMP grp_addr : offset 4B, len 4B */
 304        kex_cap.bit.igmp_grp_addr = npc_is_kex_enabled(
 305                npc, NPC_LID_LD, NPC_LT_LD_IGMP, 4 * 8, 4 * 8);
 306        /* GTPU teid : offset 4B, len 4B */
 307        kex_cap.bit.gtpu_teid = npc_is_kex_enabled(
 308                npc, NPC_LID_LE, NPC_LT_LE_GTPU, 4 * 8, 4 * 8);
 309        return kex_cap.all_bits;
 310}
 311
 312#define BYTESM1_SHIFT 16
 313#define HDR_OFF_SHIFT 8
 314static void
 315npc_update_kex_info(struct npc_xtract_info *xtract_info, uint64_t val)
 316{
 317        xtract_info->len = ((val >> BYTESM1_SHIFT) & 0xf) + 1;
 318        xtract_info->hdr_off = (val >> HDR_OFF_SHIFT) & 0xff;
 319        xtract_info->key_off = val & 0x3f;
 320        xtract_info->enable = ((val >> 7) & 0x1);
 321        xtract_info->flags_enable = ((val >> 6) & 0x1);
 322}
 323
 324int
 325npc_mcam_alloc_entries(struct npc *npc, int ref_mcam, int *alloc_entry,
 326                       int req_count, int prio, int *resp_count)
 327{
 328        struct npc_mcam_alloc_entry_req *req;
 329        struct npc_mcam_alloc_entry_rsp *rsp;
 330        struct mbox *mbox = npc->mbox;
 331        int rc = -ENOSPC;
 332        int i;
 333
 334        req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
 335        if (req == NULL)
 336                return rc;
 337        req->contig = 0;
 338        req->count = req_count;
 339        req->priority = prio;
 340        req->ref_entry = ref_mcam;
 341
 342        rc = mbox_process_msg(mbox, (void *)&rsp);
 343        if (rc)
 344                return rc;
 345        for (i = 0; i < rsp->count; i++)
 346                alloc_entry[i] = rsp->entry_list[i];
 347        *resp_count = rsp->count;
 348        return 0;
 349}
 350
 351int
 352npc_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        struct mbox *mbox = npc->mbox;
 358        int rc = -ENOSPC;
 359
 360        req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
 361        if (req == NULL)
 362                return rc;
 363        req->contig = 1;
 364        req->count = 1;
 365        req->priority = prio;
 366        req->ref_entry = ref_mcam->mcam_id;
 367
 368        rc = mbox_process_msg(mbox, (void *)&rsp);
 369        if (rc)
 370                return rc;
 371        memset(mcam, 0, sizeof(struct roc_npc_flow));
 372        mcam->mcam_id = rsp->entry;
 373        mcam->nix_intf = ref_mcam->nix_intf;
 374        *resp_count = rsp->count;
 375        return 0;
 376}
 377
 378int
 379npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable)
 380{
 381        struct npc_mcam_ena_dis_entry_req *req;
 382        struct mbox *mbox = npc->mbox;
 383        int rc = -ENOSPC;
 384
 385        if (enable)
 386                req = mbox_alloc_msg_npc_mcam_ena_entry(mbox);
 387        else
 388                req = mbox_alloc_msg_npc_mcam_dis_entry(mbox);
 389
 390        if (req == NULL)
 391                return rc;
 392        req->entry = mcam->mcam_id;
 393        mcam->enable = enable;
 394        return mbox_process(mbox);
 395}
 396
 397int
 398npc_mcam_write_entry(struct npc *npc, struct roc_npc_flow *mcam)
 399{
 400        struct npc_mcam_write_entry_req *req;
 401        struct mbox *mbox = npc->mbox;
 402        struct mbox_msghdr *rsp;
 403        int rc = -ENOSPC;
 404        int i;
 405
 406        req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
 407        if (req == NULL)
 408                return rc;
 409        req->entry = mcam->mcam_id;
 410        req->intf = mcam->nix_intf;
 411        req->enable_entry = mcam->enable;
 412        req->entry_data.action = mcam->npc_action;
 413        req->entry_data.vtag_action = mcam->vtag_action;
 414        for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
 415                req->entry_data.kw[i] = mcam->mcam_data[i];
 416                req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
 417        }
 418        return mbox_process_msg(mbox, (void *)&rsp);
 419}
 420
 421static void
 422npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
 423{
 424        volatile uint64_t(
 425                *q)[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
 426        struct npc_xtract_info *x_info = NULL;
 427        int lid, lt, ld, fl, ix;
 428        npc_dxcfg_t *p;
 429        uint64_t keyw;
 430        uint64_t val;
 431
 432        npc->keyx_supp_nmask[NPC_MCAM_RX] =
 433                kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
 434        npc->keyx_supp_nmask[NPC_MCAM_TX] =
 435                kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
 436        npc->keyx_len[NPC_MCAM_RX] =
 437                npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
 438        npc->keyx_len[NPC_MCAM_TX] =
 439                npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
 440
 441        keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
 442        npc->keyw[NPC_MCAM_RX] = keyw;
 443        keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
 444        npc->keyw[NPC_MCAM_TX] = keyw;
 445
 446        /* Update KEX_LD_FLAG */
 447        for (ix = 0; ix < NPC_MAX_INTF; ix++) {
 448                for (ld = 0; ld < NPC_MAX_LD; ld++) {
 449                        for (fl = 0; fl < NPC_MAX_LFL; fl++) {
 450                                x_info = &npc->prx_fxcfg[ix][ld][fl].xtract[0];
 451                                val = kex_rsp->intf_ld_flags[ix][ld][fl];
 452                                npc_update_kex_info(x_info, val);
 453                        }
 454                }
 455        }
 456
 457        /* Update LID, LT and LDATA cfg */
 458        p = &npc->prx_dxcfg;
 459        q = (volatile uint64_t(*)[][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD])(
 460                &kex_rsp->intf_lid_lt_ld);
 461        for (ix = 0; ix < NPC_MAX_INTF; ix++) {
 462                for (lid = 0; lid < NPC_MAX_LID; lid++) {
 463                        for (lt = 0; lt < NPC_MAX_LT; lt++) {
 464                                for (ld = 0; ld < NPC_MAX_LD; ld++) {
 465                                        x_info = &(*p)[ix][lid][lt].xtract[ld];
 466                                        val = (*q)[ix][lid][lt][ld];
 467                                        npc_update_kex_info(x_info, val);
 468                                }
 469                        }
 470                }
 471        }
 472        /* Update LDATA Flags cfg */
 473        npc->prx_lfcfg[0].i = kex_rsp->kex_ld_flags[0];
 474        npc->prx_lfcfg[1].i = kex_rsp->kex_ld_flags[1];
 475}
 476
 477int
 478npc_mcam_fetch_kex_cfg(struct npc *npc)
 479{
 480        struct npc_get_kex_cfg_rsp *kex_rsp;
 481        struct mbox *mbox = npc->mbox;
 482        int rc = 0;
 483
 484        mbox_alloc_msg_npc_get_kex_cfg(mbox);
 485        rc = mbox_process_msg(mbox, (void *)&kex_rsp);
 486        if (rc) {
 487                plt_err("Failed to fetch NPC KEX config");
 488                goto done;
 489        }
 490
 491        mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name,
 492                    MKEX_NAME_LEN);
 493
 494        npc_mcam_process_mkex_cfg(npc, kex_rsp);
 495
 496done:
 497        return rc;
 498}
 499
 500int
 501npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow,
 502                         struct npc_parse_state *pst)
 503{
 504        int use_ctr = (flow->ctr_id == NPC_COUNTER_NONE ? 0 : 1);
 505        struct npc_mcam_write_entry_req *req;
 506        struct mbox *mbox = npc->mbox;
 507        struct mbox_msghdr *rsp;
 508        uint16_t ctr = ~(0);
 509        int rc, idx;
 510        int entry;
 511
 512        PLT_SET_USED(pst);
 513
 514        if (use_ctr) {
 515                rc = npc_mcam_alloc_counter(npc, &ctr);
 516                if (rc)
 517                        return rc;
 518        }
 519
 520        entry = npc_check_preallocated_entry_cache(mbox, flow, npc);
 521        if (entry < 0) {
 522                npc_mcam_free_counter(npc, ctr);
 523                return NPC_ERR_MCAM_ALLOC;
 524        }
 525
 526        req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
 527        if (req == NULL)
 528                return -ENOSPC;
 529        req->set_cntr = use_ctr;
 530        req->cntr = ctr;
 531        req->entry = entry;
 532
 533        req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
 534        req->enable_entry = 1;
 535        req->entry_data.action = flow->npc_action;
 536
 537        /*
 538         * Driver sets vtag action on per interface basis, not
 539         * per flow basis. It is a matter of how we decide to support
 540         * this pmd specific behavior. There are two ways:
 541         *      1. Inherit the vtag action from the one configured
 542         *         for this interface. This can be read from the
 543         *         vtag_action configured for default mcam entry of
 544         *         this pf_func.
 545         *      2. Do not support vtag action with npc_flow.
 546         *
 547         * Second approach is used now.
 548         */
 549        req->entry_data.vtag_action = 0ULL;
 550
 551        for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
 552                req->entry_data.kw[idx] = flow->mcam_data[idx];
 553                req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
 554        }
 555
 556        if (flow->nix_intf == NIX_INTF_RX) {
 557                req->entry_data.kw[0] |= (uint64_t)npc->channel;
 558                req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
 559        } else {
 560                uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 561
 562                pf_func = plt_cpu_to_be_16(pf_func);
 563                req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
 564                req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
 565        }
 566
 567        rc = mbox_process_msg(mbox, (void *)&rsp);
 568        if (rc != 0)
 569                return rc;
 570
 571        flow->mcam_id = entry;
 572        if (use_ctr)
 573                flow->ctr_id = ctr;
 574        return 0;
 575}
 576
 577int
 578npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 579{
 580        struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 581        /* This is non-LDATA part in search key */
 582        uint64_t key_data[2] = {0ULL, 0ULL};
 583        uint64_t key_mask[2] = {0ULL, 0ULL};
 584        int key_len, bit = 0, index, rc = 0;
 585        int intf = pst->flow->nix_intf;
 586        struct mcam_entry *base_entry;
 587        int off, idx, data_off = 0;
 588        uint8_t lid, mask, data;
 589        uint16_t layer_info;
 590        uint64_t lt, flags;
 591
 592        /* Skip till Layer A data start */
 593        while (bit < NPC_PARSE_KEX_S_LA_OFFSET) {
 594                if (npc->keyx_supp_nmask[intf] & (1 << bit))
 595                        data_off++;
 596                bit++;
 597        }
 598
 599        /* Each bit represents 1 nibble */
 600        data_off *= 4;
 601
 602        index = 0;
 603        for (lid = 0; lid < NPC_MAX_LID; lid++) {
 604                /* Offset in key */
 605                off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
 606                lt = pst->lt[lid] & 0xf;
 607                flags = pst->flags[lid] & 0xff;
 608
 609                /* NPC_LAYER_KEX_S */
 610                layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
 611
 612                if (layer_info) {
 613                        for (idx = 0; idx <= 2; idx++) {
 614                                if (layer_info & (1 << idx)) {
 615                                        if (idx == 2)
 616                                                data = lt;
 617                                        else if (idx == 1)
 618                                                data = ((flags >> 4) & 0xf);
 619                                        else
 620                                                data = (flags & 0xf);
 621
 622                                        if (data_off >= 64) {
 623                                                data_off = 0;
 624                                                index++;
 625                                        }
 626                                        key_data[index] |=
 627                                                ((uint64_t)data << data_off);
 628                                        mask = 0xf;
 629                                        if (lt == 0)
 630                                                mask = 0;
 631                                        key_mask[index] |=
 632                                                ((uint64_t)mask << data_off);
 633                                        data_off += 4;
 634                                }
 635                        }
 636                }
 637        }
 638
 639        /* Copy this into mcam string */
 640        key_len = (pst->npc->keyx_len[intf] + 7) / 8;
 641        memcpy(pst->flow->mcam_data, key_data, key_len);
 642        memcpy(pst->flow->mcam_mask, key_mask, key_len);
 643
 644        if (pst->is_vf) {
 645                (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox);
 646                rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp);
 647                if (rc) {
 648                        plt_err("Failed to fetch VF's base MCAM entry");
 649                        return rc;
 650                }
 651                base_entry = &base_rule_rsp->entry_data;
 652                for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
 653                        pst->flow->mcam_data[idx] |= base_entry->kw[idx];
 654                        pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
 655                }
 656        }
 657
 658        /*
 659         * Now we have mcam data and mask formatted as
 660         * [Key_len/4 nibbles][0 or 1 nibble hole][data]
 661         * hole is present if key_len is odd number of nibbles.
 662         * mcam data must be split into 64 bits + 48 bits segments
 663         * for each back W0, W1.
 664         */
 665
 666        if (mcam_alloc)
 667                return npc_mcam_alloc_and_write(npc, pst->flow, pst);
 668        else
 669                return 0;
 670}
 671
 672int
 673npc_flow_free_all_resources(struct npc *npc)
 674{
 675        struct npc_mcam_ents_info *info;
 676        struct roc_npc_flow *flow;
 677        struct plt_bitmap *bmap;
 678        int entry_count = 0;
 679        int rc, idx;
 680
 681        for (idx = 0; idx < npc->flow_max_priority; idx++) {
 682                info = &npc->flow_entry_info[idx];
 683                entry_count += info->live_ent;
 684        }
 685
 686        if (entry_count == 0)
 687                return 0;
 688
 689        /* Free all MCAM entries allocated */
 690        rc = npc_mcam_free_all_entries(npc);
 691
 692        /* Free any MCAM counters and delete flow list */
 693        for (idx = 0; idx < npc->flow_max_priority; idx++) {
 694                while ((flow = TAILQ_FIRST(&npc->flow_list[idx])) != NULL) {
 695                        npc_rss_group_free(npc, flow);
 696                        if (flow->ctr_id != NPC_COUNTER_NONE)
 697                                rc |= npc_mcam_free_counter(npc, flow->ctr_id);
 698
 699                        TAILQ_REMOVE(&npc->flow_list[idx], flow, next);
 700                        plt_free(flow);
 701                        bmap = npc->live_entries[flow->priority];
 702                        plt_bitmap_clear(bmap, flow->mcam_id);
 703                }
 704                info = &npc->flow_entry_info[idx];
 705                info->free_ent = 0;
 706                info->live_ent = 0;
 707        }
 708        return rc;
 709}
 710