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