net/txgbe: add queue stats mapping
[dpdk.git] / drivers / net / dpaa / fmlib / fm_lib.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2008-2016 Freescale Semiconductor Inc.
3  * Copyright 2017-2020 NXP
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <unistd.h>
12 #include <termios.h>
13 #include <sys/ioctl.h>
14 #include <stdbool.h>
15 #include <rte_common.h>
16
17 #include "fm_ext.h"
18 #include "fm_pcd_ext.h"
19 #include "fm_port_ext.h"
20 #include <dpaa_ethdev.h>
21
22 #define DEV_TO_ID(p) \
23         do { \
24                 t_device *p_dev = (t_device *)p; \
25                 p = UINT_TO_PTR(p_dev->id); \
26         } while (0)
27
28 /* Major and minor are in sync with FMD, respin is for fmlib identification */
29 #define FM_LIB_VERSION_MAJOR    21
30 #define FM_LIB_VERSION_MINOR    1
31 #define FM_LIB_VERSION_RESPIN   0
32
33 #if (FMD_API_VERSION_MAJOR != FM_LIB_VERSION_MAJOR) || \
34         (FMD_API_VERSION_MINOR != FM_LIB_VERSION_MINOR)
35 #warning FMD and FMLIB version mismatch
36 #endif
37
38 t_handle
39 fm_open(uint8_t id)
40 {
41         t_device *p_dev;
42         int fd;
43         char dev_name[20];
44         static bool called;
45         ioc_fm_api_version_t ver;
46
47         _fml_dbg("Calling...\n");
48
49         p_dev = (t_device *)malloc(sizeof(t_device));
50         if (p_dev == NULL)
51                 return NULL;
52
53         memset(dev_name, 0, 20);
54         sprintf(dev_name, "%s%s%d", "/dev/", DEV_FM_NAME, id);
55         fd = open(dev_name, O_RDWR);
56         if (fd < 0) {
57                 free(p_dev);
58                 return NULL;
59         }
60
61         p_dev->id = id;
62         p_dev->fd = fd;
63         if (!called) {
64                 called = true;
65                 fm_get_api_version((t_handle)p_dev, &ver);
66
67                 if (ver.version.major != FMD_API_VERSION_MAJOR ||
68                     ver.version.minor != FMD_API_VERSION_MINOR ||
69                         ver.version.respin != FMD_API_VERSION_RESPIN) {
70                         DPAA_PMD_WARN("Compiled against FMD API ver %u.%u.%u",
71                                       FMD_API_VERSION_MAJOR,
72                                 FMD_API_VERSION_MINOR, FMD_API_VERSION_RESPIN);
73                         DPAA_PMD_WARN("Running with FMD API ver %u.%u.%u",
74                                       ver.version.major, ver.version.minor,
75                                 ver.version.respin);
76                 }
77         }
78         _fml_dbg("Finishing.\n");
79
80         return (t_handle)p_dev;
81 }
82
83 void fm_close(t_handle h_fm)
84 {
85         t_device *p_dev = (t_device *)h_fm;
86
87         _fml_dbg("Calling...\n");
88
89         close(p_dev->fd);
90         free(p_dev);
91
92         _fml_dbg("Finishing.\n");
93 }
94
95 uint32_t
96 fm_get_api_version(t_handle h_fm, ioc_fm_api_version_t *p_version)
97 {
98         t_device *p_dev = (t_device *)h_fm;
99         int ret;
100
101         _fml_dbg("Calling...\n");
102
103         ret = ioctl(p_dev->fd, FM_IOC_GET_API_VERSION, p_version);
104         if (ret) {
105                 DPAA_PMD_ERR("cannot get API version, error %i (%s)\n",
106                              errno, strerror(errno));
107                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
108         }
109         _fml_dbg("Finishing.\n");
110
111         return E_OK;
112 }
113
114 t_handle
115 fm_pcd_open(t_fm_pcd_params *p_fm_pcd_params)
116 {
117         t_device *p_dev;
118         int fd;
119         char dev_name[20];
120
121         _fml_dbg("Calling...\n");
122
123         p_dev = (t_device *)malloc(sizeof(t_device));
124         if (p_dev == NULL)
125                 return NULL;
126
127         memset(dev_name, 0, 20);
128         sprintf(dev_name, "%s%s%u-pcd", "/dev/", DEV_FM_NAME,
129                 (uint32_t)((t_device *)p_fm_pcd_params->h_fm)->id);
130         fd = open(dev_name, O_RDWR);
131         if (fd < 0) {
132                 free(p_dev);
133                 return NULL;
134         }
135
136         p_dev->id = ((t_device *)p_fm_pcd_params->h_fm)->id;
137         p_dev->fd = fd;
138         p_dev->owners = 0;
139
140         _fml_dbg("Finishing.\n");
141
142         return (t_handle)p_dev;
143 }
144
145 void
146 fm_pcd_close(t_handle h_fm_pcd)
147 {
148         t_device *p_dev = (t_device *)h_fm_pcd;
149
150         _fml_dbg("Calling...\n");
151
152         close(p_dev->fd);
153
154         if (p_dev->owners) {
155                 printf("\nTry delete a prev created pcd handler(owners:%u)!\n",
156                         p_dev->owners);
157                 return;
158         }
159
160         free(p_dev);
161
162         _fml_dbg("Finishing.\n");
163 }
164
165 uint32_t
166 fm_pcd_enable(t_handle h_fm_pcd)
167 {
168         t_device *p_dev = (t_device *)h_fm_pcd;
169
170         _fml_dbg("Calling...\n");
171
172         if (ioctl(p_dev->fd, FM_PCD_IOC_ENABLE))
173                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
174
175         _fml_dbg("Finishing.\n");
176
177         return E_OK;
178 }
179
180 uint32_t
181 fm_pcd_disable(t_handle h_fm_pcd)
182 {
183         t_device *p_dev = (t_device *)h_fm_pcd;
184
185         _fml_dbg("Calling...\n");
186
187         if (ioctl(p_dev->fd, FM_PCD_IOC_DISABLE))
188                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
189
190         _fml_dbg("Finishing.\n");
191
192         return E_OK;
193 }
194
195 t_handle
196 fm_pcd_net_env_characteristics_set(t_handle h_fm_pcd,
197                 ioc_fm_pcd_net_env_params_t *params)
198 {
199         t_device *p_pcd_dev = (t_device *)h_fm_pcd;
200         t_device *p_dev = NULL;
201
202         _fml_dbg("Calling...\n");
203
204         params->id = NULL;
205
206         if (ioctl(p_pcd_dev->fd, FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET,
207                   params))
208                 return NULL;
209
210         p_dev = (t_device *)malloc(sizeof(t_device));
211         if (p_dev == NULL)
212                 return NULL;
213
214         memset(p_dev, 0, sizeof(t_device));
215         p_dev->h_user_priv = (t_handle)p_pcd_dev;
216         p_pcd_dev->owners++;
217         p_dev->id = PTR_TO_UINT(params->id);
218
219         _fml_dbg("Finishing.\n");
220
221         return (t_handle)p_dev;
222 }
223
224 uint32_t
225 fm_pcd_net_env_characteristics_delete(t_handle h_net_env)
226 {
227         t_device *p_dev = (t_device *)h_net_env;
228         t_device *p_pcd_dev = NULL;
229         ioc_fm_obj_t id;
230
231         _fml_dbg("Calling...\n");
232
233         p_pcd_dev = (t_device *)p_dev->h_user_priv;
234         id.obj = UINT_TO_PTR(p_dev->id);
235
236         if (ioctl(p_pcd_dev->fd, FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE,
237                   &id))
238                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
239
240         p_pcd_dev->owners--;
241         free(p_dev);
242
243         _fml_dbg("Finishing.\n");
244
245         return E_OK;
246 }
247
248 t_handle
249 fm_pcd_kg_scheme_set(t_handle h_fm_pcd,
250                      ioc_fm_pcd_kg_scheme_params_t *params)
251 {
252         t_device *p_pcd_dev = (t_device *)h_fm_pcd;
253         t_device *p_dev = NULL;
254         int ret;
255
256         _fml_dbg("Calling...\n");
257
258         params->id = NULL;
259
260         if (params->param.modify) {
261                 if (params->param.scm_id.scheme_id)
262                         DEV_TO_ID(params->param.scm_id.scheme_id);
263                 else
264                         return NULL;
265         }
266
267         /* correct h_net_env param from scheme */
268         if (params->param.net_env_params.net_env_id)
269                 DEV_TO_ID(params->param.net_env_params.net_env_id);
270
271         /* correct next engine params handlers: cc*/
272         if (params->param.next_engine == e_IOC_FM_PCD_CC &&
273             params->param.kg_next_engine_params.cc.tree_id)
274                 DEV_TO_ID(params->param.kg_next_engine_params.cc.tree_id);
275
276         ret = ioctl(p_pcd_dev->fd, FM_PCD_IOC_KG_SCHEME_SET, params);
277         if (ret) {
278                 DPAA_PMD_ERR("  cannot set kg scheme, error %i (%s)\n",
279                              errno, strerror(errno));
280                 return NULL;
281         }
282
283         p_dev = (t_device *)malloc(sizeof(t_device));
284         if (p_dev == NULL)
285                 return NULL;
286
287         memset(p_dev, 0, sizeof(t_device));
288         p_dev->h_user_priv = (t_handle)p_pcd_dev;
289         /* increase owners only if a new scheme is created */
290         if (!params->param.modify)
291                 p_pcd_dev->owners++;
292         p_dev->id = PTR_TO_UINT(params->id);
293
294         _fml_dbg("Finishing.\n");
295
296         return (t_handle)p_dev;
297 }
298
299 uint32_t
300 fm_pcd_kg_scheme_delete(t_handle h_scheme)
301 {
302         t_device *p_dev = (t_device *)h_scheme;
303         t_device *p_pcd_dev = NULL;
304         ioc_fm_obj_t id;
305
306         _fml_dbg("Calling...\n");
307
308         p_pcd_dev =  (t_device *)p_dev->h_user_priv;
309         id.obj = UINT_TO_PTR(p_dev->id);
310
311         if (ioctl(p_pcd_dev->fd, FM_PCD_IOC_KG_SCHEME_DELETE, &id)) {
312                 DPAA_PMD_WARN("cannot delete kg scheme, error %i (%s)\n",
313                               errno, strerror(errno));
314                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
315         }
316
317         p_pcd_dev->owners--;
318         free(p_dev);
319
320         _fml_dbg("Finishing.\n");
321
322         return E_OK;
323 }
324
325 typedef struct {
326         e_fm_port_type  port_type;      /**< Port type */
327         uint8_t         port_id;        /**< Port Id - relative to type */
328 } t_fm_port;
329
330 t_handle
331 fm_port_open(t_fm_port_params *p_fm_port_params)
332 {
333         t_device *p_dev;
334         int fd;
335         char dev_name[30];
336         t_fm_port *p_fm_port;
337
338         _fml_dbg("Calling...\n");
339
340         p_dev = (t_device *)malloc(sizeof(t_device));
341         if (p_dev == NULL)
342                 return NULL;
343
344         memset(p_dev, 0, sizeof(t_device));
345
346         p_fm_port = (t_fm_port *)malloc(sizeof(t_fm_port));
347         if (!p_fm_port) {
348                 free(p_dev);
349                 return NULL;
350         }
351         memset(p_fm_port, 0, sizeof(t_fm_port));
352         memset(dev_name, 0, sizeof(dev_name));
353         switch (p_fm_port_params->port_type) {
354         case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
355                 sprintf(dev_name, "%s%s%u-port-oh%d", "/dev/", DEV_FM_NAME,
356                         (uint32_t)((t_device *)p_fm_port_params->h_fm)->id,
357                         p_fm_port_params->port_id);
358                 break;
359         case e_FM_PORT_TYPE_RX:
360                 sprintf(dev_name, "%s%s%u-port-rx%d", "/dev/", DEV_FM_NAME,
361                         (uint32_t)((t_device *)p_fm_port_params->h_fm)->id,
362                         p_fm_port_params->port_id);
363                 break;
364         case e_FM_PORT_TYPE_RX_10G:
365                 sprintf(dev_name, "%s%s%u-port-rx%d", "/dev/", DEV_FM_NAME,
366                         (uint32_t)((t_device *)p_fm_port_params->h_fm)->id,
367                         FM_MAX_NUM_OF_1G_RX_PORTS + p_fm_port_params->port_id);
368                 break;
369         case e_FM_PORT_TYPE_TX:
370                 sprintf(dev_name, "%s%s%u-port-tx%d", "/dev/", DEV_FM_NAME,
371                         (uint32_t)((t_device *)p_fm_port_params->h_fm)->id,
372                         p_fm_port_params->port_id);
373                 break;
374         case e_FM_PORT_TYPE_TX_10G:
375                 sprintf(dev_name, "%s%s%u-port-tx%d", "/dev/", DEV_FM_NAME,
376                         (uint32_t)((t_device *)p_fm_port_params->h_fm)->id,
377                         FM_MAX_NUM_OF_1G_TX_PORTS + p_fm_port_params->port_id);
378                 break;
379         default:
380                 free(p_fm_port);
381                 free(p_dev);
382                 return NULL;
383         }
384
385         fd = open(dev_name, O_RDWR);
386         if (fd < 0) {
387                 free(p_fm_port);
388                 free(p_dev);
389                 return NULL;
390         }
391
392         p_fm_port->port_type = p_fm_port_params->port_type;
393         p_fm_port->port_id = p_fm_port_params->port_id;
394         p_dev->id = p_fm_port_params->port_id;
395         p_dev->fd = fd;
396         p_dev->h_user_priv = (t_handle)p_fm_port;
397
398         _fml_dbg("Finishing.\n");
399
400         return (t_handle)p_dev;
401 }
402
403 void
404 fm_port_close(t_handle h_fm_port)
405 {
406         t_device *p_dev = (t_device *)h_fm_port;
407
408         _fml_dbg("Calling...\n");
409
410         close(p_dev->fd);
411         if (p_dev->h_user_priv)
412                 free(p_dev->h_user_priv);
413         free(p_dev);
414
415         _fml_dbg("Finishing.\n");
416 }
417
418 uint32_t
419 fm_port_disable(t_handle h_fm_port)
420 {
421         t_device *p_dev = (t_device *)h_fm_port;
422
423         _fml_dbg("Calling...\n");
424
425         if (ioctl(p_dev->fd, FM_PORT_IOC_DISABLE))
426                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
427
428         _fml_dbg("Finishing.\n");
429
430         return E_OK;
431 }
432
433 uint32_t
434 fm_port_enable(t_handle h_fm_port)
435 {
436         t_device *p_dev = (t_device *)h_fm_port;
437
438         _fml_dbg("Calling...\n");
439
440         if (ioctl(p_dev->fd, FM_PORT_IOC_ENABLE))
441                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
442
443         _fml_dbg("Finishing.\n");
444
445         return E_OK;
446 }
447
448 uint32_t
449 fm_port_set_pcd(t_handle h_fm_port,
450                 ioc_fm_port_pcd_params_t *p)
451 {
452         t_device *p_dev = (t_device *)h_fm_port;
453
454         _fml_dbg("Calling...\n");
455
456         /* correct h_net_env param from t_fm_portPcdParams */
457         DEV_TO_ID(p->net_env_id);
458
459         /* correct pcd structures according to what support was set */
460         if (p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC ||
461                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR ||
462                 p->pcd_support == e_IOC_FM_PCD_PRS_CC) {
463                 if (p->p_cc_params && p->p_cc_params->cc_tree_id)
464                         DEV_TO_ID(p->p_cc_params->cc_tree_id);
465                 else
466                         DPAA_PMD_WARN("Coarse Classification not set !");
467         }
468
469         if (p->pcd_support == e_IOC_FM_PCD_PRS_KG ||
470                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC ||
471                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR ||
472                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_PLCR){
473                 if (p->p_kg_params) {
474                         uint32_t i;
475                         ioc_fm_port_pcd_kg_params_t *kg_params;
476
477                         kg_params = p->p_kg_params;
478
479                         for (i = 0; i < kg_params->num_schemes; i++)
480                                 if (kg_params->scheme_ids[i])
481                                         DEV_TO_ID(kg_params->scheme_ids[i]);
482                                 else
483                                         DPAA_PMD_WARN("Scheme:%u not set!!", i);
484
485                         if (kg_params->direct_scheme)
486                                 DEV_TO_ID(kg_params->direct_scheme_id);
487                 } else {
488                         DPAA_PMD_WARN("KeyGen not set !");
489                 }
490         }
491
492         if (p->pcd_support == e_IOC_FM_PCD_PLCR_ONLY ||
493                 p->pcd_support == e_IOC_FM_PCD_PRS_PLCR ||
494                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR ||
495                 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_PLCR) {
496                 if (p->p_plcr_params) {
497                         if (p->p_plcr_params->plcr_profile_id)
498                                 DEV_TO_ID(p->p_plcr_params->plcr_profile_id);
499                         else
500                                 DPAA_PMD_WARN("Policer not set !");
501                 }
502         }
503
504         if (p->p_ip_reassembly_manip)
505                 DEV_TO_ID(p->p_ip_reassembly_manip);
506
507         if (p->p_capwap_reassembly_manip)
508                 DEV_TO_ID(p->p_capwap_reassembly_manip);
509
510         if (ioctl(p_dev->fd, FM_PORT_IOC_SET_PCD, p))
511                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
512
513         _fml_dbg("Finishing.\n");
514
515         return E_OK;
516 }
517
518 uint32_t
519 fm_port_delete_pcd(t_handle h_fm_port)
520 {
521         t_device *p_dev = (t_device *)h_fm_port;
522
523         _fml_dbg("Calling...\n");
524
525         if (ioctl(p_dev->fd, FM_PORT_IOC_DELETE_PCD))
526                 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG);
527
528         _fml_dbg("Finishing.\n");
529
530         return E_OK;
531 }
532
533 t_handle
534 create_device(t_handle h_user_priv, t_handle h_dev_id)
535 {
536         t_device *p_user_priv_dev = (t_device *)h_user_priv;
537         t_device *p_dev = NULL;
538
539         _fml_dbg("Calling...\n");
540
541         p_dev = (t_device *)malloc(sizeof(t_device));
542         if (p_dev == NULL)
543                 return NULL;
544
545         memset(p_dev, 0, sizeof(t_device));
546         p_dev->h_user_priv = h_user_priv;
547         p_user_priv_dev->owners++;
548         p_dev->id = PTR_TO_UINT(h_dev_id);
549
550         _fml_dbg("Finishing.\n");
551
552         return (t_handle)p_dev;
553 }
554
555 t_handle
556 get_device_id(t_handle h_dev)
557 {
558         t_device *p_dev = (t_device *)h_dev;
559
560         return (t_handle)p_dev->id;
561 }