xref: /dpdk/drivers/net/dpaa/fmlib/fm_lib.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
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 }
562