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_malloc.h>
9 : :
10 : : #include "bnxt.h"
11 : : #include "bnxt_filter.h"
12 : : #include "bnxt_hwrm.h"
13 : : #include "bnxt_ring.h"
14 : : #include "bnxt_rxq.h"
15 : : #include "bnxt_rxr.h"
16 : : #include "bnxt_vnic.h"
17 : : #include "hsi_struct_def_dpdk.h"
18 : :
19 : : /*
20 : : * RX Queues
21 : : */
22 : :
23 : 0 : uint64_t bnxt_get_rx_port_offloads(struct bnxt *bp)
24 : : {
25 : : uint64_t rx_offload_capa;
26 : :
27 : : rx_offload_capa = RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
28 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
29 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
30 : : RTE_ETH_RX_OFFLOAD_KEEP_CRC |
31 : : RTE_ETH_RX_OFFLOAD_SCATTER |
32 : : RTE_ETH_RX_OFFLOAD_RSS_HASH |
33 : : RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT;
34 : :
35 : : /* In P7 platform if truflow is enabled then vlan offload is disabled*/
36 [ # # # # : 0 : if (!(BNXT_TRUFLOW_EN(bp) && BNXT_CHIP_P7(bp)))
# # ]
37 : : rx_offload_capa |= (RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
38 : : RTE_ETH_RX_OFFLOAD_VLAN_EXTEND);
39 : :
40 : :
41 : 0 : if (!bnxt_compressed_rx_cqe_mode_enabled(bp) &&
42 [ # # # # ]: 0 : BNXT_SUPPORTS_TPA(bp))
43 : 0 : rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
44 [ # # ]: 0 : if (bp->flags & BNXT_FLAG_PTP_SUPPORTED)
45 : 0 : rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
46 [ # # ]: 0 : if (bp->vnic_cap_flags & BNXT_VNIC_CAP_VLAN_RX_STRIP) {
47 [ # # # # : 0 : if (!(BNXT_TRUFLOW_EN(bp) && BNXT_CHIP_P7(bp)))
# # ]
48 : 0 : rx_offload_capa |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
49 : : }
50 : :
51 [ # # ]: 0 : if (BNXT_TUNNELED_OFFLOADS_CAP_ALL_EN(bp))
52 : 0 : rx_offload_capa |= RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
53 : : RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM;
54 : :
55 : 0 : return rx_offload_capa;
56 : : }
57 : :
58 : : /* Determine whether the current configuration needs aggregation ring in HW. */
59 : 0 : int bnxt_need_agg_ring(struct rte_eth_dev *eth_dev)
60 : : {
61 : : /* scattered_rx will be true if OFFLOAD_SCATTER is enabled,
62 : : * if LRO is enabled, or if the max packet len is greater than the
63 : : * mbuf data size. So AGG ring will be needed whenever scattered_rx
64 : : * is set.
65 : : */
66 : 0 : return eth_dev->data->scattered_rx ? 1 : 0;
67 : : }
68 : :
69 : 0 : void bnxt_free_rxq_stats(struct bnxt_rx_queue *rxq)
70 : : {
71 [ # # # # : 0 : if (rxq && rxq->cp_ring && rxq->cp_ring->hw_stats)
# # ]
72 : 0 : rxq->cp_ring->hw_stats = NULL;
73 : 0 : }
74 : :
75 : 0 : int bnxt_mq_rx_configure(struct bnxt *bp)
76 : : {
77 : 0 : struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
78 : : struct rte_eth_rss_conf *rss = &bp->rss_conf;
79 : : const struct rte_eth_vmdq_rx_conf *conf =
80 : : &dev_conf->rx_adv_conf.vmdq_rx_conf;
81 : : unsigned int i, j, nb_q_per_grp = 1, ring_idx = 0;
82 : : int start_grp_id, end_grp_id = 1, rc = 0;
83 : : struct bnxt_vnic_info *vnic;
84 : : struct bnxt_filter_info *filter;
85 : : enum rte_eth_nb_pools pools = 1, max_pools = 0;
86 : : struct bnxt_rx_queue *rxq;
87 : :
88 : 0 : bp->nr_vnics = 0;
89 : :
90 : : /* Multi-queue mode */
91 [ # # ]: 0 : if (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB_RSS) {
92 : : /* VMDq ONLY, VMDq+RSS, VMDq+DCB, VMDq+DCB+RSS */
93 : :
94 [ # # # ]: 0 : switch (dev_conf->rxmode.mq_mode) {
95 : 0 : case RTE_ETH_MQ_RX_VMDQ_RSS:
96 : : case RTE_ETH_MQ_RX_VMDQ_ONLY:
97 : : case RTE_ETH_MQ_RX_VMDQ_DCB_RSS:
98 : : /* FALLTHROUGH */
99 : : /* ETH_8/64_POOLs */
100 : 0 : pools = conf->nb_queue_pools;
101 : : /* For each pool, allocate MACVLAN CFA rule & VNIC */
102 : 0 : max_pools = RTE_MIN(bp->max_vnics,
103 : : RTE_MIN(bp->max_l2_ctx,
104 : : RTE_MIN(bp->max_rsscos_ctx,
105 : : RTE_ETH_64_POOLS)));
106 : 0 : PMD_DRV_LOG_LINE(DEBUG,
107 : : "pools = %u max_pools = %u",
108 : : pools, max_pools);
109 : : if (pools > max_pools)
110 : : pools = max_pools;
111 : : break;
112 : 0 : case RTE_ETH_MQ_RX_RSS:
113 [ # # ]: 0 : pools = bp->rx_cosq_cnt ? bp->rx_cosq_cnt : 1;
114 : : break;
115 : 0 : default:
116 : 0 : PMD_DRV_LOG_LINE(ERR, "Unsupported mq_mod %d",
117 : : dev_conf->rxmode.mq_mode);
118 : : rc = -EINVAL;
119 : 0 : goto err_out;
120 : : }
121 [ # # ]: 0 : } else if (!dev_conf->rxmode.mq_mode) {
122 [ # # ]: 0 : pools = bp->rx_cosq_cnt ? bp->rx_cosq_cnt : pools;
123 : : }
124 : :
125 : 0 : pools = RTE_MIN(pools, bp->rx_cp_nr_rings);
126 : 0 : nb_q_per_grp = bp->rx_cp_nr_rings / pools;
127 : 0 : PMD_DRV_LOG_LINE(DEBUG, "pools = %u nb_q_per_grp = %u",
128 : : pools, nb_q_per_grp);
129 : : start_grp_id = 0;
130 : 0 : end_grp_id = nb_q_per_grp;
131 : :
132 [ # # ]: 0 : for (i = 0; i < pools; i++) {
133 : 0 : vnic = &bp->vnic_info[i];
134 [ # # ]: 0 : if (!vnic) {
135 : 0 : PMD_DRV_LOG_LINE(ERR, "VNIC alloc failed");
136 : : rc = -ENOMEM;
137 : 0 : goto err_out;
138 : : }
139 : 0 : vnic->flags |= BNXT_VNIC_INFO_BCAST;
140 : 0 : bp->nr_vnics++;
141 : :
142 [ # # ]: 0 : for (j = 0; j < nb_q_per_grp; j++, ring_idx++) {
143 : 0 : rxq = bp->eth_dev->data->rx_queues[ring_idx];
144 : 0 : rxq->vnic = vnic;
145 : 0 : PMD_DRV_LOG_LINE(DEBUG,
146 : : "rxq[%d] = %p vnic[%d] = %p",
147 : : ring_idx, rxq, i, vnic);
148 : : }
149 [ # # ]: 0 : if (i == 0) {
150 [ # # ]: 0 : if (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB) {
151 : 0 : bp->eth_dev->data->promiscuous = 1;
152 : 0 : vnic->flags |= BNXT_VNIC_INFO_PROMISC;
153 : : }
154 : 0 : vnic->func_default = true;
155 : : }
156 : 0 : vnic->start_grp_id = start_grp_id;
157 : 0 : vnic->end_grp_id = end_grp_id;
158 : :
159 [ # # ]: 0 : if (i) {
160 [ # # ]: 0 : if (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_DCB ||
161 : : !(dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS))
162 : 0 : vnic->rss_dflt_cr = true;
163 : 0 : goto skip_filter_allocation;
164 : : }
165 : 0 : filter = bnxt_alloc_filter(bp);
166 [ # # ]: 0 : if (!filter) {
167 : 0 : PMD_DRV_LOG_LINE(ERR, "L2 filter alloc failed");
168 : : rc = -ENOMEM;
169 : 0 : goto err_out;
170 : : }
171 : 0 : filter->mac_index = 0;
172 : 0 : filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST;
173 : : /*
174 : : * TODO: Configure & associate CFA rule for
175 : : * each VNIC for each VMDq with MACVLAN, MACVLAN+TC
176 : : */
177 : 0 : STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
178 : :
179 : 0 : skip_filter_allocation:
180 : : start_grp_id = end_grp_id;
181 : 0 : end_grp_id += nb_q_per_grp;
182 : : }
183 : :
184 : 0 : bp->rx_num_qs_per_vnic = nb_q_per_grp;
185 : :
186 [ # # ]: 0 : for (i = 0; i < bp->nr_vnics; i++) {
187 : 0 : uint32_t lvl = RTE_ETH_RSS_LEVEL(rss->rss_hf);
188 : :
189 : 0 : vnic = &bp->vnic_info[i];
190 : 0 : vnic->hash_type = bnxt_rte_to_hwrm_hash_types(rss->rss_hf);
191 : 0 : vnic->hash_mode = bnxt_rte_to_hwrm_hash_level(bp, rss->rss_hf, lvl);
192 : :
193 : : /*
194 : : * Use the supplied key if the key length is
195 : : * acceptable and the rss_key is not NULL
196 : : */
197 [ # # # # ]: 0 : if (rss->rss_key && rss->rss_key_len <= HW_HASH_KEY_SIZE)
198 : 0 : memcpy(vnic->rss_hash_key, rss->rss_key, rss->rss_key_len);
199 : : }
200 : :
201 : : return rc;
202 : :
203 : : err_out:
204 : : /* Free allocated vnic/filters */
205 : :
206 : : return rc;
207 : : }
208 : :
209 : 0 : void bnxt_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq)
210 : : {
211 : : struct rte_mbuf **sw_ring;
212 : : struct bnxt_tpa_info *tpa_info;
213 : : uint16_t i;
214 : :
215 [ # # # # ]: 0 : if (!rxq || !rxq->rx_ring)
216 : : return;
217 : :
218 : 0 : sw_ring = rxq->rx_ring->rx_buf_ring;
219 [ # # ]: 0 : if (sw_ring) {
220 : : #if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
221 : : /*
222 : : * The vector receive burst function does not set used
223 : : * mbuf pointers to NULL, do that here to simplify
224 : : * cleanup logic.
225 : : */
226 [ # # ]: 0 : for (i = 0; i < rxq->rxrearm_nb; i++)
227 : 0 : sw_ring[rxq->rxrearm_start + i] = NULL;
228 : 0 : rxq->rxrearm_nb = 0;
229 : : #endif
230 : 0 : for (i = 0;
231 [ # # ]: 0 : i < rxq->rx_ring->rx_ring_struct->ring_size; i++) {
232 [ # # ]: 0 : if (sw_ring[i]) {
233 [ # # ]: 0 : if (sw_ring[i] != &rxq->fake_mbuf)
234 : : rte_pktmbuf_free_seg(sw_ring[i]);
235 : 0 : sw_ring[i] = NULL;
236 : : }
237 : : }
238 : : }
239 : : /* Free up mbufs in Agg ring */
240 [ # # ]: 0 : if (rxq->bp == NULL ||
241 [ # # # # ]: 0 : rxq->bp->eth_dev == NULL ||
242 : 0 : !bnxt_need_agg_ring(rxq->bp->eth_dev))
243 : 0 : return;
244 : :
245 : 0 : sw_ring = rxq->rx_ring->ag_buf_ring;
246 [ # # ]: 0 : if (sw_ring) {
247 : : for (i = 0;
248 [ # # ]: 0 : i < rxq->rx_ring->ag_ring_struct->ring_size; i++) {
249 [ # # ]: 0 : if (sw_ring[i]) {
250 : : rte_pktmbuf_free_seg(sw_ring[i]);
251 : 0 : sw_ring[i] = NULL;
252 : : }
253 : : }
254 : : }
255 : :
256 [ # # ]: 0 : if (bnxt_compressed_rx_cqe_mode_enabled(rxq->bp))
257 : : return;
258 : :
259 : : /* Free up mbufs in TPA */
260 : 0 : tpa_info = rxq->rx_ring->tpa_info;
261 [ # # ]: 0 : if (tpa_info) {
262 [ # # ]: 0 : int max_aggs = BNXT_TPA_MAX_AGGS(rxq->bp);
263 : :
264 [ # # ]: 0 : for (i = 0; i < max_aggs; i++) {
265 [ # # ]: 0 : if (tpa_info[i].mbuf) {
266 : : rte_pktmbuf_free_seg(tpa_info[i].mbuf);
267 : 0 : tpa_info[i].mbuf = NULL;
268 : : }
269 : : }
270 : : }
271 : :
272 : : }
273 : :
274 : 0 : void bnxt_free_rx_mbufs(struct bnxt *bp)
275 : : {
276 : : struct bnxt_rx_queue *rxq;
277 : : int i;
278 : :
279 [ # # ]: 0 : for (i = 0; i < (int)bp->rx_nr_rings; i++) {
280 : 0 : rxq = bp->rx_queues[i];
281 : 0 : bnxt_rx_queue_release_mbufs(rxq);
282 : : }
283 : 0 : }
284 : :
285 : 0 : void bnxt_free_rxq_mem(struct bnxt_rx_queue *rxq)
286 : : {
287 : 0 : bnxt_rx_queue_release_mbufs(rxq);
288 : :
289 : : /* Free RX, AGG ring hardware descriptors */
290 [ # # ]: 0 : if (rxq->rx_ring) {
291 : 0 : bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
292 : 0 : rte_free(rxq->rx_ring->rx_ring_struct);
293 : 0 : rxq->rx_ring->rx_ring_struct = NULL;
294 : : /* Free RX Agg ring hardware descriptors */
295 : 0 : bnxt_free_ring(rxq->rx_ring->ag_ring_struct);
296 : 0 : rte_free(rxq->rx_ring->ag_ring_struct);
297 : 0 : rxq->rx_ring->ag_ring_struct = NULL;
298 : :
299 : 0 : rte_free(rxq->rx_ring);
300 : 0 : rxq->rx_ring = NULL;
301 : : }
302 : : /* Free RX completion ring hardware descriptors */
303 [ # # ]: 0 : if (rxq->cp_ring) {
304 : 0 : bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
305 : 0 : rte_free(rxq->cp_ring->cp_ring_struct);
306 : 0 : rxq->cp_ring->cp_ring_struct = NULL;
307 : 0 : rte_free(rxq->cp_ring);
308 : 0 : rxq->cp_ring = NULL;
309 : : }
310 : :
311 : 0 : bnxt_free_rxq_stats(rxq);
312 : 0 : rte_memzone_free(rxq->mz);
313 : 0 : rxq->mz = NULL;
314 : 0 : }
315 : :
316 : 0 : void bnxt_rx_queue_release_op(struct rte_eth_dev *dev, uint16_t queue_idx)
317 : : {
318 : 0 : struct bnxt_rx_queue *rxq = dev->data->rx_queues[queue_idx];
319 : :
320 [ # # ]: 0 : if (rxq != NULL) {
321 [ # # ]: 0 : if (is_bnxt_in_error(rxq->bp))
322 : : return;
323 : :
324 : 0 : bnxt_free_hwrm_rx_ring(rxq->bp, rxq->queue_id);
325 : 0 : bnxt_free_rxq_mem(rxq);
326 : 0 : rte_free(rxq);
327 : : }
328 : : }
329 : :
330 : 0 : int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
331 : : uint16_t queue_idx,
332 : : uint16_t nb_desc,
333 : : unsigned int socket_id,
334 : : const struct rte_eth_rxconf *rx_conf,
335 : : struct rte_mempool *mp)
336 : : {
337 : 0 : uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
338 : 0 : uint8_t rs = !!(rx_offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT);
339 : 0 : struct bnxt *bp = eth_dev->data->dev_private;
340 : 0 : struct rte_eth_rxseg_split *rx_seg =
341 : : (struct rte_eth_rxseg_split *)rx_conf->rx_seg;
342 : 0 : uint16_t n_seg = rx_conf->rx_nseg;
343 : : struct bnxt_rx_queue *rxq;
344 : : int rc = 0;
345 : :
346 : 0 : rc = is_bnxt_in_error(bp);
347 [ # # ]: 0 : if (rc)
348 : : return rc;
349 : :
350 [ # # ]: 0 : if (n_seg > 1 && !rs) {
351 : 0 : PMD_DRV_LOG_LINE(ERR, "n_seg %d does not match buffer split %d setting",
352 : : n_seg, rs);
353 : 0 : return -EINVAL;
354 : : }
355 : :
356 [ # # ]: 0 : if (n_seg > BNXT_MAX_BUFFER_SPLIT_SEGS) {
357 : 0 : PMD_DRV_LOG_LINE(ERR, "n_seg %d not supported", n_seg);
358 : 0 : return -EINVAL;
359 : : }
360 : :
361 [ # # ]: 0 : if (queue_idx >= bnxt_max_rings(bp)) {
362 : 0 : PMD_DRV_LOG_LINE(ERR,
363 : : "Cannot create Rx ring %d. Only %d rings available",
364 : : queue_idx, bp->max_rx_rings);
365 : 0 : return -EINVAL;
366 : : }
367 : :
368 [ # # ]: 0 : if (nb_desc < BNXT_MIN_RING_DESC || nb_desc > MAX_RX_DESC_CNT) {
369 : 0 : PMD_DRV_LOG_LINE(ERR, "nb_desc %d is invalid", nb_desc);
370 : 0 : return -EINVAL;
371 : : }
372 : :
373 [ # # ]: 0 : if (eth_dev->data->rx_queues) {
374 : 0 : rxq = eth_dev->data->rx_queues[queue_idx];
375 [ # # ]: 0 : if (rxq)
376 : 0 : bnxt_rx_queue_release_op(eth_dev, queue_idx);
377 : : }
378 : 0 : rxq = rte_zmalloc_socket("bnxt_rx_queue", sizeof(struct bnxt_rx_queue),
379 : : RTE_CACHE_LINE_SIZE, socket_id);
380 [ # # ]: 0 : if (!rxq) {
381 : 0 : PMD_DRV_LOG_LINE(ERR, "bnxt_rx_queue allocation failed!");
382 : 0 : return -ENOMEM;
383 : : }
384 : 0 : rxq->bp = bp;
385 [ # # ]: 0 : if (n_seg > 1) {
386 : 0 : rxq->mb_pool = rx_seg[BNXT_MEM_POOL_IDX_0].mp;
387 : 0 : rxq->agg_mb_pool = rx_seg[BNXT_MEM_POOL_IDX_1].mp;
388 : : } else {
389 : 0 : rxq->mb_pool = mp;
390 : 0 : rxq->agg_mb_pool = mp;
391 : : }
392 : :
393 : 0 : rxq->nb_rx_desc = nb_desc;
394 : 0 : rxq->rx_free_thresh =
395 : 0 : RTE_MIN(rte_align32pow2(nb_desc) / 4, RTE_BNXT_MAX_RX_BURST);
396 : :
397 : 0 : PMD_DRV_LOG_LINE(DEBUG,
398 : : "App supplied RXQ drop_en status : %d", rx_conf->rx_drop_en);
399 : 0 : rxq->drop_en = BNXT_DEFAULT_RX_DROP_EN;
400 : :
401 : 0 : PMD_DRV_LOG_LINE(DEBUG, "RX Buf MTU %d", eth_dev->data->mtu);
402 : :
403 : 0 : eth_dev->data->rx_queues[queue_idx] = rxq;
404 : :
405 : 0 : rc = bnxt_init_rx_ring_struct(rxq, socket_id);
406 [ # # ]: 0 : if (rc) {
407 : 0 : PMD_DRV_LOG_LINE(ERR,
408 : : "init_rx_ring_struct failed!");
409 : 0 : goto err;
410 : : }
411 : :
412 : 0 : PMD_DRV_LOG_LINE(DEBUG, "RX Buf size is %d", rxq->rx_buf_size);
413 : 0 : rxq->queue_id = queue_idx;
414 : 0 : rxq->port_id = eth_dev->data->port_id;
415 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)
416 : 0 : rxq->crc_len = RTE_ETHER_CRC_LEN;
417 : : else
418 : 0 : rxq->crc_len = 0;
419 : :
420 : : /* Allocate RX ring hardware descriptors */
421 : 0 : rc = bnxt_alloc_rings(bp, socket_id, queue_idx, NULL, rxq, rxq->cp_ring,
422 : : NULL, "rxr");
423 [ # # ]: 0 : if (rc) {
424 : 0 : PMD_DRV_LOG_LINE(ERR,
425 : : "ring_dma_zone_reserve for rx_ring failed!");
426 : 0 : goto err;
427 : : }
428 : 0 : rxq->rx_mbuf_alloc_fail = 0;
429 : 0 : rxq->epoch = 0;
430 : :
431 : : /* rxq 0 must not be stopped when used as async CPR */
432 : : if (!BNXT_NUM_ASYNC_CPR(bp) && queue_idx == 0)
433 : : rxq->rx_deferred_start = false;
434 : : else
435 : 0 : rxq->rx_deferred_start = rx_conf->rx_deferred_start;
436 : :
437 : 0 : rxq->rx_started = rxq->rx_deferred_start ? false : true;
438 : 0 : rxq->vnic = bnxt_get_default_vnic(bp);
439 [ # # ]: 0 : rxq->vnic->hds_threshold = n_seg ? rxq->vnic->hds_threshold : 0;
440 : :
441 : 0 : return 0;
442 : 0 : err:
443 : 0 : bnxt_rx_queue_release_op(eth_dev, queue_idx);
444 : 0 : return rc;
445 : : }
446 : :
447 : : int
448 : 0 : bnxt_rx_queue_intr_enable_op(struct rte_eth_dev *eth_dev, uint16_t queue_id)
449 : : {
450 : 0 : struct bnxt *bp = eth_dev->data->dev_private;
451 : : struct bnxt_rx_queue *rxq;
452 : : struct bnxt_cp_ring_info *cpr;
453 : : int rc = 0;
454 : :
455 : 0 : rc = is_bnxt_in_error(bp);
456 [ # # ]: 0 : if (rc)
457 : : return rc;
458 : :
459 [ # # ]: 0 : if (eth_dev->data->rx_queues) {
460 : 0 : rxq = eth_dev->data->rx_queues[queue_id];
461 [ # # ]: 0 : if (!rxq)
462 : : return -EINVAL;
463 : :
464 : 0 : cpr = rxq->cp_ring;
465 [ # # ]: 0 : if (BNXT_CHIP_P5_P7(bp)) {
466 : 0 : struct bnxt_cp_ring_info *nqr = bp->rxtx_nq_ring;
467 : :
468 : 0 : bnxt_arm_nq_p5p(nqr, 1);
469 : 0 : bnxt_arm_rx_cq_p5p(rxq->cp_ring, 1);
470 : : } else {
471 : 0 : B_CP_DB_ARM(cpr);
472 : : }
473 : : }
474 : : return rc;
475 : : }
476 : :
477 : : int
478 : 0 : bnxt_rx_queue_intr_disable_op(struct rte_eth_dev *eth_dev, uint16_t queue_id)
479 : : {
480 : 0 : struct bnxt *bp = eth_dev->data->dev_private;
481 : : struct bnxt_rx_queue *rxq;
482 : : struct bnxt_cp_ring_info *cpr;
483 : : int rc = 0;
484 : :
485 : 0 : rc = is_bnxt_in_error(bp);
486 [ # # ]: 0 : if (rc)
487 : : return rc;
488 : :
489 [ # # ]: 0 : if (eth_dev->data->rx_queues) {
490 : 0 : rxq = eth_dev->data->rx_queues[queue_id];
491 [ # # ]: 0 : if (!rxq)
492 : : return -EINVAL;
493 : :
494 : 0 : cpr = rxq->cp_ring;
495 [ # # ]: 0 : if (BNXT_CHIP_P5_P7(bp)) {
496 : 0 : struct bnxt_cp_ring_info *nqr = bp->rxtx_nq_ring;
497 : : struct bnxt_cp_ring_info *rx_cpr;
498 : :
499 : 0 : bnxt_arm_nq_p5p(nqr, 0);
500 : : /* Loops through all RXQs and finds the one that
501 : : * received a packet if any
502 : : */
503 : 0 : uint32_t cons = RING_CMPL(nqr->cp_ring_struct->ring_mask,
504 : : nqr->cp_raw_cons);
505 : 0 : struct cmpl_base *cmpl = &((nqr->cp_desc_ring)[cons]);
506 : :
507 [ # # ]: 0 : if (CMPL_VALID(cmpl, nqr->valid)) {
508 : : unsigned int rxid = 0;
509 : :
510 : 0 : rx_cpr = rxq->cp_ring;
511 [ # # ]: 0 : for (; rxid < bp->rx_nr_rings; rxid++) {
512 : 0 : rxq = bp->rx_queues[rxid];
513 : 0 : rx_cpr = rxq->cp_ring;
514 : 0 : cons = RING_CMPL(rx_cpr->cp_ring_struct->ring_mask,
515 : : rx_cpr->cp_raw_cons);
516 : 0 : cmpl = &((rx_cpr->cp_desc_ring)[cons]);
517 : : /* Because the valid bit in the rx
518 : : * completion queue is not updated the
519 : : * cmp valid using raw cons is used
520 : : */
521 [ # # ]: 0 : if (bnxt_cpr_cmp_valid(cmpl,
522 : : rx_cpr->cp_raw_cons,
523 : : rx_cpr->cp_ring_struct->ring_size)) {
524 : : break;
525 : : }
526 : : }
527 : 0 : bnxt_process_nq(bp, nqr, rx_cpr);
528 : : }
529 : : } else {
530 : 0 : B_CP_DB_DISARM(cpr);
531 : : }
532 : : }
533 : : return rc;
534 : : }
535 : :
536 : 0 : int bnxt_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
537 : : {
538 : 0 : struct bnxt *bp = dev->data->dev_private;
539 : 0 : struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
540 : 0 : struct bnxt_rx_queue *rxq = bp->rx_queues[rx_queue_id];
541 : : struct bnxt_vnic_info *vnic = NULL;
542 : 0 : uint16_t vnic_idx = 0;
543 : : uint16_t fw_grp_id = 0;
544 : : int rc = 0;
545 : :
546 : 0 : rc = is_bnxt_in_error(bp);
547 [ # # ]: 0 : if (rc)
548 : : return rc;
549 : :
550 [ # # ]: 0 : if (rxq == NULL) {
551 : 0 : PMD_DRV_LOG_LINE(ERR, "Invalid Rx queue %d", rx_queue_id);
552 : 0 : return -EINVAL;
553 : : }
554 : :
555 : 0 : vnic = bnxt_vnic_queue_id_get_next(bp, rx_queue_id, &vnic_idx);
556 [ # # ]: 0 : if (vnic == NULL) {
557 : 0 : PMD_DRV_LOG_LINE(ERR, "VNIC not initialized for RxQ %d",
558 : : rx_queue_id);
559 : 0 : return -EINVAL;
560 : : }
561 : :
562 : : /* reset the previous stats for the rx_queue since the counters
563 : : * will be cleared when the queue is started.
564 : : */
565 [ # # # # ]: 0 : if (BNXT_TPA_V2_P7(bp))
566 : 0 : memset(&bp->prev_rx_ring_stats_ext[rx_queue_id], 0,
567 : : sizeof(struct bnxt_ring_stats_ext));
568 : : else
569 : 0 : memset(&bp->prev_rx_ring_stats[rx_queue_id], 0,
570 : : sizeof(struct bnxt_ring_stats));
571 : :
572 : : /* Set the queue state to started here.
573 : : * We check the status of the queue while posting buffer.
574 : : * If queue is it started, we do not post buffers for Rx.
575 : : */
576 : 0 : rxq->rx_started = true;
577 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
578 : :
579 : 0 : bnxt_free_hwrm_rx_ring(bp, rx_queue_id);
580 : 0 : rc = bnxt_alloc_hwrm_rx_ring(bp, rx_queue_id);
581 [ # # ]: 0 : if (rc)
582 : : return rc;
583 : :
584 [ # # ]: 0 : if (BNXT_HAS_RING_GRPS(bp))
585 : 0 : fw_grp_id = bp->grp_info[rx_queue_id].fw_grp_id;
586 : :
587 : : do {
588 [ # # ]: 0 : if (BNXT_HAS_RING_GRPS(bp))
589 : 0 : vnic->dflt_ring_grp = fw_grp_id;
590 : : /* Reconfigure default receive ring and MRU. */
591 : 0 : bnxt_hwrm_vnic_cfg(bp, vnic);
592 : :
593 : 0 : PMD_DRV_LOG_LINE(INFO, "Rx queue started %d", rx_queue_id);
594 : :
595 [ # # ]: 0 : if (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
596 [ # # ]: 0 : if (BNXT_HAS_RING_GRPS(bp)) {
597 [ # # ]: 0 : if (vnic->fw_grp_ids[rx_queue_id] !=
598 : : INVALID_HW_RING_ID) {
599 : 0 : PMD_DRV_LOG_LINE(ERR, "invalid ring id %d",
600 : : rx_queue_id);
601 : 0 : return 0;
602 : : }
603 : :
604 : 0 : vnic->fw_grp_ids[rx_queue_id] = fw_grp_id;
605 : 0 : PMD_DRV_LOG_LINE(DEBUG, "vnic = %p fw_grp_id = %d",
606 : : vnic, fw_grp_id);
607 : : }
608 : :
609 : 0 : PMD_DRV_LOG_LINE(DEBUG, "Rx Queue Count %d",
610 : : vnic->rx_queue_cnt);
611 : 0 : rc += bnxt_vnic_rss_queue_status_update(bp, vnic);
612 : : }
613 : 0 : vnic_idx++;
614 : 0 : } while ((vnic = bnxt_vnic_queue_id_get_next(bp, rx_queue_id,
615 [ # # ]: 0 : &vnic_idx)) != NULL);
616 : :
617 [ # # ]: 0 : if (rc != 0) {
618 : 0 : dev->data->rx_queue_state[rx_queue_id] =
619 : : RTE_ETH_QUEUE_STATE_STOPPED;
620 : 0 : rxq->rx_started = false;
621 : : }
622 : :
623 : 0 : PMD_DRV_LOG_LINE(INFO,
624 : : "queue %d, rx_deferred_start %d, state %d!",
625 : : rx_queue_id, rxq->rx_deferred_start,
626 : : bp->eth_dev->data->rx_queue_state[rx_queue_id]);
627 : :
628 : 0 : return rc;
629 : : }
630 : :
631 : 0 : int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
632 : : {
633 : 0 : struct bnxt *bp = dev->data->dev_private;
634 : 0 : struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
635 : : struct bnxt_vnic_info *vnic = NULL;
636 : : struct bnxt_rx_queue *rxq = NULL;
637 : : int active_queue_cnt = 0;
638 : 0 : uint16_t vnic_idx = 0, q_id = rx_queue_id;
639 : : int i, rc = 0;
640 : :
641 : 0 : rc = is_bnxt_in_error(bp);
642 [ # # ]: 0 : if (rc)
643 : : return rc;
644 : :
645 : : /* For the stingray platform and other platforms needing tighter
646 : : * control of resource utilization, Rx CQ 0 also works as
647 : : * Default CQ for async notifications
648 : : */
649 : : if (!BNXT_NUM_ASYNC_CPR(bp) && !rx_queue_id) {
650 : : PMD_DRV_LOG_LINE(ERR, "Cannot stop Rx queue id %d", rx_queue_id);
651 : : return -EINVAL;
652 : : }
653 : :
654 : 0 : rxq = bp->rx_queues[rx_queue_id];
655 [ # # ]: 0 : if (!rxq) {
656 : 0 : PMD_DRV_LOG_LINE(ERR, "Invalid Rx queue %d", rx_queue_id);
657 : 0 : return -EINVAL;
658 : : }
659 : :
660 : 0 : vnic = bnxt_vnic_queue_id_get_next(bp, q_id, &vnic_idx);
661 [ # # ]: 0 : if (!vnic) {
662 : 0 : PMD_DRV_LOG_LINE(ERR, "VNIC not initialized for RxQ %d", q_id);
663 : 0 : return -EINVAL;
664 : : }
665 : :
666 [ # # ]: 0 : __rte_assume(q_id < RTE_MAX_QUEUES_PER_PORT);
667 : 0 : dev->data->rx_queue_state[q_id] = RTE_ETH_QUEUE_STATE_STOPPED;
668 : 0 : rxq->rx_started = false;
669 : 0 : PMD_DRV_LOG_LINE(DEBUG, "Rx queue stopped");
670 : :
671 : : do {
672 : : active_queue_cnt = 0;
673 [ # # ]: 0 : if (dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
674 [ # # ]: 0 : if (BNXT_HAS_RING_GRPS(bp))
675 : 0 : vnic->fw_grp_ids[q_id] = INVALID_HW_RING_ID;
676 : :
677 : 0 : PMD_DRV_LOG_LINE(DEBUG, "Rx Queue Count %d",
678 : : vnic->rx_queue_cnt);
679 : 0 : rc = bnxt_vnic_rss_queue_status_update(bp, vnic);
680 : : }
681 : :
682 : : /* Compute current number of active receive queues. */
683 [ # # ]: 0 : for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++)
684 [ # # ]: 0 : if (bp->rx_queues[i]->rx_started)
685 : 0 : active_queue_cnt++;
686 : :
687 [ # # ]: 0 : if (BNXT_CHIP_P5_P7(bp)) {
688 : : /*
689 : : * For P5, we need to ensure that the VNIC default
690 : : * receive ring corresponds to an active receive queue.
691 : : * When no queue is active, we need to temporarily set
692 : : * the MRU to zero so that packets are dropped early in
693 : : * the receive pipeline in order to prevent the VNIC
694 : : * default receive ring from being accessed.
695 : : */
696 [ # # ]: 0 : if (active_queue_cnt == 0) {
697 : 0 : uint16_t saved_mru = vnic->mru;
698 : :
699 : : /* clear RSS setting on vnic. */
700 : 0 : bnxt_vnic_rss_clear_p5(bp, vnic);
701 : :
702 : 0 : vnic->mru = 0;
703 : : /* Reconfigure default receive ring and MRU. */
704 : 0 : bnxt_hwrm_vnic_cfg(bp, vnic);
705 : 0 : vnic->mru = saved_mru;
706 : : } else {
707 : : /* Reconfigure default receive ring. */
708 : 0 : bnxt_hwrm_vnic_cfg(bp, vnic);
709 : : }
710 [ # # ]: 0 : } else if (active_queue_cnt && vnic->dflt_ring_grp ==
711 [ # # ]: 0 : bp->grp_info[q_id].fw_grp_id) {
712 : : /*
713 : : * If the queue being stopped is the current default
714 : : * queue and there are other active queues, pick one of
715 : : * them as the default and reconfigure the vnic.
716 : : */
717 [ # # ]: 0 : for (i = vnic->start_grp_id; i < vnic->end_grp_id;
718 : 0 : i++) {
719 [ # # ]: 0 : if (bp->rx_queues[i]->rx_started) {
720 : 0 : vnic->dflt_ring_grp =
721 : 0 : bp->grp_info[i].fw_grp_id;
722 : 0 : bnxt_hwrm_vnic_cfg(bp, vnic);
723 : 0 : break;
724 : : }
725 : : }
726 : : }
727 : 0 : vnic_idx++;
728 : 0 : } while ((vnic = bnxt_vnic_queue_id_get_next(bp, q_id,
729 [ # # ]: 0 : &vnic_idx)) != NULL);
730 : :
731 [ # # ]: 0 : if (rc == 0)
732 : 0 : bnxt_rx_queue_release_mbufs(rxq);
733 : :
734 : : return rc;
735 : : }
|