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