Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2014-2023 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_rxq.h"
13 : : #include "bnxt_rxr.h"
14 : : #include "bnxt_ring.h"
15 : : #include "bnxt_vnic.h"
16 : : #include "hsi_struct_def_dpdk.h"
17 : : #include "bnxt_hwrm.h"
18 : :
19 : : /* Macros to manipulate vnic bitmaps*/
20 : : #define BNXT_VNIC_BITMAP_SIZE 64
21 : : #define BNXT_VNIC_BITMAP_SET(b, i) ((b[(i) / BNXT_VNIC_BITMAP_SIZE]) |= \
22 : : (1UL << ((BNXT_VNIC_BITMAP_SIZE - 1) - \
23 : : ((i) % BNXT_VNIC_BITMAP_SIZE))))
24 : :
25 : : #define BNXT_VNIC_BITMAP_RESET(b, i) ((b[(i) / BNXT_VNIC_BITMAP_SIZE]) &= \
26 : : (~(1UL << ((BNXT_VNIC_BITMAP_SIZE - 1) - \
27 : : ((i) % BNXT_VNIC_BITMAP_SIZE)))))
28 : :
29 : : #define BNXT_VNIC_BITMAP_GET(b, i) (((b[(i) / BNXT_VNIC_BITMAP_SIZE]) >> \
30 : : ((BNXT_VNIC_BITMAP_SIZE - 1) - \
31 : : ((i) % BNXT_VNIC_BITMAP_SIZE))) & 1)
32 : :
33 : : /*
34 : : * VNIC Functions
35 : : */
36 : :
37 : 0 : void bnxt_prandom_bytes(void *dest_ptr, size_t len)
38 : : {
39 : : char *dest = (char *)dest_ptr;
40 : : uint64_t rb;
41 : :
42 [ # # ]: 0 : while (len) {
43 : 0 : rb = rte_rand();
44 [ # # ]: 0 : if (len >= 8) {
45 : : memcpy(dest, &rb, 8);
46 : 0 : len -= 8;
47 : 0 : dest += 8;
48 : : } else {
49 : : memcpy(dest, &rb, len);
50 : : dest += len;
51 : : len = 0;
52 : : }
53 : : }
54 : 0 : }
55 : :
56 : 0 : static void bnxt_init_vnics(struct bnxt *bp)
57 : : {
58 : : struct bnxt_vnic_info *vnic;
59 : : uint16_t max_vnics;
60 : : int i;
61 : :
62 : 0 : max_vnics = bp->max_vnics;
63 : 0 : STAILQ_INIT(&bp->free_vnic_list);
64 [ # # ]: 0 : for (i = 0; i < max_vnics; i++) {
65 : 0 : vnic = &bp->vnic_info[i];
66 : 0 : vnic->fw_vnic_id = (uint16_t)HWRM_NA_SIGNATURE;
67 : 0 : vnic->rss_rule = (uint16_t)HWRM_NA_SIGNATURE;
68 : 0 : vnic->cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
69 : 0 : vnic->lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
70 : 0 : vnic->hash_mode =
71 : : HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
72 : 0 : vnic->prev_hash_mode =
73 : : HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
74 : 0 : vnic->rx_queue_cnt = 0;
75 : :
76 : 0 : STAILQ_INIT(&vnic->filter);
77 : 0 : STAILQ_INIT(&vnic->flow_list);
78 : 0 : STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next);
79 : : }
80 : 0 : }
81 : :
82 : 0 : struct bnxt_vnic_info *bnxt_alloc_vnic(struct bnxt *bp)
83 : : {
84 : : struct bnxt_vnic_info *vnic;
85 : :
86 : : /* Find the 1st unused vnic from the free_vnic_list pool*/
87 : 0 : vnic = STAILQ_FIRST(&bp->free_vnic_list);
88 [ # # ]: 0 : if (!vnic) {
89 : 0 : PMD_DRV_LOG(ERR, "No more free VNIC resources\n");
90 : 0 : return NULL;
91 : : }
92 [ # # ]: 0 : STAILQ_REMOVE_HEAD(&bp->free_vnic_list, next);
93 : : return vnic;
94 : : }
95 : :
96 : 0 : void bnxt_free_all_vnics(struct bnxt *bp)
97 : : {
98 : : struct bnxt_vnic_info *vnic;
99 : : unsigned int i;
100 : :
101 [ # # ]: 0 : if (bp->vnic_info == NULL)
102 : : return;
103 : :
104 [ # # ]: 0 : for (i = 0; i < bp->max_vnics; i++) {
105 : 0 : vnic = &bp->vnic_info[i];
106 : 0 : STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next);
107 [ # # ]: 0 : if (vnic->ref_cnt) {
108 : : /* clean up the default vnic details */
109 : 0 : bnxt_vnic_rss_action_free(bp, i);
110 : : }
111 : :
112 : 0 : vnic->rx_queue_cnt = 0;
113 : : }
114 : : }
115 : :
116 : 0 : void bnxt_free_vnic_attributes(struct bnxt *bp)
117 : : {
118 : : struct bnxt_vnic_info *vnic;
119 : : unsigned int i;
120 : :
121 [ # # ]: 0 : if (bp->vnic_info == NULL)
122 : : return;
123 : :
124 [ # # ]: 0 : for (i = 0; i < bp->max_vnics; i++) {
125 : 0 : vnic = &bp->vnic_info[i];
126 [ # # ]: 0 : if (vnic->rss_mz != NULL) {
127 : 0 : rte_memzone_free(vnic->rss_mz);
128 : 0 : vnic->rss_mz = NULL;
129 : 0 : vnic->rss_hash_key = NULL;
130 : 0 : vnic->rss_table = NULL;
131 : : }
132 : : }
133 : : }
134 : :
135 : 0 : int bnxt_alloc_vnic_attributes(struct bnxt *bp, bool reconfig)
136 : : {
137 : : struct bnxt_vnic_info *vnic;
138 : 0 : struct rte_pci_device *pdev = bp->pdev;
139 : : const struct rte_memzone *mz;
140 : : char mz_name[RTE_MEMZONE_NAMESIZE];
141 : : uint32_t entry_length;
142 : : size_t rss_table_size;
143 : : int i;
144 : : rte_iova_t mz_phys_addr;
145 : :
146 : : entry_length = HW_HASH_KEY_SIZE;
147 : :
148 [ # # ]: 0 : if (BNXT_CHIP_P5(bp))
149 : : rss_table_size = BNXT_RSS_TBL_SIZE_P5 *
150 : : 2 * sizeof(*vnic->rss_table);
151 : : else
152 : : rss_table_size = HW_HASH_INDEX_SIZE * sizeof(*vnic->rss_table);
153 : :
154 : 0 : entry_length = RTE_CACHE_LINE_ROUNDUP(entry_length + rss_table_size);
155 : :
156 [ # # ]: 0 : for (i = 0; i < bp->max_vnics; i++) {
157 : 0 : vnic = &bp->vnic_info[i];
158 : :
159 : 0 : snprintf(mz_name, RTE_MEMZONE_NAMESIZE,
160 : : "bnxt_" PCI_PRI_FMT "_vnicattr_%d", pdev->addr.domain,
161 : 0 : pdev->addr.bus, pdev->addr.devid, pdev->addr.function, i);
162 : 0 : mz_name[RTE_MEMZONE_NAMESIZE - 1] = 0;
163 : 0 : mz = rte_memzone_lookup(mz_name);
164 [ # # ]: 0 : if (mz == NULL) {
165 : 0 : mz = rte_memzone_reserve(mz_name,
166 : : entry_length,
167 : 0 : bp->eth_dev->device->numa_node,
168 : : RTE_MEMZONE_2MB |
169 : : RTE_MEMZONE_SIZE_HINT_ONLY |
170 : : RTE_MEMZONE_IOVA_CONTIG);
171 [ # # ]: 0 : if (mz == NULL) {
172 : 0 : PMD_DRV_LOG(ERR, "Cannot allocate bnxt vnic_attributes memory\n");
173 : 0 : return -ENOMEM;
174 : : }
175 : : }
176 : 0 : vnic->rss_mz = mz;
177 : 0 : mz_phys_addr = mz->iova;
178 : :
179 : : /* Allocate rss table and hash key */
180 : 0 : vnic->rss_table = (void *)((char *)mz->addr);
181 : 0 : vnic->rss_table_dma_addr = mz_phys_addr;
182 [ # # ]: 0 : memset(vnic->rss_table, -1, entry_length);
183 : :
184 : 0 : vnic->rss_hash_key = (void *)((char *)vnic->rss_table + rss_table_size);
185 : 0 : vnic->rss_hash_key_dma_addr = vnic->rss_table_dma_addr + rss_table_size;
186 [ # # ]: 0 : if (!reconfig) {
187 : 0 : bnxt_prandom_bytes(vnic->rss_hash_key, HW_HASH_KEY_SIZE);
188 : 0 : memcpy(bp->rss_conf.rss_key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
189 : : } else {
190 : 0 : memcpy(vnic->rss_hash_key, bp->rss_conf.rss_key, HW_HASH_KEY_SIZE);
191 : : }
192 : : }
193 : :
194 : : return 0;
195 : : }
196 : :
197 : 0 : void bnxt_free_vnic_mem(struct bnxt *bp)
198 : : {
199 : : struct bnxt_vnic_info *vnic;
200 : : uint16_t max_vnics, i;
201 : :
202 [ # # ]: 0 : if (bp->vnic_info == NULL)
203 : : return;
204 : :
205 : 0 : max_vnics = bp->max_vnics;
206 [ # # ]: 0 : for (i = 0; i < max_vnics; i++) {
207 : 0 : vnic = &bp->vnic_info[i];
208 [ # # ]: 0 : if (vnic->fw_vnic_id != (uint16_t)HWRM_NA_SIGNATURE) {
209 : 0 : PMD_DRV_LOG(ERR, "VNIC is not freed yet!\n");
210 : : /* TODO Call HWRM to free VNIC */
211 : : }
212 : : }
213 : :
214 : 0 : rte_free(bp->vnic_info);
215 : 0 : bp->vnic_info = NULL;
216 : : }
217 : :
218 : 0 : int bnxt_alloc_vnic_mem(struct bnxt *bp)
219 : : {
220 : : struct bnxt_vnic_info *vnic_mem;
221 : : uint16_t max_vnics;
222 : :
223 : 0 : max_vnics = bp->max_vnics;
224 : : /* Allocate memory for VNIC pool and filter pool */
225 : 0 : vnic_mem = rte_zmalloc("bnxt_vnic_info",
226 : : max_vnics * sizeof(struct bnxt_vnic_info), 0);
227 [ # # ]: 0 : if (vnic_mem == NULL) {
228 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for %d VNICs",
229 : : max_vnics);
230 : 0 : return -ENOMEM;
231 : : }
232 : 0 : bp->vnic_info = vnic_mem;
233 : 0 : bnxt_init_vnics(bp);
234 : 0 : return 0;
235 : : }
236 : :
237 : 0 : int bnxt_vnic_grp_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic)
238 : : {
239 : 0 : uint32_t size = sizeof(*vnic->fw_grp_ids) * bp->max_ring_grps;
240 : : uint32_t i;
241 : :
242 : 0 : vnic->fw_grp_ids = rte_zmalloc("vnic_fw_grp_ids", size, 0);
243 [ # # ]: 0 : if (!vnic->fw_grp_ids) {
244 : 0 : PMD_DRV_LOG(ERR,
245 : : "Failed to alloc %d bytes for group ids\n",
246 : : size);
247 : 0 : return -ENOMEM;
248 : : }
249 : :
250 : : /* Initialize to invalid ring id */
251 [ # # ]: 0 : for (i = 0; i < bp->max_ring_grps; i++)
252 : 0 : vnic->fw_grp_ids[i] = INVALID_HW_RING_ID;
253 : :
254 : : return 0;
255 : : }
256 : :
257 : 0 : uint16_t bnxt_rte_to_hwrm_hash_types(uint64_t rte_type)
258 : : {
259 : : uint16_t hwrm_type = 0;
260 : :
261 [ # # ]: 0 : if ((rte_type & RTE_ETH_RSS_IPV4) ||
262 : : (rte_type & RTE_ETH_RSS_ECPRI))
263 : : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
264 [ # # ]: 0 : if (rte_type & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
265 : 0 : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
266 [ # # ]: 0 : if (rte_type & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
267 : 0 : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
268 [ # # ]: 0 : if (rte_type & RTE_ETH_RSS_IPV6)
269 : 0 : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
270 [ # # ]: 0 : if (rte_type & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
271 : 0 : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
272 [ # # ]: 0 : if (rte_type & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
273 : 0 : hwrm_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
274 : :
275 : 0 : return hwrm_type;
276 : : }
277 : :
278 : 0 : int bnxt_rte_to_hwrm_hash_level(struct bnxt *bp, uint64_t hash_f, uint32_t lvl)
279 : : {
280 : : uint32_t mode = HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_DEFAULT;
281 : 0 : bool l3 = (hash_f & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_ECPRI));
282 : 0 : bool l4 = (hash_f & (RTE_ETH_RSS_NONFRAG_IPV4_UDP |
283 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP |
284 : : RTE_ETH_RSS_NONFRAG_IPV4_TCP |
285 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP));
286 : 0 : bool l3_only = l3 && !l4;
287 : : bool l3_and_l4 = l3 && l4;
288 : :
289 : : /* If FW has not advertised capability to configure outer/inner
290 : : * RSS hashing , just log a message. HW will work in default RSS mode.
291 : : */
292 [ # # # # : 0 : if ((BNXT_CHIP_P5(bp) && BNXT_VNIC_OUTER_RSS_UNSUPPORTED(bp)) ||
# # # # #
# # # #
# ]
293 [ # # ]: 0 : (!BNXT_CHIP_P5(bp) && !(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS))) {
294 [ # # ]: 0 : if (lvl)
295 : 0 : PMD_DRV_LOG(INFO,
296 : : "Given RSS level is unsupported, using default RSS level\n");
297 : 0 : return mode;
298 : : }
299 : :
300 [ # # # ]: 0 : switch (lvl) {
301 : 0 : case BNXT_RSS_LEVEL_INNERMOST:
302 : : /* Irrespective of what RTE says, FW always does 4 tuple */
303 [ # # ]: 0 : if (l3_and_l4 || l4 || l3_only)
304 : : mode = BNXT_HASH_MODE_INNERMOST;
305 : : break;
306 : 0 : case BNXT_RSS_LEVEL_OUTERMOST:
307 : : /* Irrespective of what RTE says, FW always does 4 tuple */
308 [ # # ]: 0 : if (l3_and_l4 || l4 || l3_only)
309 : : mode = BNXT_HASH_MODE_OUTERMOST;
310 : : break;
311 : : default:
312 : : mode = BNXT_HASH_MODE_DEFAULT;
313 : : break;
314 : : }
315 : :
316 : 0 : return mode;
317 : : }
318 : :
319 : 0 : uint64_t bnxt_hwrm_to_rte_rss_level(struct bnxt *bp, uint32_t mode)
320 : : {
321 : : uint64_t rss_level = 0;
322 : :
323 : : /* If FW has not advertised capability to configure inner/outer RSS
324 : : * return default hash mode.
325 : : */
326 [ # # # # : 0 : if ((BNXT_CHIP_P5(bp) && BNXT_VNIC_OUTER_RSS_UNSUPPORTED(bp)) ||
# # # # #
# # # #
# ]
327 [ # # ]: 0 : (!BNXT_CHIP_P5(bp) && !(bp->vnic_cap_flags & BNXT_VNIC_CAP_OUTER_RSS)))
328 : : return RTE_ETH_RSS_LEVEL_PMD_DEFAULT;
329 : :
330 : 0 : if (mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_2 ||
331 [ # # # ]: 0 : mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_OUTERMOST_4)
332 : : rss_level |= RTE_ETH_RSS_LEVEL_OUTERMOST;
333 : : else if (mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_2 ||
334 : : mode == HWRM_VNIC_RSS_CFG_INPUT_HASH_MODE_FLAGS_INNERMOST_4)
335 : : rss_level |= RTE_ETH_RSS_LEVEL_INNERMOST;
336 : : else
337 : : rss_level |= RTE_ETH_RSS_LEVEL_PMD_DEFAULT;
338 : :
339 : : return rss_level;
340 : : }
341 : :
342 : : static
343 : 0 : int32_t bnxt_vnic_populate_rss_table_p5(struct bnxt *bp,
344 : : struct bnxt_vnic_info *vnic)
345 : : {
346 : : uint32_t ctx_idx = 0, rss_idx = 0, cnt = 0;
347 : : uint32_t q_id = -1;
348 : : struct bnxt_rx_queue *rxq;
349 : 0 : uint16_t *ring_tbl = vnic->rss_table;
350 : 0 : uint8_t *rx_queue_state = bp->eth_dev->data->rx_queue_state;
351 : : uint16_t ring_id;
352 : :
353 : : /* For P5 platform */
354 [ # # ]: 0 : for (ctx_idx = 0; ctx_idx < vnic->num_lb_ctxts; ctx_idx++) {
355 [ # # ]: 0 : for (rss_idx = 0; rss_idx < BNXT_RSS_ENTRIES_PER_CTX_P5;
356 : 0 : rss_idx++) {
357 : : /* Find next active ring. */
358 [ # # ]: 0 : for (cnt = 0; cnt < BNXT_VNIC_MAX_QUEUE_SIZE; cnt++) {
359 [ # # ]: 0 : if (++q_id == bp->rx_nr_rings)
360 : : q_id = 0; /* reset the q_id */
361 [ # # ]: 0 : if (BNXT_VNIC_BITMAP_GET(vnic->queue_bitmap,
362 : 0 : q_id) &&
363 [ # # ]: 0 : rx_queue_state[q_id] !=
364 : : RTE_ETH_QUEUE_STATE_STOPPED)
365 : : break;
366 : : }
367 : :
368 : : /* no active queues exit */
369 [ # # ]: 0 : if (cnt == BNXT_VNIC_MAX_QUEUE_SIZE)
370 : : return 0;
371 : :
372 : 0 : rxq = bp->rx_queues[q_id];
373 : 0 : ring_id = rxq->rx_ring->rx_ring_struct->fw_ring_id;
374 : 0 : *ring_tbl++ = rte_cpu_to_le_16(ring_id);
375 : 0 : ring_id = rxq->cp_ring->cp_ring_struct->fw_ring_id;
376 : 0 : *ring_tbl++ = rte_cpu_to_le_16(ring_id);
377 : : }
378 : : }
379 : : return 0;
380 : : }
381 : :
382 : : static
383 : 0 : int32_t bnxt_vnic_populate_rss_table_p4(struct bnxt *bp,
384 : : struct bnxt_vnic_info *vnic)
385 : : {
386 : : uint32_t rss_idx = 0, cnt = 0;
387 : : uint32_t q_id = -1;
388 : 0 : uint16_t *ring_tbl = vnic->rss_table;
389 : 0 : uint8_t *rx_queue_state = bp->eth_dev->data->rx_queue_state;
390 : : uint16_t ring_id;
391 : :
392 : : /* For Wh+ platform */
393 [ # # ]: 0 : for (rss_idx = 0; rss_idx < bnxt_rss_hash_tbl_size(bp); rss_idx++) {
394 : : /* Find next active ring. */
395 [ # # ]: 0 : for (cnt = 0; cnt < BNXT_VNIC_MAX_QUEUE_SIZE; cnt++) {
396 [ # # ]: 0 : if (++q_id == bp->rx_nr_rings)
397 : : q_id = 0; /* reset the q_id */
398 [ # # ]: 0 : if (BNXT_VNIC_BITMAP_GET(vnic->queue_bitmap,
399 : 0 : q_id) &&
400 [ # # ]: 0 : rx_queue_state[q_id] !=
401 : : RTE_ETH_QUEUE_STATE_STOPPED)
402 : : break;
403 : : }
404 : :
405 : : /* no active queues exit */
406 [ # # ]: 0 : if (cnt == BNXT_VNIC_MAX_QUEUE_SIZE)
407 : : return 0;
408 : :
409 : 0 : ring_id = vnic->fw_grp_ids[q_id];
410 : 0 : *ring_tbl++ = rte_cpu_to_le_16(ring_id);
411 : : }
412 : : return 0;
413 : : }
414 : :
415 : : static
416 : 0 : int32_t bnxt_vnic_populate_rss_table(struct bnxt *bp,
417 : : struct bnxt_vnic_info *vnic)
418 : : {
419 : : /* RSS table population is different for p4 and p5 platforms */
420 [ # # ]: 0 : if (BNXT_CHIP_P5(bp))
421 : 0 : return bnxt_vnic_populate_rss_table_p5(bp, vnic);
422 : :
423 : 0 : return bnxt_vnic_populate_rss_table_p4(bp, vnic);
424 : : }
425 : :
426 : : static void
427 : 0 : bnxt_vnic_queue_delete(struct bnxt *bp, uint16_t vnic_idx)
428 : : {
429 : 0 : struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_idx];
430 : :
431 [ # # ]: 0 : if (bnxt_hwrm_vnic_free(bp, vnic))
432 : 0 : PMD_DRV_LOG(ERR, "Failed to delete queue\n");
433 : :
434 [ # # ]: 0 : if (vnic->fw_grp_ids) {
435 : 0 : rte_free(vnic->fw_grp_ids);
436 : 0 : vnic->fw_grp_ids = NULL;
437 : : }
438 : :
439 : 0 : vnic->rx_queue_cnt = 0;
440 [ # # ]: 0 : if (bp->nr_vnics)
441 : 0 : bp->nr_vnics--;
442 : :
443 : : /* reset the queue_bitmap */
444 : 0 : memset(vnic->queue_bitmap, 0, sizeof(vnic->queue_bitmap));
445 : 0 : }
446 : :
447 : : static struct bnxt_vnic_info*
448 : 0 : bnxt_vnic_queue_create(struct bnxt *bp, int32_t vnic_id, uint16_t q_index)
449 : : {
450 : 0 : uint8_t *rx_queue_state = bp->eth_dev->data->rx_queue_state;
451 : : struct bnxt_vnic_info *vnic;
452 : : struct bnxt_rx_queue *rxq = NULL;
453 : : int32_t rc = -EINVAL;
454 : : uint16_t saved_mru = 0;
455 : :
456 : 0 : vnic = &bp->vnic_info[vnic_id];
457 [ # # ]: 0 : if (vnic->rx_queue_cnt) {
458 : 0 : PMD_DRV_LOG(ERR, "invalid queue configuration %d\n", vnic_id);
459 : 0 : return NULL;
460 : : }
461 : :
462 : : /* set the queue_bitmap */
463 : 0 : BNXT_VNIC_BITMAP_SET(vnic->queue_bitmap, q_index);
464 : :
465 : 0 : rxq = bp->rx_queues[q_index];
466 [ # # ]: 0 : if (rx_queue_state[q_index] == RTE_ETH_QUEUE_STATE_STOPPED)
467 : 0 : rxq->rx_started = 0;
468 : : else
469 : 0 : rxq->rx_started = 1;
470 : :
471 : 0 : vnic->rx_queue_cnt++;
472 : 0 : vnic->start_grp_id = q_index;
473 : 0 : vnic->end_grp_id = q_index + 1;
474 : 0 : vnic->func_default = 0; /* This is not a default VNIC. */
475 : 0 : bp->nr_vnics++;
476 : :
477 : : /* Allocate vnic group for p4 platform */
478 : 0 : rc = bnxt_vnic_grp_alloc(bp, vnic);
479 [ # # ]: 0 : if (rc) {
480 : 0 : PMD_DRV_LOG(DEBUG, "Failed to allocate vnic groups\n");
481 : 0 : goto cleanup;
482 : : }
483 : :
484 : : /* populate the fw group table */
485 : 0 : bnxt_vnic_ring_grp_populate(bp, vnic);
486 : 0 : bnxt_vnic_rules_init(vnic);
487 : :
488 : 0 : rc = bnxt_hwrm_vnic_alloc(bp, vnic);
489 [ # # ]: 0 : if (rc) {
490 : 0 : PMD_DRV_LOG(DEBUG, "Failed to allocate vnic %d\n", q_index);
491 : 0 : goto cleanup;
492 : : }
493 : :
494 : : /* store the mru so we can set it to zero in hw */
495 [ # # ]: 0 : if (rxq->rx_started == 0) {
496 : 0 : saved_mru = vnic->mru;
497 : 0 : vnic->mru = 0;
498 : : }
499 : :
500 : 0 : rc = bnxt_hwrm_vnic_cfg(bp, vnic);
501 [ # # ]: 0 : if (rxq->rx_started == 0)
502 : 0 : vnic->mru = saved_mru;
503 : :
504 [ # # ]: 0 : if (rc) {
505 : 0 : PMD_DRV_LOG(DEBUG, "Failed to configure vnic %d\n", q_index);
506 : 0 : goto cleanup;
507 : : }
508 : :
509 : 0 : rc = bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
510 [ # # ]: 0 : if (rc) {
511 : 0 : PMD_DRV_LOG(DEBUG, "Failed to configure vnic plcmode %d\n",
512 : : q_index);
513 : 0 : goto cleanup;
514 : : }
515 : :
516 : 0 : vnic->ref_cnt++;
517 : 0 : return vnic;
518 : :
519 : 0 : cleanup:
520 : 0 : bnxt_vnic_queue_delete(bp, vnic_id);
521 : 0 : return NULL;
522 : : }
523 : :
524 : : static inline int32_t
525 : : bnxt_vnic_queue_db_lookup(struct bnxt *bp, uint64_t *q_list)
526 : : {
527 : : /* lookup in the database to check if it is in use */
528 : 0 : return rte_hash_lookup(bp->vnic_queue_db.rss_q_db,
529 : : (const void *)q_list);
530 : : }
531 : :
532 : : static inline int32_t
533 : : bnxt_vnic_queue_db_del(struct bnxt *bp, uint64_t *q_list)
534 : : {
535 : 0 : return rte_hash_del_key(bp->vnic_queue_db.rss_q_db,
536 : : (const void *)q_list);
537 : : }
538 : :
539 : : static int32_t
540 : 0 : bnxt_vnic_queue_db_add(struct bnxt *bp, uint64_t *q_list)
541 : : {
542 : : struct bnxt_vnic_info *vnic_info;
543 : : int32_t vnic_id, rc = -1;
544 : :
545 : 0 : vnic_id = rte_hash_add_key(bp->vnic_queue_db.rss_q_db,
546 : : (const void *)q_list);
547 : :
548 [ # # # # ]: 0 : if (vnic_id < 0 || vnic_id >= bp->max_vnics) {
549 : 0 : PMD_DRV_LOG(DEBUG, "unable to assign vnic index %d\n",
550 : : vnic_id);
551 : 0 : return rc;
552 : : }
553 : :
554 : 0 : vnic_info = &bp->vnic_info[vnic_id];
555 [ # # ]: 0 : if (vnic_info->fw_vnic_id != INVALID_HW_RING_ID) {
556 : 0 : PMD_DRV_LOG(DEBUG, "Invalid ring id for %d.\n", vnic_id);
557 : 0 : return rc;
558 : : }
559 : : return vnic_id;
560 : : }
561 : :
562 : : /* Function to validate the incoming rss configuration */
563 : : static
564 : 0 : int32_t bnxt_vnic_queue_db_rss_validate(struct bnxt *bp,
565 : : struct bnxt_vnic_rss_info *rss_info,
566 : : int32_t *vnic_idx)
567 : : {
568 : 0 : struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
569 : : int32_t rc = -EINVAL;
570 : : uint32_t idx = 0;
571 : : int32_t out_idx;
572 : :
573 [ # # ]: 0 : if (!(dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS)) {
574 : 0 : PMD_DRV_LOG(ERR, "Error Rss is not supported on this port\n");
575 : 0 : return rc;
576 : : }
577 : :
578 : : /* rss queue is zero then use the default vnic */
579 [ # # ]: 0 : if (rss_info->queue_num == 0) {
580 : 0 : *vnic_idx = 0;
581 : 0 : return 0;
582 : : }
583 : :
584 : : /* Check to see if the queues id are in supported range */
585 [ # # ]: 0 : if (rss_info->queue_num > bp->rx_nr_rings) {
586 : 0 : PMD_DRV_LOG(ERR, "Error unsupported queue num.\n");
587 : 0 : return rc;
588 : : }
589 : :
590 : : /* validate the queue ids are in correct range */
591 [ # # ]: 0 : for (idx = 0; idx < BNXT_VNIC_MAX_QUEUE_SIZE; idx++) {
592 [ # # ]: 0 : if (BNXT_VNIC_BITMAP_GET(rss_info->queue_list, idx)) {
593 [ # # ]: 0 : if (idx >= bp->rx_nr_rings) {
594 : 0 : PMD_DRV_LOG(ERR,
595 : : "Error %d beyond support size %u\n",
596 : : idx, bp->rx_nr_rings);
597 : 0 : return rc;
598 : : }
599 : : }
600 : : }
601 : :
602 : : /* check if the vnic already exist */
603 : 0 : out_idx = bnxt_vnic_queue_db_lookup(bp, rss_info->queue_list);
604 [ # # # # ]: 0 : if (out_idx < 0 || out_idx >= bp->max_vnics)
605 : : return -ENOENT; /* entry not found */
606 : :
607 : : /* found an entry */
608 : 0 : *vnic_idx = out_idx;
609 : 0 : return 0;
610 : : }
611 : :
612 : : static void
613 : 0 : bnxt_vnic_rss_delete(struct bnxt *bp, uint16_t q_index)
614 : : {
615 : : struct bnxt_vnic_info *vnic;
616 : :
617 : 0 : vnic = &bp->vnic_info[q_index];
618 [ # # ]: 0 : if (vnic->rx_queue_cnt >= 1)
619 : 0 : bnxt_hwrm_vnic_ctx_free(bp, vnic);
620 : :
621 [ # # ]: 0 : if (vnic->fw_vnic_id != INVALID_HW_RING_ID)
622 : 0 : bnxt_hwrm_vnic_free(bp, vnic);
623 : :
624 [ # # ]: 0 : if (vnic->fw_grp_ids) {
625 : 0 : rte_free(vnic->fw_grp_ids);
626 : 0 : vnic->fw_grp_ids = NULL;
627 : : }
628 : :
629 : : /* Update the vnic details for all the rx queues */
630 : 0 : vnic->rx_queue_cnt = 0;
631 [ # # ]: 0 : memset(vnic->queue_bitmap, 0, sizeof(vnic->queue_bitmap));
632 : :
633 [ # # ]: 0 : if (bp->nr_vnics)
634 : 0 : bp->nr_vnics--;
635 : 0 : }
636 : :
637 : : /* The validation of the rss_info should be done before calling this function*/
638 : :
639 : : static struct bnxt_vnic_info *
640 : 0 : bnxt_vnic_rss_create(struct bnxt *bp,
641 : : struct bnxt_vnic_rss_info *rss_info,
642 : : uint16_t vnic_id)
643 : : {
644 : 0 : uint8_t *rx_queue_state = bp->eth_dev->data->rx_queue_state;
645 : : struct bnxt_vnic_info *vnic;
646 : : struct bnxt_rx_queue *rxq = NULL;
647 : : uint32_t idx, nr_ctxs, config_rss = 0;
648 : : uint16_t saved_mru = 0;
649 : : uint16_t active_q_cnt = 0;
650 : : int16_t first_q = -1;
651 : : int16_t end_q = -1;
652 : : int32_t rc = 0;
653 : :
654 : : /* Assign the vnic to be used for this rss configuration */
655 : 0 : vnic = &bp->vnic_info[vnic_id];
656 : :
657 : : /* Update the vnic details for all the rx queues */
658 [ # # ]: 0 : for (idx = 0; idx < BNXT_VNIC_MAX_QUEUE_SIZE; idx++) {
659 [ # # ]: 0 : if (BNXT_VNIC_BITMAP_GET(rss_info->queue_list, idx)) {
660 : 0 : rxq = bp->rx_queues[idx];
661 [ # # ]: 0 : if (rx_queue_state[idx] ==
662 : : RTE_ETH_QUEUE_STATE_STOPPED) {
663 : 0 : rxq->rx_started = 0;
664 : : } else {
665 : 0 : rxq->rx_started = 1;
666 : 0 : active_q_cnt++;
667 : : }
668 : 0 : vnic->rx_queue_cnt++;
669 : :
670 : : /* Update the queue list */
671 : 0 : BNXT_VNIC_BITMAP_SET(vnic->queue_bitmap, idx);
672 [ # # ]: 0 : if (first_q == -1)
673 : 0 : first_q = idx;
674 : 0 : end_q = idx;
675 : : }
676 : : }
677 : 0 : vnic->start_grp_id = first_q;
678 : 0 : vnic->end_grp_id = end_q + 1;
679 : 0 : vnic->func_default = 0; /* This is not a default VNIC. */
680 : 0 : bp->nr_vnics++;
681 : :
682 : : /* Allocate vnic group for p4 platform */
683 : 0 : rc = bnxt_vnic_grp_alloc(bp, vnic);
684 [ # # ]: 0 : if (rc) {
685 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate vnic groups\n");
686 : 0 : goto fail_cleanup;
687 : : }
688 : :
689 : : /* populate the fw group table */
690 : 0 : bnxt_vnic_ring_grp_populate(bp, vnic);
691 : 0 : bnxt_vnic_rules_init(vnic);
692 : :
693 : : /* Allocate the vnic in the firmware */
694 : 0 : rc = bnxt_hwrm_vnic_alloc(bp, vnic);
695 [ # # ]: 0 : if (rc) {
696 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate vnic %d\n", idx);
697 : 0 : goto fail_cleanup;
698 : : }
699 : :
700 : : /* Allocate the vnic rss context */
701 : : /* RSS table size in P5 is 512. Cap max Rx rings to same value */
702 : 0 : nr_ctxs = bnxt_rss_ctxts(bp);
703 [ # # ]: 0 : for (idx = 0; idx < nr_ctxs; idx++) {
704 : 0 : rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, idx);
705 [ # # ]: 0 : if (rc)
706 : : break;
707 : : }
708 [ # # ]: 0 : if (rc) {
709 : 0 : PMD_DRV_LOG(ERR,
710 : : "HWRM ctx %d alloc failure rc: %x\n", idx, rc);
711 : 0 : goto fail_cleanup;
712 : : }
713 : 0 : vnic->num_lb_ctxts = nr_ctxs;
714 : :
715 : 0 : saved_mru = vnic->mru;
716 [ # # ]: 0 : if (!active_q_cnt)
717 : 0 : vnic->mru = 0;
718 : :
719 : : /* configure the vnic details in firmware */
720 : 0 : rc = bnxt_hwrm_vnic_cfg(bp, vnic);
721 : 0 : vnic->mru = saved_mru;
722 [ # # ]: 0 : if (rc) {
723 : 0 : PMD_DRV_LOG(ERR, "Failed to configure vnic %d\n", idx);
724 : 0 : goto fail_cleanup;
725 : : }
726 : :
727 : 0 : rc = bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
728 [ # # ]: 0 : if (rc) {
729 : 0 : PMD_DRV_LOG(ERR, "Failed to configure vnic plcmode %d\n",
730 : : idx);
731 : 0 : goto fail_cleanup;
732 : : }
733 : :
734 : : /* hwrm_type conversion */
735 : 0 : vnic->hash_type = bnxt_rte_to_hwrm_hash_types(rss_info->rss_types);
736 : 0 : vnic->hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss_info->rss_types,
737 : : rss_info->rss_level);
738 : :
739 : : /* configure the key */
740 [ # # ]: 0 : if (!rss_info->key_len)
741 : : /* If hash key has not been specified, use random hash key.*/
742 : 0 : bnxt_prandom_bytes(vnic->rss_hash_key, HW_HASH_KEY_SIZE);
743 : : else
744 : 0 : memcpy(vnic->rss_hash_key, rss_info->key, rss_info->key_len);
745 : :
746 : : /* Prepare the indirection table */
747 : 0 : bnxt_vnic_populate_rss_table(bp, vnic);
748 : :
749 : : /* check to see if there is at least one queue that is active */
750 [ # # ]: 0 : for (idx = vnic->start_grp_id; idx < vnic->end_grp_id; idx++) {
751 [ # # ]: 0 : if (bnxt_vnic_queue_id_is_valid(vnic, idx) &&
752 [ # # ]: 0 : bp->rx_queues[idx]->rx_started) {
753 : : config_rss = 1;
754 : : break;
755 : : }
756 : : }
757 : :
758 : : /* configure the rss table */
759 [ # # ]: 0 : if (config_rss) {
760 : 0 : rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
761 [ # # ]: 0 : if (rc) {
762 : 0 : memset(vnic->rss_hash_key, 0, HW_HASH_KEY_SIZE);
763 : 0 : PMD_DRV_LOG(ERR,
764 : : "Failed to configure vnic rss details %d\n",
765 : : idx);
766 : 0 : goto fail_cleanup;
767 : : }
768 : : }
769 : :
770 : 0 : vnic->ref_cnt++;
771 : 0 : return vnic;
772 : :
773 : 0 : fail_cleanup:
774 : 0 : bnxt_vnic_rss_delete(bp, idx);
775 : 0 : return NULL;
776 : : }
777 : :
778 : : int32_t
779 : 0 : bnxt_vnic_rss_queue_status_update(struct bnxt *bp, struct bnxt_vnic_info *vnic)
780 : : {
781 [ # # ]: 0 : if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
782 : : return 0;
783 : :
784 [ # # # # ]: 0 : if (!(vnic->rss_table && vnic->hash_type))
785 : : return 0;
786 : :
787 : : /* Prepare the indirection table */
788 : 0 : bnxt_vnic_populate_rss_table(bp, vnic);
789 : :
790 : : /* configure the rss table */
791 [ # # ]: 0 : if (bnxt_hwrm_vnic_rss_cfg(bp, vnic)) {
792 : 0 : PMD_DRV_LOG(DEBUG, "Failed to update vnic rss details\n");
793 : 0 : return -EINVAL;
794 : : }
795 : : return 0;
796 : : }
797 : :
798 : : static int32_t
799 : 0 : bnxt_vnic_rss_hash_algo_update(struct bnxt *bp,
800 : : struct bnxt_vnic_info *vnic,
801 : : struct bnxt_vnic_rss_info *rss_info)
802 : : {
803 : 0 : uint8_t old_rss_hash_key[HW_HASH_KEY_SIZE] = { 0 };
804 : : uint16_t hash_type;
805 : : uint8_t hash_mode;
806 : : uint32_t apply = 0;
807 : :
808 : : /* validate key length */
809 [ # # ]: 0 : if (rss_info->key_len != 0 && rss_info->key_len != HW_HASH_KEY_SIZE) {
810 : 0 : PMD_DRV_LOG(ERR,
811 : : "Invalid hashkey length, should be %d bytes\n",
812 : : HW_HASH_KEY_SIZE);
813 : 0 : return -EINVAL;
814 : : }
815 : :
816 : : /* hwrm_type conversion */
817 : 0 : hash_type = bnxt_rte_to_hwrm_hash_types(rss_info->rss_types);
818 : 0 : hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss_info->rss_types,
819 : : rss_info->rss_level);
820 [ # # ]: 0 : if (vnic->hash_mode != hash_mode ||
821 [ # # ]: 0 : vnic->hash_type != hash_type) {
822 : : apply = 1;
823 : 0 : vnic->hash_mode = hash_mode;
824 : 0 : vnic->hash_type = hash_type;
825 : : }
826 : : /* Store the old hash key before programming the new one. It will
827 : : * be used to restore the old hash key when HWRM_VNIC_RSS_CFG
828 : : * fails.
829 : : */
830 : 0 : memcpy(old_rss_hash_key, vnic->rss_hash_key, HW_HASH_KEY_SIZE);
831 [ # # # # ]: 0 : if (rss_info->key_len != 0 && memcmp(rss_info->key, vnic->rss_hash_key,
832 : : HW_HASH_KEY_SIZE)) {
833 : : apply = 1;
834 : : memcpy(vnic->rss_hash_key, rss_info->key, HW_HASH_KEY_SIZE);
835 : : }
836 : :
837 [ # # ]: 0 : if (apply) {
838 [ # # ]: 0 : if (bnxt_hwrm_vnic_rss_cfg(bp, vnic)) {
839 : 0 : memcpy(vnic->rss_hash_key, old_rss_hash_key, HW_HASH_KEY_SIZE);
840 : 0 : BNXT_TF_DBG(ERR, "Error configuring vnic RSS config\n");
841 : 0 : return -EINVAL;
842 : : }
843 : 0 : BNXT_TF_DBG(INFO, "Rss config successfully applied\n");
844 : : }
845 : : return 0;
846 : : }
847 : :
848 : 0 : int32_t bnxt_vnic_queue_db_deinit(struct bnxt *bp)
849 : : {
850 : 0 : rte_hash_free(bp->vnic_queue_db.rss_q_db);
851 : 0 : return 0;
852 : : }
853 : :
854 : 0 : int32_t bnxt_vnic_queue_db_init(struct bnxt *bp)
855 : : {
856 : 0 : struct rte_hash_parameters hash_tbl_params = {0};
857 : 0 : char hash_tbl_name[64] = {0};
858 : :
859 : : /* choose the least supported value */
860 [ # # ]: 0 : if (bp->rx_nr_rings > BNXT_VNIC_MAX_QUEUE_SIZE)
861 : 0 : bp->vnic_queue_db.num_queues = BNXT_VNIC_MAX_QUEUE_SIZE;
862 : : else
863 : 0 : bp->vnic_queue_db.num_queues = bp->rx_nr_rings;
864 : :
865 : : /* create the hash table for the rss hash entries */
866 : 0 : snprintf(hash_tbl_name, sizeof(hash_tbl_name),
867 : 0 : "bnxt_rss_hash_%d", bp->eth_dev->data->port_id);
868 : 0 : hash_tbl_params.name = hash_tbl_name;
869 : 0 : hash_tbl_params.entries = (bp->max_vnics > BNXT_VNIC_MAX_SUPPORTED_ID) ?
870 : 0 : BNXT_VNIC_MAX_SUPPORTED_ID : bp->max_vnics;
871 : 0 : hash_tbl_params.key_len = BNXT_VNIC_MAX_QUEUE_SZ_IN_8BITS;
872 : 0 : hash_tbl_params.socket_id = rte_socket_id();
873 : 0 : bp->vnic_queue_db.rss_q_db = rte_hash_create(&hash_tbl_params);
874 [ # # ]: 0 : if (bp->vnic_queue_db.rss_q_db == NULL) {
875 : 0 : PMD_DRV_LOG(ERR, "Failed to create rss hash tbl\n");
876 : 0 : return -ENOMEM;
877 : : }
878 : : return 0;
879 : : }
880 : :
881 : 0 : void bnxt_vnic_queue_db_update_dlft_vnic(struct bnxt *bp)
882 : : {
883 : : struct bnxt_vnic_info *dflt_vnic;
884 : : uint64_t bitmap[BNXT_VNIC_MAX_QUEUE_SZ_IN_64BITS];
885 : : uint32_t idx;
886 : : int32_t vnic_id;
887 : :
888 : : /* populate all the queue ids in the default vnic */
889 : : memset(bitmap, 0, sizeof(bitmap));
890 [ # # ]: 0 : for (idx = 0; idx < bp->vnic_queue_db.num_queues; idx++)
891 : 0 : BNXT_VNIC_BITMAP_SET(bitmap, idx);
892 : :
893 : 0 : vnic_id = bnxt_vnic_queue_db_add(bp, bitmap);
894 [ # # ]: 0 : if (vnic_id < 0) {
895 : 0 : PMD_DRV_LOG(ERR, "Unable to alloc vnic for default rss\n");
896 : 0 : return;
897 : : }
898 : :
899 : 0 : dflt_vnic = bnxt_vnic_queue_db_get_vnic(bp, vnic_id);
900 [ # # ]: 0 : if (dflt_vnic == NULL) {
901 : 0 : PMD_DRV_LOG(ERR, "Invalid vnic for default rss %d\n", vnic_id);
902 : 0 : return;
903 : : }
904 : : /* Update the default vnic structure */
905 : 0 : bp->vnic_queue_db.dflt_vnic_id = vnic_id;
906 : 0 : memcpy(dflt_vnic->queue_bitmap, bitmap, sizeof(bitmap));
907 : 0 : dflt_vnic->rx_queue_cnt = bp->vnic_queue_db.num_queues;
908 : 0 : dflt_vnic->ref_cnt++;
909 : : }
910 : :
911 : 0 : int32_t bnxt_vnic_queue_action_alloc(struct bnxt *bp,
912 : : uint16_t q_index,
913 : : uint16_t *vnic_idx,
914 : : uint16_t *vnicid)
915 : : {
916 : 0 : uint64_t queue_list[BNXT_VNIC_MAX_QUEUE_SZ_IN_64BITS] = {0};
917 : : struct bnxt_vnic_info *vnic_info;
918 : : int32_t idx;
919 : : int32_t rc = -EINVAL;
920 : :
921 : : /* validate the given queue id */
922 [ # # # # ]: 0 : if (q_index >= bp->rx_nr_rings || q_index >= BNXT_VNIC_MAX_QUEUE_SIZE) {
923 : 0 : PMD_DRV_LOG(ERR, "invalid queue id should be less than %d\n",
924 : : bp->rx_nr_rings);
925 : 0 : return rc;
926 : : }
927 : :
928 : : /* Populate the queue list */
929 : 0 : BNXT_VNIC_BITMAP_SET(queue_list, q_index);
930 : :
931 : : /* check to see if the q_index is already in use */
932 : : idx = bnxt_vnic_queue_db_lookup(bp, queue_list);
933 [ # # ]: 0 : if (idx < 0) {
934 : : /* Assign the vnic slot */
935 : 0 : idx = bnxt_vnic_queue_db_add(bp, queue_list);
936 [ # # ]: 0 : if (idx < 0) {
937 : 0 : PMD_DRV_LOG(DEBUG, "Unable to alloc vnic for queue\n");
938 : 0 : return rc;
939 : : }
940 : :
941 : : /* Allocate a new one */
942 : 0 : vnic_info = bnxt_vnic_queue_create(bp, idx, q_index);
943 [ # # ]: 0 : if (!vnic_info) {
944 : 0 : PMD_DRV_LOG(ERR, "failed to create vnic - %d\n",
945 : : q_index);
946 : : bnxt_vnic_queue_db_del(bp, queue_list);
947 : 0 : return rc; /* failed */
948 : : }
949 : : } else {
950 : 0 : vnic_info = bnxt_vnic_queue_db_get_vnic(bp, idx);
951 [ # # ]: 0 : if (vnic_info == NULL) {
952 : 0 : PMD_DRV_LOG(ERR, "Unable to lookup vnic for queue %d\n",
953 : : q_index);
954 : 0 : return rc;
955 : : }
956 : : /* increment the reference count and return the vnic id */
957 : 0 : vnic_info->ref_cnt++;
958 : : }
959 : 0 : *vnic_idx = (uint16_t)idx;
960 : 0 : *vnicid = vnic_info->fw_vnic_id;
961 : 0 : return 0;
962 : : }
963 : :
964 : : int32_t
965 : 0 : bnxt_vnic_queue_action_free(struct bnxt *bp, uint16_t vnic_id)
966 : : {
967 : : struct bnxt_vnic_info *vnic_info;
968 : : int32_t rc = -EINVAL;
969 : 0 : int32_t vnic_idx = vnic_id, idx;
970 : :
971 : : /* validate the given vnic idx */
972 [ # # ]: 0 : if (vnic_idx >= bp->max_vnics) {
973 : 0 : PMD_DRV_LOG(ERR, "invalid vnic idx %d\n", vnic_idx);
974 : 0 : return rc;
975 : : }
976 : :
977 : : /* validate the vnic info */
978 : 0 : vnic_info = &bp->vnic_info[vnic_idx];
979 [ # # ]: 0 : if (!vnic_info->rx_queue_cnt) {
980 : 0 : PMD_DRV_LOG(ERR, "Invalid vnic idx, no queues being used\n");
981 : 0 : return rc;
982 : : }
983 [ # # ]: 0 : if (vnic_info->ref_cnt) {
984 : 0 : vnic_info->ref_cnt--;
985 [ # # ]: 0 : if (!vnic_info->ref_cnt) {
986 : : idx = bnxt_vnic_queue_db_del(bp,
987 : 0 : vnic_info->queue_bitmap);
988 : : /* Check to ensure there is no corruption */
989 [ # # ]: 0 : if (idx != vnic_idx)
990 : 0 : PMD_DRV_LOG(ERR, "bad vnic idx %d\n", vnic_idx);
991 : :
992 : 0 : bnxt_vnic_queue_delete(bp, vnic_idx);
993 : : }
994 : : }
995 : : return 0;
996 : : }
997 : :
998 : : int32_t
999 : 0 : bnxt_vnic_rss_action_alloc(struct bnxt *bp,
1000 : : struct bnxt_vnic_rss_info *rss_info,
1001 : : uint16_t *vnic_idx,
1002 : : uint16_t *vnicid)
1003 : : {
1004 : : struct bnxt_vnic_info *vnic_info = NULL;
1005 : : int32_t rc = -EINVAL;
1006 : : int32_t idx;
1007 : :
1008 : : /* validate the given parameters */
1009 : 0 : rc = bnxt_vnic_queue_db_rss_validate(bp, rss_info, &idx);
1010 [ # # ]: 0 : if (rc == -EINVAL) {
1011 : 0 : PMD_DRV_LOG(ERR, "Failed to apply the rss action.\n");
1012 : 0 : return rc;
1013 [ # # ]: 0 : } else if (rc == -ENOENT) {
1014 : : /* Allocate a new entry */
1015 : 0 : idx = bnxt_vnic_queue_db_add(bp, rss_info->queue_list);
1016 [ # # ]: 0 : if (idx < 0) {
1017 : 0 : PMD_DRV_LOG(DEBUG, "Unable to alloc vnic for rss\n");
1018 : 0 : return rc;
1019 : : }
1020 : : /* create the rss vnic */
1021 : 0 : vnic_info = bnxt_vnic_rss_create(bp, rss_info, idx);
1022 [ # # ]: 0 : if (!vnic_info) {
1023 : 0 : PMD_DRV_LOG(ERR, "Failed to create rss action.\n");
1024 : : bnxt_vnic_queue_db_del(bp, rss_info->queue_list);
1025 : 0 : return rc;
1026 : : }
1027 : : } else {
1028 : 0 : vnic_info = bnxt_vnic_queue_db_get_vnic(bp, idx);
1029 [ # # ]: 0 : if (vnic_info == NULL) {
1030 : 0 : PMD_DRV_LOG(ERR, "Unable to lookup vnic for idx %d\n",
1031 : : idx);
1032 : 0 : return rc;
1033 : : }
1034 : : /* increment the reference count and return the vnic id */
1035 : 0 : vnic_info->ref_cnt++;
1036 : :
1037 : : /* check configuration has changed then update hash details */
1038 : 0 : rc = bnxt_vnic_rss_hash_algo_update(bp, vnic_info, rss_info);
1039 [ # # ]: 0 : if (rc) {
1040 : 0 : PMD_DRV_LOG(ERR, "Failed to update the rss action.\n");
1041 : 0 : return rc;
1042 : : }
1043 : : }
1044 : 0 : *vnic_idx = idx;
1045 : 0 : *vnicid = vnic_info->fw_vnic_id;
1046 : 0 : return 0;
1047 : : }
1048 : :
1049 : : /* Delete the vnic associated with the given rss action index */
1050 : : int32_t
1051 : 0 : bnxt_vnic_rss_action_free(struct bnxt *bp, uint16_t vnic_id)
1052 : : {
1053 : : uint64_t bitmap[BNXT_VNIC_MAX_QUEUE_SZ_IN_64BITS];
1054 : : struct bnxt_vnic_info *vnic_info;
1055 : : int32_t rc = -EINVAL;
1056 : : uint64_t *q_list;
1057 : : int32_t idx = 0;
1058 : :
1059 : : /* validate the given vnic id */
1060 [ # # ]: 0 : if (vnic_id >= bp->max_vnics) {
1061 : 0 : PMD_DRV_LOG(ERR, "invalid vnic id %d\n", vnic_id);
1062 : 0 : return rc;
1063 : : }
1064 : :
1065 : : /* validate vnic info */
1066 : 0 : vnic_info = &bp->vnic_info[vnic_id];
1067 [ # # ]: 0 : if (!vnic_info->rx_queue_cnt) {
1068 : 0 : PMD_DRV_LOG(ERR, "Invalid vnic id, not using any queues\n");
1069 : 0 : return rc;
1070 : : }
1071 : :
1072 [ # # ]: 0 : if (vnic_info->ref_cnt) {
1073 : 0 : vnic_info->ref_cnt--;
1074 [ # # ]: 0 : if (!vnic_info->ref_cnt) {
1075 [ # # ]: 0 : if (bp->vnic_queue_db.dflt_vnic_id == vnic_id) {
1076 : : /* in case of default queue, list can be
1077 : : * changed by reta config so need a list
1078 : : * with all queues populated.
1079 : : */
1080 : : memset(bitmap, 0, sizeof(bitmap));
1081 : 0 : for (idx = 0;
1082 [ # # ]: 0 : idx < bp->vnic_queue_db.num_queues;
1083 : 0 : idx++)
1084 : 0 : BNXT_VNIC_BITMAP_SET(bitmap, idx);
1085 : : q_list = bitmap;
1086 : : } else {
1087 : 0 : q_list = vnic_info->queue_bitmap;
1088 : : }
1089 : : idx = bnxt_vnic_queue_db_del(bp, q_list);
1090 : :
1091 : : /* check to ensure there is no corruption */
1092 [ # # ]: 0 : if (idx != vnic_id)
1093 : 0 : PMD_DRV_LOG(ERR, "bad vnic idx %d\n", vnic_id);
1094 : 0 : bnxt_vnic_rss_delete(bp, vnic_id);
1095 : : }
1096 : : }
1097 : : return 0;
1098 : : }
1099 : :
1100 : : int32_t
1101 : 0 : bnxt_vnic_reta_config_update(struct bnxt *bp,
1102 : : struct bnxt_vnic_info *vnic_info,
1103 : : struct rte_eth_rss_reta_entry64 *reta_conf,
1104 : : uint16_t reta_size)
1105 : : {
1106 : 0 : uint64_t l_bitmap[BNXT_VNIC_MAX_QUEUE_SZ_IN_64BITS] = {0};
1107 : : uint16_t i, sft, idx;
1108 : : uint16_t q_id;
1109 : :
1110 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
1111 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
1112 : 0 : sft = i % RTE_ETH_RETA_GROUP_SIZE;
1113 : :
1114 [ # # ]: 0 : if (!(reta_conf[idx].mask & (1ULL << sft)))
1115 : 0 : continue;
1116 : :
1117 : 0 : q_id = reta_conf[idx].reta[sft];
1118 [ # # ]: 0 : if (q_id >= bp->vnic_queue_db.num_queues ||
1119 [ # # ]: 0 : !bp->eth_dev->data->rx_queues[q_id]) {
1120 : 0 : PMD_DRV_LOG(ERR, "Queue id %d is invalid\n", q_id);
1121 : 0 : return -EINVAL;
1122 : : }
1123 : 0 : BNXT_VNIC_BITMAP_SET(l_bitmap, q_id);
1124 : : }
1125 : : /* update the queue bitmap after the validation */
1126 : 0 : memcpy(vnic_info->queue_bitmap, l_bitmap, sizeof(l_bitmap));
1127 : 0 : return 0;
1128 : : }
1129 : :
1130 : : int32_t
1131 : 0 : bnxt_vnic_queue_id_is_valid(struct bnxt_vnic_info *vnic_info,
1132 : : uint16_t queue_id)
1133 : : {
1134 [ # # ]: 0 : if (BNXT_VNIC_BITMAP_GET(vnic_info->queue_bitmap, queue_id))
1135 : 0 : return 1;
1136 : : return 0;
1137 : : }
1138 : :
1139 : : void
1140 : 0 : bnxt_vnic_ring_grp_populate(struct bnxt *bp, struct bnxt_vnic_info *vnic)
1141 : : {
1142 : : uint32_t i;
1143 : :
1144 : : /* check if ring group is supported */
1145 [ # # ]: 0 : if (!BNXT_HAS_RING_GRPS(bp))
1146 : : return;
1147 : :
1148 : : /* map ring groups to this vnic */
1149 [ # # ]: 0 : for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++)
1150 [ # # ]: 0 : if (bnxt_vnic_queue_id_is_valid(vnic, i) &&
1151 [ # # ]: 0 : bp->rx_queues[i]->rx_started)
1152 : 0 : vnic->fw_grp_ids[i] = bp->grp_info[i].fw_grp_id;
1153 : :
1154 : 0 : vnic->dflt_ring_grp = bp->grp_info[vnic->start_grp_id].fw_grp_id;
1155 : : }
1156 : :
1157 : : void
1158 : 0 : bnxt_vnic_rules_init(struct bnxt_vnic_info *vnic)
1159 : : {
1160 : 0 : vnic->rss_rule = (uint16_t)HWRM_NA_SIGNATURE;
1161 : 0 : vnic->cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
1162 : 0 : vnic->lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
1163 : 0 : }
1164 : :
1165 : : int32_t
1166 : 0 : bnxt_vnic_mru_config(struct bnxt *bp, uint16_t new_mtu)
1167 : : {
1168 : : struct bnxt_vnic_info *vnic;
1169 : : uint16_t size = 0;
1170 : : int32_t rc = 0;
1171 : : uint32_t i;
1172 : :
1173 [ # # ]: 0 : for (i = 0; i < bp->max_vnics; i++) {
1174 : 0 : vnic = &bp->vnic_info[i];
1175 [ # # ]: 0 : if (vnic->fw_vnic_id == INVALID_VNIC_ID)
1176 : 0 : continue;
1177 : :
1178 : 0 : vnic->mru = BNXT_VNIC_MRU(new_mtu);
1179 : 0 : rc = bnxt_hwrm_vnic_cfg(bp, vnic);
1180 [ # # ]: 0 : if (rc)
1181 : : break;
1182 : :
1183 [ # # ]: 0 : size = rte_pktmbuf_data_room_size(bp->rx_queues[0]->mb_pool);
1184 : 0 : size -= RTE_PKTMBUF_HEADROOM;
1185 : :
1186 [ # # ]: 0 : if (size < new_mtu) {
1187 : 0 : rc = bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
1188 [ # # ]: 0 : if (rc)
1189 : : break;
1190 : : }
1191 : : }
1192 : 0 : return rc;
1193 : : }
1194 : :
1195 : : struct bnxt_vnic_info *
1196 : 0 : bnxt_vnic_queue_db_get_vnic(struct bnxt *bp, uint16_t vnic_idx)
1197 : : {
1198 : : struct bnxt_vnic_info *vnic_info;
1199 : :
1200 [ # # ]: 0 : if (vnic_idx >= bp->max_vnics) {
1201 : 0 : PMD_DRV_LOG(ERR, "invalid vnic index %u\n", vnic_idx);
1202 : 0 : return NULL;
1203 : : }
1204 : 0 : vnic_info = &bp->vnic_info[vnic_idx];
1205 : 0 : return vnic_info;
1206 : : }
1207 : :
1208 : : struct bnxt_vnic_info *
1209 : 0 : bnxt_vnic_queue_id_get_next(struct bnxt *bp, uint16_t queue_id,
1210 : : uint16_t *vnic_idx)
1211 : : {
1212 : : struct bnxt_vnic_info *vnic = NULL;
1213 : 0 : uint16_t i = *vnic_idx;
1214 : :
1215 [ # # ]: 0 : while (i < bp->max_vnics) {
1216 : 0 : vnic = &bp->vnic_info[i];
1217 [ # # # # ]: 0 : if (vnic->ref_cnt && BNXT_VNIC_BITMAP_GET(vnic->queue_bitmap,
1218 : : queue_id)) {
1219 : : /* found a vnic that has the queue id */
1220 : 0 : *vnic_idx = i;
1221 : 0 : return vnic;
1222 : : }
1223 : 0 : i++;
1224 : : }
1225 : : return NULL;
1226 : : }
1227 : :
1228 : : void
1229 : 0 : bnxt_vnic_tpa_cfg(struct bnxt *bp, uint16_t queue_id, bool flag)
1230 : : {
1231 : : struct bnxt_vnic_info *vnic = NULL;
1232 : 0 : uint16_t vnic_idx = 0;
1233 : :
1234 : 0 : while ((vnic = bnxt_vnic_queue_id_get_next(bp, queue_id,
1235 [ # # ]: 0 : &vnic_idx)) != NULL) {
1236 : 0 : bnxt_hwrm_vnic_tpa_cfg(bp, vnic, flag);
1237 : 0 : vnic_idx++;
1238 : : }
1239 : 0 : }
1240 : :
1241 : : inline struct bnxt_vnic_info *
1242 : 0 : bnxt_get_default_vnic(struct bnxt *bp)
1243 : : {
1244 : 0 : return &bp->vnic_info[bp->vnic_queue_db.dflt_vnic_id];
1245 : : }
|