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