xref: /f-stack/dpdk/drivers/net/bnxt/bnxt_rxq.c (revision 031be553)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) Broadcom Limited.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Broadcom Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <inttypes.h>
35 
36 #include <rte_malloc.h>
37 
38 #include "bnxt.h"
39 #include "bnxt_cpr.h"
40 #include "bnxt_filter.h"
41 #include "bnxt_hwrm.h"
42 #include "bnxt_ring.h"
43 #include "bnxt_rxq.h"
44 #include "bnxt_rxr.h"
45 #include "bnxt_vnic.h"
46 #include "hsi_struct_def_dpdk.h"
47 
48 /*
49  * RX Queues
50  */
51 
52 void bnxt_free_rxq_stats(struct bnxt_rx_queue *rxq)
53 {
54 	struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
55 
56 	if (cpr->hw_stats)
57 		cpr->hw_stats = NULL;
58 }
59 
60 int bnxt_mq_rx_configure(struct bnxt *bp)
61 {
62 	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
63 	const struct rte_eth_vmdq_rx_conf *conf =
64 		    &dev_conf->rx_adv_conf.vmdq_rx_conf;
65 	unsigned int i, j, nb_q_per_grp = 1, ring_idx = 0;
66 	int start_grp_id, end_grp_id = 1, rc = 0;
67 	struct bnxt_vnic_info *vnic;
68 	struct bnxt_filter_info *filter;
69 	enum rte_eth_nb_pools pools = bp->rx_cp_nr_rings, max_pools = 0;
70 	struct bnxt_rx_queue *rxq;
71 
72 	bp->nr_vnics = 0;
73 
74 	/* Single queue mode */
75 	if (bp->rx_cp_nr_rings < 2) {
76 		vnic = bnxt_alloc_vnic(bp);
77 		if (!vnic) {
78 			RTE_LOG(ERR, PMD, "VNIC alloc failed\n");
79 			rc = -ENOMEM;
80 			goto err_out;
81 		}
82 		vnic->flags |= BNXT_VNIC_INFO_BCAST;
83 		STAILQ_INSERT_TAIL(&bp->ff_pool[0], vnic, next);
84 		bp->nr_vnics++;
85 
86 		rxq = bp->eth_dev->data->rx_queues[0];
87 		rxq->vnic = vnic;
88 
89 		vnic->func_default = true;
90 		vnic->ff_pool_idx = 0;
91 		vnic->start_grp_id = 0;
92 		vnic->end_grp_id = vnic->start_grp_id;
93 		filter = bnxt_alloc_filter(bp);
94 		if (!filter) {
95 			RTE_LOG(ERR, PMD, "L2 filter alloc failed\n");
96 			rc = -ENOMEM;
97 			goto err_out;
98 		}
99 		STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
100 		goto out;
101 	}
102 
103 	/* Multi-queue mode */
104 	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_VMDQ_DCB_RSS) {
105 		/* VMDq ONLY, VMDq+RSS, VMDq+DCB, VMDq+DCB+RSS */
106 
107 		switch (dev_conf->rxmode.mq_mode) {
108 		case ETH_MQ_RX_VMDQ_RSS:
109 		case ETH_MQ_RX_VMDQ_ONLY:
110 			/* ETH_8/64_POOLs */
111 			pools = conf->nb_queue_pools;
112 			/* For each pool, allocate MACVLAN CFA rule & VNIC */
113 			max_pools = RTE_MIN(bp->max_vnics,
114 					    RTE_MIN(bp->max_l2_ctx,
115 					    RTE_MIN(bp->max_rsscos_ctx,
116 						    ETH_64_POOLS)));
117 			if (pools > max_pools)
118 				pools = max_pools;
119 			break;
120 		case ETH_MQ_RX_RSS:
121 			pools = 1;
122 			break;
123 		default:
124 			RTE_LOG(ERR, PMD, "Unsupported mq_mod %d\n",
125 				dev_conf->rxmode.mq_mode);
126 			rc = -EINVAL;
127 			goto err_out;
128 		}
129 	}
130 
131 	nb_q_per_grp = bp->rx_cp_nr_rings / pools;
132 	start_grp_id = 0;
133 	end_grp_id = nb_q_per_grp;
134 
135 	for (i = 0; i < pools; i++) {
136 		vnic = bnxt_alloc_vnic(bp);
137 		if (!vnic) {
138 			RTE_LOG(ERR, PMD, "VNIC alloc failed\n");
139 			rc = -ENOMEM;
140 			goto err_out;
141 		}
142 		vnic->flags |= BNXT_VNIC_INFO_BCAST;
143 		STAILQ_INSERT_TAIL(&bp->ff_pool[i], vnic, next);
144 		bp->nr_vnics++;
145 
146 		for (j = 0; j < nb_q_per_grp; j++, ring_idx++) {
147 			rxq = bp->eth_dev->data->rx_queues[ring_idx];
148 			rxq->vnic = vnic;
149 		}
150 		if (i == 0) {
151 			if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_VMDQ_DCB) {
152 				bp->eth_dev->data->promiscuous = 1;
153 				vnic->flags |= BNXT_VNIC_INFO_PROMISC;
154 			}
155 			vnic->func_default = true;
156 		}
157 		vnic->ff_pool_idx = i;
158 		vnic->start_grp_id = start_grp_id;
159 		vnic->end_grp_id = end_grp_id;
160 
161 		if (i) {
162 			if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_VMDQ_DCB ||
163 			    !(dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS))
164 				vnic->rss_dflt_cr = true;
165 			goto skip_filter_allocation;
166 		}
167 		filter = bnxt_alloc_filter(bp);
168 		if (!filter) {
169 			RTE_LOG(ERR, PMD, "L2 filter alloc failed\n");
170 			rc = -ENOMEM;
171 			goto err_out;
172 		}
173 		/*
174 		 * TODO: Configure & associate CFA rule for
175 		 * each VNIC for each VMDq with MACVLAN, MACVLAN+TC
176 		 */
177 		STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
178 
179 skip_filter_allocation:
180 		start_grp_id = end_grp_id;
181 		end_grp_id += nb_q_per_grp;
182 	}
183 
184 out:
185 	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
186 		struct rte_eth_rss_conf *rss = &dev_conf->rx_adv_conf.rss_conf;
187 		uint16_t hash_type = 0;
188 
189 		if (bp->flags & BNXT_FLAG_UPDATE_HASH) {
190 			rss = &bp->rss_conf;
191 			bp->flags &= ~BNXT_FLAG_UPDATE_HASH;
192 		}
193 
194 		if (rss->rss_hf & ETH_RSS_IPV4)
195 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4;
196 		if (rss->rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
197 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4;
198 		if (rss->rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
199 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4;
200 		if (rss->rss_hf & ETH_RSS_IPV6)
201 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6;
202 		if (rss->rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
203 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6;
204 		if (rss->rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
205 			hash_type |= HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
206 
207 		for (i = 0; i < bp->nr_vnics; i++) {
208 			STAILQ_FOREACH(vnic, &bp->ff_pool[i], next) {
209 			vnic->hash_type = hash_type;
210 
211 			/*
212 			 * Use the supplied key if the key length is
213 			 * acceptable and the rss_key is not NULL
214 			 */
215 			if (rss->rss_key &&
216 			    rss->rss_key_len <= HW_HASH_KEY_SIZE)
217 				memcpy(vnic->rss_hash_key,
218 				       rss->rss_key, rss->rss_key_len);
219 			}
220 		}
221 	}
222 
223 	return rc;
224 
225 err_out:
226 	/* Free allocated vnic/filters */
227 
228 	return rc;
229 }
230 
231 static void bnxt_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq)
232 {
233 	struct bnxt_sw_rx_bd *sw_ring;
234 	struct bnxt_tpa_info *tpa_info;
235 	uint16_t i;
236 
237 	if (rxq) {
238 		sw_ring = rxq->rx_ring->rx_buf_ring;
239 		if (sw_ring) {
240 			for (i = 0;
241 			     i < rxq->rx_ring->rx_ring_struct->ring_size; i++) {
242 				if (sw_ring[i].mbuf) {
243 					rte_pktmbuf_free_seg(sw_ring[i].mbuf);
244 					sw_ring[i].mbuf = NULL;
245 				}
246 			}
247 		}
248 		/* Free up mbufs in Agg ring */
249 		sw_ring = rxq->rx_ring->ag_buf_ring;
250 		if (sw_ring) {
251 			for (i = 0;
252 			     i < rxq->rx_ring->ag_ring_struct->ring_size; i++) {
253 				if (sw_ring[i].mbuf) {
254 					rte_pktmbuf_free_seg(sw_ring[i].mbuf);
255 					sw_ring[i].mbuf = NULL;
256 				}
257 			}
258 		}
259 
260 		/* Free up mbufs in TPA */
261 		tpa_info = rxq->rx_ring->tpa_info;
262 		if (tpa_info) {
263 			for (i = 0; i < BNXT_TPA_MAX; i++) {
264 				if (tpa_info[i].mbuf) {
265 					rte_pktmbuf_free_seg(tpa_info[i].mbuf);
266 					tpa_info[i].mbuf = NULL;
267 				}
268 			}
269 		}
270 	}
271 }
272 
273 void bnxt_free_rx_mbufs(struct bnxt *bp)
274 {
275 	struct bnxt_rx_queue *rxq;
276 	int i;
277 
278 	for (i = 0; i < (int)bp->rx_nr_rings; i++) {
279 		rxq = bp->rx_queues[i];
280 		bnxt_rx_queue_release_mbufs(rxq);
281 	}
282 }
283 
284 void bnxt_rx_queue_release_op(void *rx_queue)
285 {
286 	struct bnxt_rx_queue *rxq = (struct bnxt_rx_queue *)rx_queue;
287 
288 	if (rxq) {
289 		bnxt_rx_queue_release_mbufs(rxq);
290 
291 		/* Free RX ring hardware descriptors */
292 		bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
293 		/* Free RX Agg ring hardware descriptors */
294 		bnxt_free_ring(rxq->rx_ring->ag_ring_struct);
295 
296 		/* Free RX completion ring hardware descriptors */
297 		bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
298 
299 		bnxt_free_rxq_stats(rxq);
300 
301 		rte_free(rxq);
302 	}
303 }
304 
305 int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
306 			       uint16_t queue_idx,
307 			       uint16_t nb_desc,
308 			       unsigned int socket_id,
309 			       const struct rte_eth_rxconf *rx_conf,
310 			       struct rte_mempool *mp)
311 {
312 	struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
313 	struct bnxt_rx_queue *rxq;
314 	int rc = 0;
315 
316 	if (!nb_desc || nb_desc > MAX_RX_DESC_CNT) {
317 		RTE_LOG(ERR, PMD, "nb_desc %d is invalid\n", nb_desc);
318 		rc = -EINVAL;
319 		goto out;
320 	}
321 
322 	if (eth_dev->data->rx_queues) {
323 		rxq = eth_dev->data->rx_queues[queue_idx];
324 		if (rxq)
325 			bnxt_rx_queue_release_op(rxq);
326 	}
327 	rxq = rte_zmalloc_socket("bnxt_rx_queue", sizeof(struct bnxt_rx_queue),
328 				 RTE_CACHE_LINE_SIZE, socket_id);
329 	if (!rxq) {
330 		RTE_LOG(ERR, PMD, "bnxt_rx_queue allocation failed!\n");
331 		rc = -ENOMEM;
332 		goto out;
333 	}
334 	rxq->bp = bp;
335 	rxq->mb_pool = mp;
336 	rxq->nb_rx_desc = nb_desc;
337 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
338 
339 	RTE_LOG(DEBUG, PMD, "RX Buf size is %d\n", rxq->rx_buf_use_size);
340 	RTE_LOG(DEBUG, PMD, "RX Buf MTU %d\n", eth_dev->data->mtu);
341 
342 	rc = bnxt_init_rx_ring_struct(rxq, socket_id);
343 	if (rc)
344 		goto out;
345 
346 	rxq->queue_id = queue_idx;
347 	rxq->port_id = eth_dev->data->port_id;
348 	rxq->crc_len = (uint8_t)((eth_dev->data->dev_conf.rxmode.hw_strip_crc) ?
349 				0 : ETHER_CRC_LEN);
350 
351 	eth_dev->data->rx_queues[queue_idx] = rxq;
352 	/* Allocate RX ring hardware descriptors */
353 	if (bnxt_alloc_rings(bp, queue_idx, NULL, rxq->rx_ring, rxq->cp_ring,
354 			"rxr")) {
355 		RTE_LOG(ERR, PMD,
356 			"ring_dma_zone_reserve for rx_ring failed!\n");
357 		bnxt_rx_queue_release_op(rxq);
358 		rc = -ENOMEM;
359 		goto out;
360 	}
361 
362 out:
363 	return rc;
364 }
365 
366 int
367 bnxt_rx_queue_intr_enable_op(struct rte_eth_dev *eth_dev, uint16_t queue_id)
368 {
369 	struct bnxt_rx_queue *rxq;
370 	struct bnxt_cp_ring_info *cpr;
371 	int rc = 0;
372 
373 	if (eth_dev->data->rx_queues) {
374 		rxq = eth_dev->data->rx_queues[queue_id];
375 		if (!rxq) {
376 			rc = -EINVAL;
377 			return rc;
378 		}
379 		cpr = rxq->cp_ring;
380 		B_CP_DB_ARM(cpr);
381 	}
382 	return rc;
383 }
384 
385 int
386 bnxt_rx_queue_intr_disable_op(struct rte_eth_dev *eth_dev, uint16_t queue_id)
387 {
388 	struct bnxt_rx_queue *rxq;
389 	struct bnxt_cp_ring_info *cpr;
390 	int rc = 0;
391 
392 	if (eth_dev->data->rx_queues) {
393 		rxq = eth_dev->data->rx_queues[queue_id];
394 		if (!rxq) {
395 			rc = -EINVAL;
396 			return rc;
397 		}
398 		cpr = rxq->cp_ring;
399 		B_CP_DB_DISARM(cpr);
400 	}
401 	return rc;
402 }
403