xref: /dpdk/drivers/net/dpaa/dpaa_flow.c (revision e498f3b51f3882c43eccb3d5b59b1d045b51c39a)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017-2019,2021-2024 NXP
3  */
4 
5 /* System headers */
6 #include <stdio.h>
7 #include <inttypes.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 
11 #include <dpaa_ethdev.h>
12 #include <dpaa_flow.h>
13 #include <rte_dpaa_logs.h>
14 #include <fmlib/fm_port_ext.h>
15 #include <fmlib/fm_vsp_ext.h>
16 #include <rte_pmd_dpaa.h>
17 
18 #define DPAA_MAX_NUM_ETH_DEV	8
19 
20 static inline
21 ioc_fm_pcd_extract_entry_t *
22 SCH_EXT_ARR(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
23 {
24 return &scheme_params->param.key_ext_and_hash.extract_array[hdr_idx];
25 }
26 
27 #define SCH_EXT_HDR(scheme_params, hdr_idx) \
28 	SCH_EXT_ARR(scheme_params, hdr_idx)->extract_params.extract_by_hdr
29 
30 #define SCH_EXT_FULL_FLD(scheme_params, hdr_idx) \
31 	SCH_EXT_HDR(scheme_params, hdr_idx).extract_by_hdr_type.full_field
32 
33 /* FMAN mac indexes mappings (0 is unused, first 8 are for 1G, next for 10G
34  * ports).
35  */
36 const uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
37 
38 /* FM global info */
39 struct dpaa_fm_info {
40 	t_handle fman_handle;
41 	t_handle pcd_handle;
42 };
43 
44 /*FM model to read and write from file */
45 struct dpaa_fm_model {
46 	uint32_t dev_count;
47 	uint8_t device_order[DPAA_MAX_NUM_ETH_DEV];
48 	t_fm_port_params fm_port_params[DPAA_MAX_NUM_ETH_DEV];
49 	t_handle netenv_devid[DPAA_MAX_NUM_ETH_DEV];
50 	t_handle scheme_devid[DPAA_MAX_NUM_ETH_DEV][2];
51 };
52 
53 static struct dpaa_fm_info fm_info;
54 static struct dpaa_fm_model fm_model;
55 static const char *fm_log = "/tmp/fmdpdk.bin";
56 
57 static void fm_prev_cleanup(void)
58 {
59 	uint32_t fman_id = 0, i = 0, devid;
60 	struct dpaa_if dpaa_intf = {0};
61 	t_fm_pcd_params fm_pcd_params = {0};
62 	PMD_INIT_FUNC_TRACE();
63 
64 	fm_info.fman_handle = fm_open(fman_id);
65 	if (!fm_info.fman_handle) {
66 		DPAA_PMD_ERR("unable to open FMAN");
67 		return;
68 	}
69 
70 	fm_pcd_params.h_fm = fm_info.fman_handle;
71 	fm_pcd_params.prs_support = true;
72 	fm_pcd_params.kg_support = true;
73 	/* FM PCD Open */
74 	fm_info.pcd_handle = fm_pcd_open(&fm_pcd_params);
75 	if (!fm_info.pcd_handle) {
76 		DPAA_PMD_ERR("unable to open PCD");
77 		return;
78 	}
79 
80 	while (i < fm_model.dev_count) {
81 		devid = fm_model.device_order[i];
82 		/* FM Port Open */
83 		fm_model.fm_port_params[devid].h_fm = fm_info.fman_handle;
84 		dpaa_intf.port_handle =
85 				fm_port_open(&fm_model.fm_port_params[devid]);
86 		dpaa_intf.scheme_handle[0] = create_device(fm_info.pcd_handle,
87 					fm_model.scheme_devid[devid][0]);
88 		dpaa_intf.scheme_count = 1;
89 		if (fm_model.scheme_devid[devid][1]) {
90 			dpaa_intf.scheme_handle[1] =
91 				create_device(fm_info.pcd_handle,
92 					fm_model.scheme_devid[devid][1]);
93 			if (dpaa_intf.scheme_handle[1])
94 				dpaa_intf.scheme_count++;
95 		}
96 
97 		dpaa_intf.netenv_handle = create_device(fm_info.pcd_handle,
98 					fm_model.netenv_devid[devid]);
99 		i++;
100 		if (!dpaa_intf.netenv_handle ||
101 			!dpaa_intf.scheme_handle[0] ||
102 			!dpaa_intf.port_handle)
103 			continue;
104 
105 		if (dpaa_fm_deconfig(&dpaa_intf, NULL))
106 			DPAA_PMD_ERR("DPAA FM deconfig failed");
107 	}
108 
109 	if (dpaa_fm_term())
110 		DPAA_PMD_ERR("DPAA FM term failed");
111 
112 	memset(&fm_model, 0, sizeof(struct dpaa_fm_model));
113 }
114 
115 void dpaa_write_fm_config_to_file(void)
116 {
117 	size_t bytes_write;
118 	FILE *fp = fopen(fm_log, "wb");
119 	PMD_INIT_FUNC_TRACE();
120 
121 	if (!fp) {
122 		DPAA_PMD_ERR("File open failed");
123 		return;
124 	}
125 	bytes_write = fwrite(&fm_model, sizeof(struct dpaa_fm_model), 1, fp);
126 	if (!bytes_write) {
127 		DPAA_PMD_WARN("No bytes write");
128 		fclose(fp);
129 		return;
130 	}
131 	fclose(fp);
132 }
133 
134 static void dpaa_read_fm_config_from_file(void)
135 {
136 	size_t bytes_read;
137 	FILE *fp = fopen(fm_log, "rb");
138 	PMD_INIT_FUNC_TRACE();
139 
140 	if (!fp)
141 		return;
142 	DPAA_PMD_INFO("Previous DPDK-FM config instance present, cleaning up.");
143 
144 	bytes_read = fread(&fm_model, sizeof(struct dpaa_fm_model), 1, fp);
145 	if (!bytes_read) {
146 		DPAA_PMD_WARN("No bytes read");
147 		fclose(fp);
148 		return;
149 	}
150 	fclose(fp);
151 
152 	/*FM cleanup from previous configured app */
153 	fm_prev_cleanup();
154 }
155 
156 static inline int
157 set_hash_params_eth(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
158 {
159 	int k;
160 
161 	for (k = 0; k < 2; k++) {
162 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
163 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
164 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
165 						HEADER_TYPE_ETH;
166 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
167 						e_IOC_FM_PCD_HDR_INDEX_NONE;
168 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
169 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
170 		if (k == 0)
171 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth =
172 						IOC_NET_HF_ETH_SA;
173 		else
174 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).eth =
175 						IOC_NET_HF_ETH_DA;
176 		hdr_idx++;
177 	}
178 	return hdr_idx;
179 }
180 
181 static inline int
182 set_hash_params_ipv4(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
183 {
184 	int k;
185 
186 	for (k = 0; k < 2; k++) {
187 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
188 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
189 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
190 						HEADER_TYPE_IPV4;
191 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
192 						e_IOC_FM_PCD_HDR_INDEX_NONE;
193 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
194 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
195 		if (k == 0)
196 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 =
197 					ioc_net_hf_ipv_4_src_ip;
198 		else
199 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv4 =
200 					ioc_net_hf_ipv_4_dst_ip;
201 		hdr_idx++;
202 	}
203 	return hdr_idx;
204 }
205 
206 static inline int
207 set_hash_params_ipv6(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
208 {
209 	int k;
210 
211 	for (k = 0; k < 2; k++) {
212 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
213 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
214 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
215 							HEADER_TYPE_IPV6;
216 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
217 						e_IOC_FM_PCD_HDR_INDEX_NONE;
218 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
219 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
220 		if (k == 0)
221 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 =
222 					ioc_net_hf_ipv_6_src_ip;
223 		else
224 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).ipv6 =
225 					ioc_net_hf_ipv_6_dst_ip;
226 		hdr_idx++;
227 	}
228 	return hdr_idx;
229 }
230 
231 static inline int
232 set_hash_params_udp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
233 {
234 	int k;
235 
236 	for (k = 0; k < 2; k++) {
237 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
238 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
239 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
240 						HEADER_TYPE_UDP;
241 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
242 						e_IOC_FM_PCD_HDR_INDEX_NONE;
243 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
244 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
245 		if (k == 0)
246 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp =
247 					IOC_NET_HF_UDP_PORT_SRC;
248 		else
249 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).udp =
250 					IOC_NET_HF_UDP_PORT_DST;
251 		hdr_idx++;
252 	}
253 	return hdr_idx;
254 }
255 
256 static inline int
257 set_hash_params_tcp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
258 {
259 	int k;
260 
261 	for (k = 0; k < 2; k++) {
262 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
263 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
264 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
265 						HEADER_TYPE_TCP;
266 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
267 						e_IOC_FM_PCD_HDR_INDEX_NONE;
268 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
269 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
270 		if (k == 0)
271 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp =
272 					IOC_NET_HF_TCP_PORT_SRC;
273 		else
274 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).tcp =
275 					IOC_NET_HF_TCP_PORT_DST;
276 		hdr_idx++;
277 	}
278 	return hdr_idx;
279 }
280 
281 static inline int
282 set_hash_params_sctp(ioc_fm_pcd_kg_scheme_params_t *scheme_params, int hdr_idx)
283 {
284 	int k;
285 
286 	for (k = 0; k < 2; k++) {
287 		SCH_EXT_ARR(scheme_params, hdr_idx)->type =
288 						e_IOC_FM_PCD_EXTRACT_BY_HDR;
289 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr =
290 						HEADER_TYPE_SCTP;
291 		SCH_EXT_HDR(scheme_params, hdr_idx).hdr_index =
292 						e_IOC_FM_PCD_HDR_INDEX_NONE;
293 		SCH_EXT_HDR(scheme_params, hdr_idx).type =
294 						e_IOC_FM_PCD_EXTRACT_FULL_FIELD;
295 		if (k == 0)
296 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp =
297 					IOC_NET_HF_SCTP_PORT_SRC;
298 		else
299 			SCH_EXT_FULL_FLD(scheme_params, hdr_idx).sctp =
300 					IOC_NET_HF_SCTP_PORT_DST;
301 		hdr_idx++;
302 	}
303 	return hdr_idx;
304 }
305 
306 /* Set scheme params for hash distribution */
307 static int set_scheme_params(ioc_fm_pcd_kg_scheme_params_t *scheme_params,
308 	ioc_fm_pcd_net_env_params_t *dist_units,
309 	struct dpaa_if *dpaa_intf,
310 	struct fman_if *fif)
311 {
312 	int dist_idx, hdr_idx = 0;
313 	PMD_INIT_FUNC_TRACE();
314 
315 	if (fif->num_profiles) {
316 		scheme_params->param.override_storage_profile = true;
317 		scheme_params->param.storage_profile.direct = true;
318 		scheme_params->param.storage_profile.profile_select
319 			.direct_relative_profile_id = fm_default_vsp_id(fif);
320 	}
321 
322 	scheme_params->param.use_hash = 1;
323 	scheme_params->param.modify = false;
324 	scheme_params->param.always_direct = false;
325 	scheme_params->param.scheme_counter.update = 1;
326 	scheme_params->param.scheme_counter.value = 0;
327 	scheme_params->param.next_engine = e_IOC_FM_PCD_DONE;
328 	scheme_params->param.base_fqid = dpaa_intf->rx_queues[0].fqid;
329 	scheme_params->param.net_env_params.net_env_id =
330 		dpaa_intf->netenv_handle;
331 	scheme_params->param.net_env_params.num_of_distinction_units =
332 		dist_units->param.num_of_distinction_units;
333 
334 	scheme_params->param.key_ext_and_hash.hash_dist_num_of_fqids =
335 			dpaa_intf->nb_rx_queues;
336 	scheme_params->param.key_ext_and_hash.num_of_used_extracts =
337 			2 * dist_units->param.num_of_distinction_units;
338 
339 	for (dist_idx = 0; dist_idx <
340 		dist_units->param.num_of_distinction_units;
341 		dist_idx++) {
342 		switch (dist_units->param.units[dist_idx].hdrs[0].hdr) {
343 		case HEADER_TYPE_ETH:
344 			hdr_idx = set_hash_params_eth(scheme_params, hdr_idx);
345 			break;
346 
347 		case HEADER_TYPE_IPV4:
348 			hdr_idx = set_hash_params_ipv4(scheme_params, hdr_idx);
349 			break;
350 
351 		case HEADER_TYPE_IPV6:
352 			hdr_idx = set_hash_params_ipv6(scheme_params, hdr_idx);
353 			break;
354 
355 		case HEADER_TYPE_UDP:
356 			hdr_idx = set_hash_params_udp(scheme_params, hdr_idx);
357 			break;
358 
359 		case HEADER_TYPE_TCP:
360 			hdr_idx = set_hash_params_tcp(scheme_params, hdr_idx);
361 			break;
362 
363 		case HEADER_TYPE_SCTP:
364 			hdr_idx = set_hash_params_sctp(scheme_params, hdr_idx);
365 			break;
366 
367 		default:
368 			DPAA_PMD_ERR("Invalid Distinction Unit");
369 			return -1;
370 		}
371 	}
372 
373 	return 0;
374 }
375 
376 static void set_dist_units(ioc_fm_pcd_net_env_params_t *dist_units,
377 			   uint64_t req_dist_set)
378 {
379 	uint32_t loop = 0, dist_idx = 0, dist_field = 0;
380 	int l2_configured = 0, ipv4_configured = 0, ipv6_configured = 0;
381 	int udp_configured = 0, tcp_configured = 0, sctp_configured = 0;
382 	PMD_INIT_FUNC_TRACE();
383 
384 	if (!req_dist_set)
385 		dist_units->param.units[dist_idx++].hdrs[0].hdr =
386 			HEADER_TYPE_ETH;
387 
388 	while (req_dist_set) {
389 		if (req_dist_set % 2 != 0) {
390 			dist_field = 1U << loop;
391 			switch (dist_field) {
392 			case RTE_ETH_RSS_L2_PAYLOAD:
393 
394 				if (l2_configured)
395 					break;
396 				l2_configured = 1;
397 
398 				dist_units->param.units[dist_idx++].hdrs[0].hdr
399 					= HEADER_TYPE_ETH;
400 				break;
401 
402 			case RTE_ETH_RSS_IPV4:
403 			case RTE_ETH_RSS_FRAG_IPV4:
404 			case RTE_ETH_RSS_NONFRAG_IPV4_OTHER:
405 
406 				if (ipv4_configured)
407 					break;
408 				ipv4_configured = 1;
409 				dist_units->param.units[dist_idx++].hdrs[0].hdr
410 					= HEADER_TYPE_IPV4;
411 				break;
412 
413 			case RTE_ETH_RSS_IPV6:
414 			case RTE_ETH_RSS_FRAG_IPV6:
415 			case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
416 			case RTE_ETH_RSS_IPV6_EX:
417 
418 				if (ipv6_configured)
419 					break;
420 				ipv6_configured = 1;
421 				dist_units->param.units[dist_idx++].hdrs[0].hdr
422 					= HEADER_TYPE_IPV6;
423 				break;
424 
425 			case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
426 			case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
427 			case RTE_ETH_RSS_IPV6_TCP_EX:
428 
429 				if (tcp_configured)
430 					break;
431 				tcp_configured = 1;
432 				dist_units->param.units[dist_idx++].hdrs[0].hdr
433 					= HEADER_TYPE_TCP;
434 				break;
435 
436 			case RTE_ETH_RSS_NONFRAG_IPV4_UDP:
437 			case RTE_ETH_RSS_NONFRAG_IPV6_UDP:
438 			case RTE_ETH_RSS_IPV6_UDP_EX:
439 
440 				if (udp_configured)
441 					break;
442 				udp_configured = 1;
443 				dist_units->param.units[dist_idx++].hdrs[0].hdr
444 					= HEADER_TYPE_UDP;
445 				break;
446 
447 			case RTE_ETH_RSS_NONFRAG_IPV4_SCTP:
448 			case RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
449 
450 				if (sctp_configured)
451 					break;
452 				sctp_configured = 1;
453 
454 				dist_units->param.units[dist_idx++].hdrs[0].hdr
455 					= HEADER_TYPE_SCTP;
456 				break;
457 
458 			default:
459 				DPAA_PMD_ERR("Bad flow distribution option");
460 			}
461 		}
462 		req_dist_set = req_dist_set >> 1;
463 		loop++;
464 	}
465 
466 	/* Dist units is set to dist_idx */
467 	dist_units->param.num_of_distinction_units = dist_idx;
468 }
469 
470 /* Apply PCD configuration on interface */
471 static inline int set_port_pcd(struct dpaa_if *dpaa_intf)
472 {
473 	int ret = 0;
474 	unsigned int idx;
475 	ioc_fm_port_pcd_params_t pcd_param;
476 	ioc_fm_port_pcd_prs_params_t prs_param;
477 	ioc_fm_port_pcd_kg_params_t  kg_param;
478 
479 	PMD_INIT_FUNC_TRACE();
480 
481 	/* PCD support for hash distribution */
482 	uint8_t pcd_support = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG;
483 
484 	memset(&pcd_param, 0, sizeof(pcd_param));
485 	memset(&prs_param, 0, sizeof(prs_param));
486 	memset(&kg_param, 0, sizeof(kg_param));
487 
488 	/* Set parse params */
489 	prs_param.first_prs_hdr = HEADER_TYPE_ETH;
490 
491 	/* Set kg params */
492 	for (idx = 0; idx < dpaa_intf->scheme_count; idx++)
493 		kg_param.scheme_ids[idx] = dpaa_intf->scheme_handle[idx];
494 	kg_param.num_schemes = dpaa_intf->scheme_count;
495 
496 	/* Set pcd params */
497 	pcd_param.net_env_id = dpaa_intf->netenv_handle;
498 	pcd_param.pcd_support = pcd_support;
499 	pcd_param.p_kg_params = &kg_param;
500 	pcd_param.p_prs_params = &prs_param;
501 
502 	/* FM PORT Disable */
503 	ret = fm_port_disable(dpaa_intf->port_handle);
504 	if (ret != E_OK) {
505 		DPAA_PMD_ERR("fm_port_disable: Failed");
506 		return ret;
507 	}
508 
509 	/* FM PORT SetPCD */
510 	ret = fm_port_set_pcd(dpaa_intf->port_handle, &pcd_param);
511 	if (ret != E_OK) {
512 		DPAA_PMD_ERR("fm_port_set_pcd: Failed");
513 		return ret;
514 	}
515 
516 	/* FM PORT Enable */
517 	ret = fm_port_enable(dpaa_intf->port_handle);
518 	if (ret != E_OK) {
519 		DPAA_PMD_ERR("fm_port_enable: Failed");
520 		goto fm_port_delete_pcd;
521 	}
522 
523 	return 0;
524 
525 fm_port_delete_pcd:
526 	/* FM PORT DeletePCD */
527 	ret = fm_port_delete_pcd(dpaa_intf->port_handle);
528 	if (ret != E_OK) {
529 		DPAA_PMD_ERR("fm_port_delete_pcd: Failed");
530 		return ret;
531 	}
532 	return -1;
533 }
534 
535 /* Unset PCD NerEnv and scheme */
536 static inline void unset_pcd_netenv_scheme(struct dpaa_if *dpaa_intf)
537 {
538 	int ret;
539 	PMD_INIT_FUNC_TRACE();
540 
541 	/* reduce scheme count */
542 	if (dpaa_intf->scheme_count)
543 		dpaa_intf->scheme_count--;
544 
545 	DPAA_PMD_DEBUG("KG SCHEME DEL %d handle =%p",
546 		dpaa_intf->scheme_count,
547 		dpaa_intf->scheme_handle[dpaa_intf->scheme_count]);
548 
549 	ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle
550 					[dpaa_intf->scheme_count]);
551 	if (ret != E_OK)
552 		DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed");
553 
554 	dpaa_intf->scheme_handle[dpaa_intf->scheme_count] = NULL;
555 }
556 
557 /* Set PCD NetEnv and Scheme and default scheme */
558 static inline int set_default_scheme(struct dpaa_if *dpaa_intf)
559 {
560 	ioc_fm_pcd_kg_scheme_params_t scheme_params;
561 	int idx = dpaa_intf->scheme_count;
562 	PMD_INIT_FUNC_TRACE();
563 
564 	/* Set PCD NetEnvCharacteristics */
565 	memset(&scheme_params, 0, sizeof(scheme_params));
566 
567 	/* Adding 10 to default schemes as the number of interface would be
568 	 * lesser than 10 and the relative scheme ids should be unique for
569 	 * every scheme.
570 	 */
571 	scheme_params.param.scm_id.relative_scheme_id =
572 		10 + dpaa_intf->ifid;
573 	scheme_params.param.use_hash = 0;
574 	scheme_params.param.next_engine = e_IOC_FM_PCD_DONE;
575 	scheme_params.param.net_env_params.num_of_distinction_units = 0;
576 	scheme_params.param.net_env_params.net_env_id =
577 		dpaa_intf->netenv_handle;
578 	scheme_params.param.base_fqid = dpaa_intf->rx_queues[0].fqid;
579 	scheme_params.param.key_ext_and_hash.hash_dist_num_of_fqids = 1;
580 	scheme_params.param.key_ext_and_hash.num_of_used_extracts = 0;
581 	scheme_params.param.modify = false;
582 	scheme_params.param.always_direct = false;
583 	scheme_params.param.scheme_counter.update = 1;
584 	scheme_params.param.scheme_counter.value = 0;
585 
586 	/* FM PCD KgSchemeSet */
587 	dpaa_intf->scheme_handle[idx] =
588 		fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params);
589 	DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p",
590 		idx, dpaa_intf->scheme_handle[idx]);
591 	if (!dpaa_intf->scheme_handle[idx]) {
592 		DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed");
593 		return -1;
594 	}
595 
596 	fm_model.scheme_devid[dpaa_intf->ifid][idx] =
597 				get_device_id(dpaa_intf->scheme_handle[idx]);
598 	dpaa_intf->scheme_count++;
599 	return 0;
600 }
601 
602 
603 /* Set PCD NetEnv and Scheme and default scheme */
604 static inline int set_pcd_netenv_scheme(struct dpaa_if *dpaa_intf,
605 					uint64_t req_dist_set,
606 					struct fman_if *fif)
607 {
608 	int ret = -1;
609 	ioc_fm_pcd_net_env_params_t dist_units;
610 	ioc_fm_pcd_kg_scheme_params_t scheme_params;
611 	int idx = dpaa_intf->scheme_count;
612 	PMD_INIT_FUNC_TRACE();
613 
614 	/* Set PCD NetEnvCharacteristics */
615 	memset(&dist_units, 0, sizeof(dist_units));
616 	memset(&scheme_params, 0, sizeof(scheme_params));
617 
618 	/* Set dist unit header type */
619 	set_dist_units(&dist_units, req_dist_set);
620 
621 	scheme_params.param.scm_id.relative_scheme_id = dpaa_intf->ifid;
622 
623 	/* Set PCD Scheme params */
624 	ret = set_scheme_params(&scheme_params, &dist_units, dpaa_intf, fif);
625 	if (ret) {
626 		DPAA_PMD_ERR("Set scheme params: Failed");
627 		return -1;
628 	}
629 
630 	/* FM PCD KgSchemeSet */
631 	dpaa_intf->scheme_handle[idx] =
632 		fm_pcd_kg_scheme_set(fm_info.pcd_handle, &scheme_params);
633 	DPAA_PMD_DEBUG("KG SCHEME SET %d handle =%p",
634 			idx, dpaa_intf->scheme_handle[idx]);
635 	if (!dpaa_intf->scheme_handle[idx]) {
636 		DPAA_PMD_ERR("fm_pcd_kg_scheme_set: Failed");
637 		return -1;
638 	}
639 
640 	fm_model.scheme_devid[dpaa_intf->ifid][idx] =
641 				get_device_id(dpaa_intf->scheme_handle[idx]);
642 	dpaa_intf->scheme_count++;
643 	return 0;
644 }
645 
646 
647 static inline int get_rx_port_type(struct fman_if *fif)
648 {
649 	/* For onic ports, configure the VSP as offline ports so that
650 	 * kernel can configure correct port.
651 	 */
652 	if (fif->mac_type == fman_offline_internal ||
653 	    fif->mac_type == fman_onic)
654 		return e_FM_PORT_TYPE_OH_OFFLINE_PARSING;
655 	/* For 1G fm-mac9 and fm-mac10 ports, configure the VSP as 10G
656 	 * ports so that kernel can configure correct port.
657 	 */
658 	else if (fif->mac_type == fman_mac_1g &&
659 		fif->mac_idx >= DPAA_10G_MAC_START_IDX)
660 		return e_FM_PORT_TYPE_RX_10G;
661 	else if (fif->mac_type == fman_mac_1g)
662 		return e_FM_PORT_TYPE_RX;
663 	else if (fif->mac_type == fman_mac_2_5g)
664 		return e_FM_PORT_TYPE_RX_2_5G;
665 	else if (fif->mac_type == fman_mac_10g)
666 		return e_FM_PORT_TYPE_RX_10G;
667 
668 	DPAA_PMD_ERR("MAC type unsupported");
669 	return e_FM_PORT_TYPE_DUMMY;
670 }
671 
672 static inline int set_fm_port_handle(struct dpaa_if *dpaa_intf,
673 				     uint64_t req_dist_set,
674 				     struct fman_if *fif)
675 {
676 	t_fm_port_params	fm_port_params;
677 	ioc_fm_pcd_net_env_params_t dist_units;
678 	PMD_INIT_FUNC_TRACE();
679 
680 	/* Memset FM port params */
681 	memset(&fm_port_params, 0, sizeof(fm_port_params));
682 
683 	/* Set FM port params */
684 	fm_port_params.h_fm = fm_info.fman_handle;
685 	fm_port_params.port_type = get_rx_port_type(fif);
686 	fm_port_params.port_id = mac_idx[fif->mac_idx];
687 
688 	/* FM PORT Open */
689 	dpaa_intf->port_handle = fm_port_open(&fm_port_params);
690 	if (!dpaa_intf->port_handle) {
691 		DPAA_PMD_ERR("fm_port_open: Failed");
692 		return -1;
693 	}
694 
695 	fm_model.fm_port_params[dpaa_intf->ifid] = fm_port_params;
696 
697 	/* Set PCD NetEnvCharacteristics */
698 	memset(&dist_units, 0, sizeof(dist_units));
699 
700 	/* Set dist unit header type */
701 	set_dist_units(&dist_units, req_dist_set);
702 
703 	/* FM PCD NetEnvCharacteristicsSet */
704 	dpaa_intf->netenv_handle =
705 		fm_pcd_net_env_characteristics_set(fm_info.pcd_handle,
706 							&dist_units);
707 	if (!dpaa_intf->netenv_handle) {
708 		DPAA_PMD_ERR("fm_pcd_net_env_characteristics_set: Failed");
709 		return -1;
710 	}
711 
712 	fm_model.netenv_devid[dpaa_intf->ifid] =
713 				get_device_id(dpaa_intf->netenv_handle);
714 
715 	return 0;
716 }
717 
718 /* De-Configure DPAA FM */
719 int dpaa_fm_deconfig(struct dpaa_if *dpaa_intf,
720 			struct fman_if *fif __rte_unused)
721 {
722 	int ret;
723 	unsigned int idx;
724 
725 	PMD_INIT_FUNC_TRACE();
726 
727 	/* FM PORT Disable */
728 	ret = fm_port_disable(dpaa_intf->port_handle);
729 	if (ret != E_OK) {
730 		DPAA_PMD_ERR("fm_port_disable: Failed");
731 		return ret;
732 	}
733 
734 	/* FM PORT DeletePCD */
735 	ret = fm_port_delete_pcd(dpaa_intf->port_handle);
736 	if (ret != E_OK) {
737 		DPAA_PMD_ERR("fm_port_delete_pcd: Failed");
738 		return ret;
739 	}
740 
741 	for (idx = 0; idx < dpaa_intf->scheme_count; idx++) {
742 		DPAA_PMD_DEBUG("KG SCHEME DEL %d, handle =%p",
743 			idx, dpaa_intf->scheme_handle[idx]);
744 		/* FM PCD KgSchemeDelete */
745 		ret = fm_pcd_kg_scheme_delete(dpaa_intf->scheme_handle[idx]);
746 		if (ret != E_OK) {
747 			DPAA_PMD_ERR("fm_pcd_kg_scheme_delete: Failed");
748 			return ret;
749 		}
750 		dpaa_intf->scheme_handle[idx] = NULL;
751 	}
752 	/* FM PCD NetEnvCharacteristicsDelete */
753 	ret = fm_pcd_net_env_characteristics_delete(dpaa_intf->netenv_handle);
754 	if (ret != E_OK) {
755 		DPAA_PMD_ERR("fm_pcd_net_env_characteristics_delete: Failed");
756 		return ret;
757 	}
758 	dpaa_intf->netenv_handle = NULL;
759 
760 	if (fif && fif->is_shared_mac) {
761 		ret = fm_port_enable(dpaa_intf->port_handle);
762 		if (ret != E_OK) {
763 			DPAA_PMD_ERR("shared mac re-enable failed");
764 			return ret;
765 		}
766 	}
767 
768 	/* FM PORT Close */
769 	fm_port_close(dpaa_intf->port_handle);
770 	dpaa_intf->port_handle = NULL;
771 
772 	/* Set scheme count to 0 */
773 	dpaa_intf->scheme_count = 0;
774 
775 	return 0;
776 }
777 
778 int dpaa_fm_config(struct rte_eth_dev *dev, uint64_t req_dist_set)
779 {
780 	struct dpaa_if *dpaa_intf = dev->data->dev_private;
781 	struct fman_if *fif = dev->process_private;
782 	int ret;
783 	unsigned int i = 0;
784 	PMD_INIT_FUNC_TRACE();
785 
786 	if (dpaa_intf->port_handle) {
787 		if (dpaa_fm_deconfig(dpaa_intf, fif))
788 			DPAA_PMD_ERR("DPAA FM deconfig failed");
789 	}
790 
791 	if (!dev->data->nb_rx_queues)
792 		return 0;
793 
794 	if (dev->data->nb_rx_queues & (dev->data->nb_rx_queues - 1)) {
795 		DPAA_PMD_ERR("No of queues should be power of 2");
796 		return -1;
797 	}
798 
799 	/* Open FM Port and set it in port info */
800 	ret = set_fm_port_handle(dpaa_intf, req_dist_set, fif);
801 	if (ret) {
802 		DPAA_PMD_ERR("Set FM Port handle: Failed");
803 		return -1;
804 	}
805 
806 	if (fif->num_profiles) {
807 		for (i = 0; i < dev->data->nb_rx_queues; i++)
808 			dpaa_intf->rx_queues[i].vsp_id =
809 				fm_default_vsp_id(fif);
810 
811 		i = 0;
812 	}
813 
814 	/* Set PCD netenv and scheme */
815 	if (req_dist_set) {
816 		ret = set_pcd_netenv_scheme(dpaa_intf, req_dist_set, fif);
817 		if (ret) {
818 			DPAA_PMD_ERR("Set PCD NetEnv and Scheme dist: Failed");
819 			goto unset_fm_port_handle;
820 		}
821 	}
822 	/* Set default netenv and scheme */
823 	if (!fif->is_shared_mac) {
824 		ret = set_default_scheme(dpaa_intf);
825 		if (ret) {
826 			DPAA_PMD_ERR("Set PCD NetEnv and Scheme: Failed");
827 			goto unset_pcd_netenv_scheme1;
828 		}
829 	}
830 
831 	/* Set Port PCD */
832 	ret = set_port_pcd(dpaa_intf);
833 	if (ret) {
834 		DPAA_PMD_ERR("Set Port PCD: Failed");
835 		goto unset_pcd_netenv_scheme;
836 	}
837 
838 	for (; i < fm_model.dev_count; i++)
839 		if (fm_model.device_order[i] == dpaa_intf->ifid)
840 			return 0;
841 
842 	fm_model.device_order[fm_model.dev_count] = dpaa_intf->ifid;
843 	fm_model.dev_count++;
844 
845 	return 0;
846 
847 unset_pcd_netenv_scheme:
848 	unset_pcd_netenv_scheme(dpaa_intf);
849 
850 unset_pcd_netenv_scheme1:
851 	unset_pcd_netenv_scheme(dpaa_intf);
852 
853 unset_fm_port_handle:
854 	/* FM PORT Close */
855 	fm_port_close(dpaa_intf->port_handle);
856 	dpaa_intf->port_handle = NULL;
857 	return -1;
858 }
859 
860 int dpaa_fm_init(void)
861 {
862 	t_handle fman_handle;
863 	t_handle pcd_handle;
864 	t_fm_pcd_params fm_pcd_params = {0};
865 	/* Hard-coded : fman id 0 since one fman is present in LS104x */
866 	int fman_id = 0, ret;
867 	PMD_INIT_FUNC_TRACE();
868 
869 	dpaa_read_fm_config_from_file();
870 
871 	/* FM Open */
872 	fman_handle = fm_open(fman_id);
873 	if (!fman_handle) {
874 		DPAA_PMD_ERR("fm_open: Failed");
875 		return -1;
876 	}
877 
878 	/* FM PCD Open */
879 	fm_pcd_params.h_fm = fman_handle;
880 	fm_pcd_params.prs_support = true;
881 	fm_pcd_params.kg_support = true;
882 	pcd_handle = fm_pcd_open(&fm_pcd_params);
883 	if (!pcd_handle) {
884 		fm_close(fman_handle);
885 		DPAA_PMD_ERR("fm_pcd_open: Failed");
886 		return -1;
887 	}
888 
889 	/* FM PCD Enable */
890 	ret = fm_pcd_enable(pcd_handle);
891 	if (ret) {
892 		fm_close(fman_handle);
893 		fm_pcd_close(pcd_handle);
894 		DPAA_PMD_ERR("fm_pcd_enable: Failed");
895 		return -1;
896 	}
897 
898 	/* Set fman and pcd handle in fm info */
899 	fm_info.fman_handle = fman_handle;
900 	fm_info.pcd_handle = pcd_handle;
901 
902 	return 0;
903 }
904 
905 
906 /* De-initialization of FM */
907 int dpaa_fm_term(void)
908 {
909 	int ret;
910 
911 	PMD_INIT_FUNC_TRACE();
912 
913 	if (fm_info.pcd_handle && fm_info.fman_handle) {
914 		/* FM PCD Disable */
915 		ret = fm_pcd_disable(fm_info.pcd_handle);
916 		if (ret) {
917 			DPAA_PMD_ERR("fm_pcd_disable: Failed");
918 			return -1;
919 		}
920 
921 		/* FM PCD Close */
922 		fm_pcd_close(fm_info.pcd_handle);
923 		fm_info.pcd_handle = NULL;
924 	}
925 
926 	if (fm_info.fman_handle) {
927 		/* FM Close */
928 		fm_close(fm_info.fman_handle);
929 		fm_info.fman_handle = NULL;
930 	}
931 
932 	if (access(fm_log, F_OK) != -1) {
933 		ret = remove(fm_log);
934 		if (ret)
935 			DPAA_PMD_ERR("File remove: Failed");
936 	}
937 	return 0;
938 }
939 
940 static int dpaa_port_vsp_configure(struct dpaa_if *dpaa_intf,
941 		uint8_t vsp_id, t_handle fman_handle,
942 		struct fman_if *fif, u32 mbuf_data_room_size)
943 {
944 	t_fm_vsp_params vsp_params;
945 	t_fm_buffer_prefix_content buf_prefix_cont;
946 	uint8_t idx = mac_idx[fif->mac_idx];
947 	int ret;
948 
949 	if (vsp_id == fif->base_profile_id && fif->is_shared_mac) {
950 		/* For shared interface, VSP of base
951 		 * profile is default pool located in kernel.
952 		 */
953 		dpaa_intf->vsp_bpid[vsp_id] = 0;
954 		return 0;
955 	}
956 
957 	if (vsp_id >= DPAA_VSP_PROFILE_MAX_NUM) {
958 		DPAA_PMD_ERR("VSP ID %d exceeds MAX number %d",
959 			vsp_id, DPAA_VSP_PROFILE_MAX_NUM);
960 		return -1;
961 	}
962 
963 	memset(&vsp_params, 0, sizeof(vsp_params));
964 	vsp_params.h_fm = fman_handle;
965 	vsp_params.relative_profile_id = vsp_id;
966 	if (fif->mac_type == fman_offline_internal ||
967 	    fif->mac_type == fman_onic)
968 		vsp_params.port_params.port_id = fif->mac_idx;
969 	else
970 		vsp_params.port_params.port_id = idx;
971 
972 	vsp_params.port_params.port_type = get_rx_port_type(fif);
973 	if (vsp_params.port_params.port_type == e_FM_PORT_TYPE_DUMMY) {
974 		DPAA_PMD_ERR("Mac type %d error", fif->mac_type);
975 		return -1;
976 	}
977 
978 	vsp_params.ext_buf_pools.num_of_pools_used = 1;
979 	vsp_params.ext_buf_pools.ext_buf_pool[0].id = dpaa_intf->vsp_bpid[vsp_id];
980 	vsp_params.ext_buf_pools.ext_buf_pool[0].size = mbuf_data_room_size;
981 
982 	dpaa_intf->vsp_handle[vsp_id] = fm_vsp_config(&vsp_params);
983 	if (!dpaa_intf->vsp_handle[vsp_id]) {
984 		DPAA_PMD_ERR("fm_vsp_config error for profile %d", vsp_id);
985 		return -EINVAL;
986 	}
987 
988 	/* configure the application buffer (structure, size and
989 	 * content)
990 	 */
991 
992 	memset(&buf_prefix_cont, 0, sizeof(buf_prefix_cont));
993 
994 	buf_prefix_cont.priv_data_size = 16;
995 	buf_prefix_cont.data_align = 64;
996 	buf_prefix_cont.pass_prs_result = true;
997 	buf_prefix_cont.pass_time_stamp = true;
998 	buf_prefix_cont.pass_hash_result = false;
999 	buf_prefix_cont.pass_all_other_pcdinfo = false;
1000 	buf_prefix_cont.manip_ext_space =
1001 		RTE_PKTMBUF_HEADROOM - DPAA_MBUF_HW_ANNOTATION;
1002 
1003 	ret = fm_vsp_config_buffer_prefix_content(dpaa_intf->vsp_handle[vsp_id],
1004 					       &buf_prefix_cont);
1005 	if (ret != E_OK) {
1006 		DPAA_PMD_ERR("fm_vsp_config_buffer_prefix_content error for profile %d err: %d",
1007 			     vsp_id, ret);
1008 		return ret;
1009 	}
1010 
1011 	/* initialize the FM VSP module */
1012 	ret = fm_vsp_init(dpaa_intf->vsp_handle[vsp_id]);
1013 	if (ret != E_OK) {
1014 		DPAA_PMD_ERR("fm_vsp_init error for profile %d err:%d",
1015 			 vsp_id, ret);
1016 		return ret;
1017 	}
1018 
1019 	return 0;
1020 }
1021 
1022 int dpaa_port_vsp_update(struct dpaa_if *dpaa_intf,
1023 		bool fmc_mode, uint8_t vsp_id, uint32_t bpid,
1024 		struct fman_if *fif, u32 mbuf_data_room_size)
1025 {
1026 	int ret = 0;
1027 	t_handle fman_handle;
1028 
1029 	if (!fif->num_profiles)
1030 		return 0;
1031 
1032 	if (vsp_id >= fif->num_profiles)
1033 		return 0;
1034 
1035 	if (dpaa_intf->vsp_bpid[vsp_id] == bpid)
1036 		return 0;
1037 
1038 	if (dpaa_intf->vsp_handle[vsp_id]) {
1039 		ret = fm_vsp_free(dpaa_intf->vsp_handle[vsp_id]);
1040 		if (ret != E_OK) {
1041 			DPAA_PMD_ERR("Error fm_vsp_free: err %d vsp_handle[%d]",
1042 				     ret, vsp_id);
1043 			return ret;
1044 		}
1045 		dpaa_intf->vsp_handle[vsp_id] = 0;
1046 	}
1047 
1048 	if (fmc_mode)
1049 		fman_handle = fm_open(0);
1050 	else
1051 		fman_handle = fm_info.fman_handle;
1052 
1053 	dpaa_intf->vsp_bpid[vsp_id] = bpid;
1054 
1055 	return dpaa_port_vsp_configure(dpaa_intf, vsp_id, fman_handle, fif,
1056 				       mbuf_data_room_size);
1057 }
1058 
1059 int dpaa_port_vsp_cleanup(struct dpaa_if *dpaa_intf, struct fman_if *fif)
1060 {
1061 	int idx, ret;
1062 
1063 	for (idx = 0; idx < (uint8_t)fif->num_profiles; idx++) {
1064 		if (dpaa_intf->vsp_handle[idx]) {
1065 			ret = fm_vsp_free(dpaa_intf->vsp_handle[idx]);
1066 			if (ret != E_OK) {
1067 				DPAA_PMD_ERR("Error fm_vsp_free: err %d"
1068 					     " vsp_handle[%d]", ret, idx);
1069 				return ret;
1070 			}
1071 		}
1072 	}
1073 
1074 	return E_OK;
1075 }
1076