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