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