dpdk/drivers/net/bnxt/bnxt_vnic.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2014-2021 Broadcom
   3 * All rights reserved.
   4 */
   5
   6#include <inttypes.h>
   7
   8#include <rte_memzone.h>
   9#include <rte_malloc.h>
  10
  11#include "bnxt.h"
  12#include "bnxt_vnic.h"
  13#include "hsi_struct_def_dpdk.h"
  14
  15/*
  16 * VNIC Functions
  17 */
  18
  19void prandom_bytes(void *dest_ptr, size_t len)
  20{
  21        char *dest = (char *)dest_ptr;
  22        uint64_t rb;
  23
  24        while (len) {
  25                rb = rte_rand();
  26                if (len >= 8) {
  27                        memcpy(dest, &rb, 8);
  28                        len -= 8;
  29                        dest += 8;
  30                } else {
  31                        memcpy(dest, &rb, len);
  32                        dest += len;
  33                        len = 0;
  34                }
  35        }
  36}
  37
  38static void bnxt_init_vnics(struct bnxt *bp)
  39{
  40        struct bnxt_vnic_info *vnic;
  41        uint16_t max_vnics;
  42        int i;
  43
  44        max_vnics = bp->max_vnics;
  45        STAILQ_INIT(&bp->free_vnic_list);
  46        for (i = 0; i < max_vnics; i++) {
  47                vnic = &bp->vnic_info[i];
  48                vnic->fw_vnic_id = (uint16_t)HWRM_NA_SIGNATURE;
  49                vnic->rss_rule = (uint16_t)HWRM_NA_SIGNATURE;
  50                vnic->cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
  51                vnic->lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
  52                vnic->hash_mode =
  53                        HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
  54                vnic->rx_queue_cnt = 0;
  55
  56                STAILQ_INIT(&vnic->filter);
  57                STAILQ_INIT(&vnic->flow_list);
  58                STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next);
  59        }
  60}
  61
  62struct bnxt_vnic_info *bnxt_alloc_vnic(struct bnxt *bp)
  63{
  64        struct bnxt_vnic_info *vnic;
  65
  66        /* Find the 1st unused vnic from the free_vnic_list pool*/
  67        vnic = STAILQ_FIRST(&bp->free_vnic_list);
  68        if (!vnic) {
  69                PMD_DRV_LOG(ERR, "No more free VNIC resources\n");
  70                return NULL;
  71        }
  72        STAILQ_REMOVE_HEAD(&bp->free_vnic_list, next);
  73        return vnic;
  74}
  75
  76void bnxt_free_all_vnics(struct bnxt *bp)
  77{
  78        struct bnxt_vnic_info *vnic;
  79        unsigned int i;
  80
  81        if (bp->vnic_info == NULL)
  82                return;
  83
  84        for (i = 0; i < bp->max_vnics; i++) {
  85                vnic = &bp->vnic_info[i];
  86                STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next);
  87                vnic->rx_queue_cnt = 0;
  88        }
  89}
  90
  91void bnxt_free_vnic_attributes(struct bnxt *bp)
  92{
  93        struct bnxt_vnic_info *vnic;
  94        unsigned int i;
  95
  96        if (bp->vnic_info == NULL)
  97                return;
  98
  99        for (i = 0; i < bp->max_vnics; i++) {
 100                vnic = &bp->vnic_info[i];
 101                if (vnic->rss_table) {
 102                        /* 'Unreserve' the rss_table */
 103                        /* N/A */
 104
 105                        vnic->rss_table = NULL;
 106                }
 107
 108                if (vnic->rss_hash_key) {
 109                        /* 'Unreserve' the rss_hash_key */
 110                        /* N/A */
 111
 112                        vnic->rss_hash_key = NULL;
 113                }
 114        }
 115}
 116
 117int bnxt_alloc_vnic_attributes(struct bnxt *bp)
 118{
 119        struct bnxt_vnic_info *vnic;
 120        struct rte_pci_device *pdev = bp->pdev;
 121        const struct rte_memzone *mz;
 122        char mz_name[RTE_MEMZONE_NAMESIZE];
 123        uint32_t entry_length;
 124        size_t rss_table_size;
 125        uint16_t max_vnics;
 126        int i;
 127        rte_iova_t mz_phys_addr;
 128
 129        entry_length = HW_HASH_KEY_SIZE +
 130                       BNXT_MAX_MC_ADDRS * RTE_ETHER_ADDR_LEN;
 131
 132        if (BNXT_CHIP_P5(bp))
 133                rss_table_size = BNXT_RSS_TBL_SIZE_P5 *
 134                                 2 * sizeof(*vnic->rss_table);
 135        else
 136                rss_table_size = HW_HASH_INDEX_SIZE * sizeof(*vnic->rss_table);
 137
 138        entry_length = RTE_CACHE_LINE_ROUNDUP(entry_length + rss_table_size);
 139
 140        max_vnics = bp->max_vnics;
 141        snprintf(mz_name, RTE_MEMZONE_NAMESIZE,
 142                 "bnxt_" PCI_PRI_FMT "_vnicattr", pdev->addr.domain,
 143                 pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
 144        mz_name[RTE_MEMZONE_NAMESIZE - 1] = 0;
 145        mz = rte_memzone_lookup(mz_name);
 146        if (!mz) {
 147                mz = rte_memzone_reserve(mz_name,
 148                                entry_length * max_vnics, SOCKET_ID_ANY,
 149                                RTE_MEMZONE_2MB |
 150                                RTE_MEMZONE_SIZE_HINT_ONLY |
 151                                RTE_MEMZONE_IOVA_CONTIG);
 152                if (!mz)
 153                        return -ENOMEM;
 154        }
 155        mz_phys_addr = mz->iova;
 156
 157        for (i = 0; i < max_vnics; i++) {
 158                vnic = &bp->vnic_info[i];
 159
 160                /* Allocate rss table and hash key */
 161                vnic->rss_table =
 162                        (void *)((char *)mz->addr + (entry_length * i));
 163                memset(vnic->rss_table, -1, entry_length);
 164
 165                vnic->rss_table_dma_addr = mz_phys_addr + (entry_length * i);
 166                vnic->rss_hash_key = (void *)((char *)vnic->rss_table +
 167                                              rss_table_size);
 168
 169                vnic->rss_hash_key_dma_addr = vnic->rss_table_dma_addr +
 170                                              rss_table_size;
 171                vnic->mc_list = (void *)((char *)vnic->rss_hash_key +
 172                                HW_HASH_KEY_SIZE);
 173                vnic->mc_list_dma_addr = vnic->rss_hash_key_dma_addr +
 174                                HW_HASH_KEY_SIZE;
 175                prandom_bytes(vnic->rss_hash_key, HW_HASH_KEY_SIZE);
 176        }
 177
 178        return 0;
 179}
 180
 181void bnxt_free_vnic_mem(struct bnxt *bp)
 182{
 183        struct bnxt_vnic_info *vnic;
 184        uint16_t max_vnics, i;
 185
 186        if (bp->vnic_info == NULL)
 187                return;
 188
 189        max_vnics = bp->max_vnics;
 190        for (i = 0; i < max_vnics; i++) {
 191                vnic = &bp->vnic_info[i];
 192                if (vnic->fw_vnic_id != (uint16_t)HWRM_NA_SIGNATURE) {
 193                        PMD_DRV_LOG(ERR, "VNIC is not freed yet!\n");
 194                        /* TODO Call HWRM to free VNIC */
 195                }
 196        }
 197
 198        rte_free(bp->vnic_info);
 199        bp->vnic_info = NULL;
 200}
 201
 202int bnxt_alloc_vnic_mem(struct bnxt *bp)
 203{
 204        struct bnxt_vnic_info *vnic_mem;
 205        uint16_t max_vnics;
 206
 207        max_vnics = bp->max_vnics;
 208        /* Allocate memory for VNIC pool and filter pool */
 209        vnic_mem = rte_zmalloc("bnxt_vnic_info",
 210                               max_vnics * sizeof(struct bnxt_vnic_info), 0);
 211        if (vnic_mem == NULL) {
 212                PMD_DRV_LOG(ERR, "Failed to alloc memory for %d VNICs",
 213                        max_vnics);
 214                return -ENOMEM;
 215        }
 216        bp->vnic_info = vnic_mem;
 217        bnxt_init_vnics(bp);
 218        return 0;
 219}
 220
 221int bnxt_vnic_grp_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 222{
 223        uint32_t size = sizeof(*vnic->fw_grp_ids) * bp->max_ring_grps;
 224
 225        vnic->fw_grp_ids = rte_zmalloc("vnic_fw_grp_ids", size, 0);
 226        if (!vnic->fw_grp_ids) {
 227                PMD_DRV_LOG(ERR,
 228                            "Failed to alloc %d bytes for group ids\n",
 229                            size);
 230                return -ENOMEM;
 231        }
 232        memset(vnic->fw_grp_ids, -1, size);
 233
 234        return 0;
 235}
 236
 237uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
 238{
 239        uint16_t hwrm_type = 0;
 240
 241        if (rte_type & ETH_RSS_IPV4)
 242                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
 243        if (rte_type & ETH_RSS_NONFRAG_IPV4_TCP)
 244                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
 245        if (rte_type & ETH_RSS_NONFRAG_IPV4_UDP)
 246                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
 247        if (rte_type & ETH_RSS_IPV6)
 248                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
 249        if (rte_type & ETH_RSS_NONFRAG_IPV6_TCP)
 250                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
 251        if (rte_type & ETH_RSS_NONFRAG_IPV6_UDP)
 252                hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
 253
 254        return hwrm_type;
 255}
 256
 257int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp, uint64_t hash_f, uint32_t lvl)
 258{
 259        uint32_t mode = HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
 260        bool l3 = (hash_f & (ETH_RSS_IPV4 | ETH_RSS_IPV6));
 261        bool l4 = (hash_f & (ETH_RSS_NONFRAG_IPV4_UDP |
 262                             ETH_RSS_NONFRAG_IPV6_UDP |
 263                             ETH_RSS_NONFRAG_IPV4_TCP |
 264                             ETH_RSS_NONFRAG_IPV6_TCP));
 265        bool l3_only = l3 && !l4;
 266        bool l3_and_l4 = l3 && l4;
 267
 268        /* If FW has not advertised capability to configure outer/inner
 269         * RSS hashing , just log a message. HW will work in default RSS mode.
 270         */
 271        if (!(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS)) {
 272                PMD_DRV_LOG(ERR, "RSS hash level cannot be configured\n");
 273                return mode;
 274        }
 275
 276        switch (lvl) {
 277        case BNXT_RSS_LEVEL_INNERMOST:
 278                if (l3_and_l4 || l4)
 279                        mode =
 280                        HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_4;
 281                else if (l3_only)
 282                        mode =
 283                        HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_2;
 284                break;
 285        case BNXT_RSS_LEVEL_OUTERMOST:
 286                if (l3_and_l4 || l4)
 287                        mode =
 288                        HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_4;
 289                else if (l3_only)
 290                        mode =
 291                        HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_2;
 292                break;
 293        default:
 294                mode = HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
 295                break;
 296        }
 297
 298        return mode;
 299}
 300
 301uint64_t bnxt_hwrm_to_rte_rss_level(struct bnxt *bp, uint32_t mode)
 302{
 303        uint64_t rss_level = 0;
 304
 305        /* If FW has not advertised capability to configure inner/outer RSS
 306         * return default hash mode.
 307         */
 308        if (!(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS))
 309                return ETH_RSS_LEVEL_PMD_DEFAULT;
 310
 311        if (mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_2 ||
 312            mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_4)
 313                rss_level |= ETH_RSS_LEVEL_OUTERMOST;
 314        else if (mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_2 ||
 315                 mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_4)
 316                rss_level |= ETH_RSS_LEVEL_INNERMOST;
 317        else
 318                rss_level |= ETH_RSS_LEVEL_PMD_DEFAULT;
 319
 320        return rss_level;
 321}
 322