xref: /dpdk/drivers/net/dpaa2/base/dpaa2_hw_dpni.c (revision 6ac5a55b)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
4  *   Copyright 2016-2021 NXP
5  *
6  */
7 
8 #include <time.h>
9 #include <net/if.h>
10 
11 #include <rte_mbuf.h>
12 #include <ethdev_driver.h>
13 #include <rte_malloc.h>
14 #include <rte_memcpy.h>
15 #include <rte_string_fns.h>
16 #include <rte_cycles.h>
17 #include <rte_kvargs.h>
18 #include <rte_dev.h>
19 
20 #include <dpaa2_pmd_logs.h>
21 #include <dpaa2_hw_pvt.h>
22 #include <dpaa2_hw_mempool.h>
23 
24 #include "../dpaa2_ethdev.h"
25 
26 int
27 dpaa2_distset_to_dpkg_profile_cfg(
28 		uint64_t req_dist_set,
29 		struct dpkg_profile_cfg *kg_cfg);
30 
31 int
rte_pmd_dpaa2_set_custom_hash(uint16_t port_id,uint16_t offset,uint8_t size)32 rte_pmd_dpaa2_set_custom_hash(uint16_t port_id,
33 			      uint16_t offset,
34 			      uint8_t size)
35 {
36 	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
37 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
38 	struct fsl_mc_io *dpni = priv->hw;
39 	struct dpni_rx_tc_dist_cfg tc_cfg;
40 	struct dpkg_profile_cfg kg_cfg;
41 	void *p_params;
42 	int ret, tc_index = 0;
43 
44 	if (!rte_eth_dev_is_valid_port(port_id)) {
45 		DPAA2_PMD_WARN("Invalid port id %u", port_id);
46 		return -EINVAL;
47 	}
48 
49 	if (strcmp(eth_dev->device->driver->name,
50 			RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) {
51 		DPAA2_PMD_WARN("Not a valid dpaa2 port");
52 		return -EINVAL;
53 	}
54 
55 	p_params = rte_zmalloc(
56 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
57 	if (!p_params) {
58 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
59 		return -ENOMEM;
60 	}
61 
62 	kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA;
63 	kg_cfg.extracts[0].extract.from_data.offset = offset;
64 	kg_cfg.extracts[0].extract.from_data.size = size;
65 	kg_cfg.extracts[0].num_of_byte_masks = 0;
66 	kg_cfg.num_extracts = 1;
67 
68 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
69 	if (ret) {
70 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
71 		rte_free(p_params);
72 		return ret;
73 	}
74 
75 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
76 	tc_cfg.key_cfg_iova = (size_t)(DPAA2_VADDR_TO_IOVA(p_params));
77 	tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
78 	tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
79 
80 	ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
81 				  &tc_cfg);
82 	rte_free(p_params);
83 	if (ret) {
84 		DPAA2_PMD_ERR(
85 			     "Setting distribution for Rx failed with err: %d",
86 			     ret);
87 		return ret;
88 	}
89 
90 	return 0;
91 }
92 
93 int
dpaa2_setup_flow_dist(struct rte_eth_dev * eth_dev,uint64_t req_dist_set,int tc_index)94 dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
95 	uint64_t req_dist_set, int tc_index)
96 {
97 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
98 	struct fsl_mc_io *dpni = eth_dev->process_private;
99 	struct dpni_rx_dist_cfg tc_cfg;
100 	struct dpkg_profile_cfg kg_cfg;
101 	void *p_params;
102 	int ret, tc_dist_queues;
103 
104 	/*TC distribution size is set with dist_queues or
105 	 * nb_rx_queues % dist_queues in order of TC priority index.
106 	 * Calculating dist size for this tc_index:-
107 	 */
108 	tc_dist_queues = eth_dev->data->nb_rx_queues -
109 		tc_index * priv->dist_queues;
110 	if (tc_dist_queues <= 0) {
111 		DPAA2_PMD_INFO("No distribution on TC%d", tc_index);
112 		return 0;
113 	}
114 
115 	if (tc_dist_queues > priv->dist_queues)
116 		tc_dist_queues = priv->dist_queues;
117 
118 	p_params = rte_malloc(
119 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
120 	if (!p_params) {
121 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
122 		return -ENOMEM;
123 	}
124 
125 	memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
126 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
127 
128 	ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
129 	if (ret) {
130 		DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported",
131 			      req_dist_set);
132 		rte_free(p_params);
133 		return ret;
134 	}
135 
136 	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
137 	tc_cfg.dist_size = tc_dist_queues;
138 	tc_cfg.enable = true;
139 	tc_cfg.tc = tc_index;
140 
141 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
142 	if (ret) {
143 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
144 		rte_free(p_params);
145 		return ret;
146 	}
147 
148 	ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg);
149 	rte_free(p_params);
150 	if (ret) {
151 		DPAA2_PMD_ERR(
152 			     "Setting distribution for Rx failed with err: %d",
153 			     ret);
154 		return ret;
155 	}
156 
157 	return 0;
158 }
159 
dpaa2_remove_flow_dist(struct rte_eth_dev * eth_dev,uint8_t tc_index)160 int dpaa2_remove_flow_dist(
161 	struct rte_eth_dev *eth_dev,
162 	uint8_t tc_index)
163 {
164 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
165 	struct fsl_mc_io *dpni = priv->hw;
166 	struct dpni_rx_dist_cfg tc_cfg;
167 	struct dpkg_profile_cfg kg_cfg;
168 	void *p_params;
169 	int ret;
170 
171 	p_params = rte_malloc(
172 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
173 	if (!p_params) {
174 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
175 		return -ENOMEM;
176 	}
177 
178 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
179 	tc_cfg.dist_size = 0;
180 	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
181 	tc_cfg.enable = true;
182 	tc_cfg.tc = tc_index;
183 
184 	memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
185 	kg_cfg.num_extracts = 0;
186 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
187 	if (ret) {
188 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
189 		rte_free(p_params);
190 		return ret;
191 	}
192 
193 	ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token,
194 			&tc_cfg);
195 	rte_free(p_params);
196 	if (ret)
197 		DPAA2_PMD_ERR(
198 			     "Setting distribution for Rx failed with err: %d",
199 			     ret);
200 	return ret;
201 }
202 
203 int
dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set,struct dpkg_profile_cfg * kg_cfg)204 dpaa2_distset_to_dpkg_profile_cfg(
205 		uint64_t req_dist_set,
206 		struct dpkg_profile_cfg *kg_cfg)
207 {
208 	uint32_t loop = 0, i = 0;
209 	uint64_t dist_field = 0;
210 	int l2_configured = 0, l3_configured = 0;
211 	int l4_configured = 0, sctp_configured = 0;
212 	int mpls_configured = 0;
213 	int vlan_configured = 0;
214 	int esp_configured = 0;
215 	int ah_configured = 0;
216 	int pppoe_configured = 0;
217 
218 	memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
219 	while (req_dist_set) {
220 		if (req_dist_set % 2 != 0) {
221 			dist_field = 1ULL << loop;
222 			switch (dist_field) {
223 			case RTE_ETH_RSS_L2_PAYLOAD:
224 			case RTE_ETH_RSS_ETH:
225 				if (l2_configured)
226 					break;
227 				l2_configured = 1;
228 
229 				kg_cfg->extracts[i].extract.from_hdr.prot =
230 					NET_PROT_ETH;
231 				kg_cfg->extracts[i].extract.from_hdr.field =
232 					NH_FLD_ETH_TYPE;
233 				kg_cfg->extracts[i].type =
234 					DPKG_EXTRACT_FROM_HDR;
235 				kg_cfg->extracts[i].extract.from_hdr.type =
236 					DPKG_FULL_FIELD;
237 				i++;
238 				break;
239 
240 			case RTE_ETH_RSS_PPPOE:
241 				if (pppoe_configured)
242 					break;
243 				kg_cfg->extracts[i].extract.from_hdr.prot =
244 					NET_PROT_PPPOE;
245 				kg_cfg->extracts[i].extract.from_hdr.field =
246 					NH_FLD_PPPOE_SID;
247 				kg_cfg->extracts[i].type =
248 					DPKG_EXTRACT_FROM_HDR;
249 				kg_cfg->extracts[i].extract.from_hdr.type =
250 					DPKG_FULL_FIELD;
251 				i++;
252 				break;
253 
254 			case RTE_ETH_RSS_ESP:
255 				if (esp_configured)
256 					break;
257 				esp_configured = 1;
258 
259 				kg_cfg->extracts[i].extract.from_hdr.prot =
260 					NET_PROT_IPSEC_ESP;
261 				kg_cfg->extracts[i].extract.from_hdr.field =
262 					NH_FLD_IPSEC_ESP_SPI;
263 				kg_cfg->extracts[i].type =
264 					DPKG_EXTRACT_FROM_HDR;
265 				kg_cfg->extracts[i].extract.from_hdr.type =
266 					DPKG_FULL_FIELD;
267 				i++;
268 				break;
269 
270 			case RTE_ETH_RSS_AH:
271 				if (ah_configured)
272 					break;
273 				ah_configured = 1;
274 
275 				kg_cfg->extracts[i].extract.from_hdr.prot =
276 					NET_PROT_IPSEC_AH;
277 				kg_cfg->extracts[i].extract.from_hdr.field =
278 					NH_FLD_IPSEC_AH_SPI;
279 				kg_cfg->extracts[i].type =
280 					DPKG_EXTRACT_FROM_HDR;
281 				kg_cfg->extracts[i].extract.from_hdr.type =
282 					DPKG_FULL_FIELD;
283 				i++;
284 				break;
285 
286 			case RTE_ETH_RSS_C_VLAN:
287 			case RTE_ETH_RSS_S_VLAN:
288 				if (vlan_configured)
289 					break;
290 				vlan_configured = 1;
291 
292 				kg_cfg->extracts[i].extract.from_hdr.prot =
293 					NET_PROT_VLAN;
294 				kg_cfg->extracts[i].extract.from_hdr.field =
295 					NH_FLD_VLAN_TCI;
296 				kg_cfg->extracts[i].type =
297 					DPKG_EXTRACT_FROM_HDR;
298 				kg_cfg->extracts[i].extract.from_hdr.type =
299 					DPKG_FULL_FIELD;
300 				i++;
301 				break;
302 
303 			case RTE_ETH_RSS_MPLS:
304 
305 				if (mpls_configured)
306 					break;
307 				mpls_configured = 1;
308 
309 				kg_cfg->extracts[i].extract.from_hdr.prot =
310 					NET_PROT_MPLS;
311 				kg_cfg->extracts[i].extract.from_hdr.field =
312 					NH_FLD_MPLS_MPLSL_1;
313 				kg_cfg->extracts[i].type =
314 					DPKG_EXTRACT_FROM_HDR;
315 				kg_cfg->extracts[i].extract.from_hdr.type =
316 					DPKG_FULL_FIELD;
317 				i++;
318 
319 				kg_cfg->extracts[i].extract.from_hdr.prot =
320 					NET_PROT_MPLS;
321 				kg_cfg->extracts[i].extract.from_hdr.field =
322 					NH_FLD_MPLS_MPLSL_2;
323 				kg_cfg->extracts[i].type =
324 					DPKG_EXTRACT_FROM_HDR;
325 				kg_cfg->extracts[i].extract.from_hdr.type =
326 					DPKG_FULL_FIELD;
327 				i++;
328 
329 				kg_cfg->extracts[i].extract.from_hdr.prot =
330 					NET_PROT_MPLS;
331 				kg_cfg->extracts[i].extract.from_hdr.field =
332 					NH_FLD_MPLS_MPLSL_N;
333 				kg_cfg->extracts[i].type =
334 					DPKG_EXTRACT_FROM_HDR;
335 				kg_cfg->extracts[i].extract.from_hdr.type =
336 					DPKG_FULL_FIELD;
337 				i++;
338 				break;
339 
340 			case RTE_ETH_RSS_IPV4:
341 			case RTE_ETH_RSS_FRAG_IPV4:
342 			case RTE_ETH_RSS_NONFRAG_IPV4_OTHER:
343 			case RTE_ETH_RSS_IPV6:
344 			case RTE_ETH_RSS_FRAG_IPV6:
345 			case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
346 			case RTE_ETH_RSS_IPV6_EX:
347 
348 				if (l3_configured)
349 					break;
350 				l3_configured = 1;
351 
352 				kg_cfg->extracts[i].extract.from_hdr.prot =
353 					NET_PROT_IP;
354 				kg_cfg->extracts[i].extract.from_hdr.field =
355 					NH_FLD_IP_SRC;
356 				kg_cfg->extracts[i].type =
357 					DPKG_EXTRACT_FROM_HDR;
358 				kg_cfg->extracts[i].extract.from_hdr.type =
359 					DPKG_FULL_FIELD;
360 				i++;
361 
362 				kg_cfg->extracts[i].extract.from_hdr.prot =
363 					NET_PROT_IP;
364 				kg_cfg->extracts[i].extract.from_hdr.field =
365 					NH_FLD_IP_DST;
366 				kg_cfg->extracts[i].type =
367 					DPKG_EXTRACT_FROM_HDR;
368 				kg_cfg->extracts[i].extract.from_hdr.type =
369 					DPKG_FULL_FIELD;
370 				i++;
371 
372 				kg_cfg->extracts[i].extract.from_hdr.prot =
373 					NET_PROT_IP;
374 				kg_cfg->extracts[i].extract.from_hdr.field =
375 					NH_FLD_IP_PROTO;
376 				kg_cfg->extracts[i].type =
377 					DPKG_EXTRACT_FROM_HDR;
378 				kg_cfg->extracts[i].extract.from_hdr.type =
379 					DPKG_FULL_FIELD;
380 				kg_cfg->num_extracts++;
381 				i++;
382 			break;
383 
384 			case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
385 			case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
386 			case RTE_ETH_RSS_NONFRAG_IPV4_UDP:
387 			case RTE_ETH_RSS_NONFRAG_IPV6_UDP:
388 			case RTE_ETH_RSS_IPV6_TCP_EX:
389 			case RTE_ETH_RSS_IPV6_UDP_EX:
390 
391 				if (l4_configured)
392 					break;
393 				l4_configured = 1;
394 
395 				kg_cfg->extracts[i].extract.from_hdr.prot =
396 					NET_PROT_TCP;
397 				kg_cfg->extracts[i].extract.from_hdr.field =
398 					NH_FLD_TCP_PORT_SRC;
399 				kg_cfg->extracts[i].type =
400 					DPKG_EXTRACT_FROM_HDR;
401 				kg_cfg->extracts[i].extract.from_hdr.type =
402 					DPKG_FULL_FIELD;
403 				i++;
404 
405 				kg_cfg->extracts[i].extract.from_hdr.prot =
406 					NET_PROT_TCP;
407 				kg_cfg->extracts[i].extract.from_hdr.field =
408 					NH_FLD_TCP_PORT_SRC;
409 				kg_cfg->extracts[i].type =
410 					DPKG_EXTRACT_FROM_HDR;
411 				kg_cfg->extracts[i].extract.from_hdr.type =
412 					DPKG_FULL_FIELD;
413 				i++;
414 				break;
415 
416 			case RTE_ETH_RSS_NONFRAG_IPV4_SCTP:
417 			case RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
418 
419 				if (sctp_configured)
420 					break;
421 				sctp_configured = 1;
422 
423 				kg_cfg->extracts[i].extract.from_hdr.prot =
424 					NET_PROT_SCTP;
425 				kg_cfg->extracts[i].extract.from_hdr.field =
426 					NH_FLD_SCTP_PORT_SRC;
427 				kg_cfg->extracts[i].type =
428 					DPKG_EXTRACT_FROM_HDR;
429 				kg_cfg->extracts[i].extract.from_hdr.type =
430 					DPKG_FULL_FIELD;
431 				i++;
432 
433 				kg_cfg->extracts[i].extract.from_hdr.prot =
434 					NET_PROT_SCTP;
435 				kg_cfg->extracts[i].extract.from_hdr.field =
436 					NH_FLD_SCTP_PORT_DST;
437 				kg_cfg->extracts[i].type =
438 					DPKG_EXTRACT_FROM_HDR;
439 				kg_cfg->extracts[i].extract.from_hdr.type =
440 					DPKG_FULL_FIELD;
441 				i++;
442 				break;
443 
444 			default:
445 				DPAA2_PMD_WARN(
446 				      "unsupported flow dist option 0x%" PRIx64,
447 					     dist_field);
448 				return -EINVAL;
449 			}
450 		}
451 		req_dist_set = req_dist_set >> 1;
452 		loop++;
453 	}
454 	kg_cfg->num_extracts = i;
455 	return 0;
456 }
457 
458 int
dpaa2_attach_bp_list(struct dpaa2_dev_priv * priv,struct fsl_mc_io * dpni,void * blist)459 dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv,
460 	struct fsl_mc_io *dpni, void *blist)
461 {
462 	/* Function to attach a DPNI with a buffer pool list. Buffer pool list
463 	 * handle is passed in blist.
464 	 */
465 	int32_t retcode;
466 	struct dpni_pools_cfg bpool_cfg;
467 	struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist;
468 	struct dpni_buffer_layout layout;
469 	int tot_size;
470 
471 	/* ... rx buffer layout .
472 	 * Check alignment for buffer layouts first
473 	 */
474 
475 	/* ... rx buffer layout ... */
476 	tot_size = RTE_PKTMBUF_HEADROOM;
477 	tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN);
478 
479 	memset(&layout, 0, sizeof(struct dpni_buffer_layout));
480 	layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM |
481 			 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
482 			 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
483 			 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
484 			 DPNI_BUF_LAYOUT_OPT_TIMESTAMP |
485 			 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
486 
487 	layout.pass_timestamp = true;
488 	layout.pass_frame_status = 1;
489 	layout.private_data_size = DPAA2_FD_PTA_SIZE;
490 	layout.pass_parser_result = 1;
491 	layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN;
492 	layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE -
493 				DPAA2_MBUF_HW_ANNOTATION;
494 	retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token,
495 					 DPNI_QUEUE_RX, &layout);
496 	if (retcode) {
497 		DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)",
498 			     retcode);
499 		return retcode;
500 	}
501 
502 	/*Attach buffer pool to the network interface as described by the user*/
503 	memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg));
504 	bpool_cfg.num_dpbp = 1;
505 	bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id;
506 	bpool_cfg.pools[0].backup_pool = 0;
507 	bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size,
508 						DPAA2_PACKET_LAYOUT_ALIGN);
509 	bpool_cfg.pools[0].priority_mask = 0;
510 
511 	retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg);
512 	if (retcode != 0) {
513 		DPAA2_PMD_ERR("Error configuring buffer pool on interface."
514 			      " bpid = %d error code = %d",
515 			      bpool_cfg.pools[0].dpbp_id, retcode);
516 		return retcode;
517 	}
518 
519 	priv->bp_list = bp_list;
520 	return 0;
521 }
522