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 19 void 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 38 static 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 62 struct 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 76 void 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 91 void 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 117 int 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 181 void 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 202 int 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 221 int 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 237 uint16_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 257 int 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 301 uint64_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