1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2008-2016 Freescale Semiconductor Inc. 3 * Copyright 2017-2024 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..."); 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."); 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..."); 88 89 close(p_dev->fd); 90 free(p_dev); 91 92 _fml_dbg("Finishing."); 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..."); 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)", 106 errno, strerror(errno)); 107 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG); 108 } 109 _fml_dbg("Finishing."); 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..."); 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."); 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..."); 151 152 close(p_dev->fd); 153 154 if (p_dev->owners) { 155 printf("\nTry delete a prev created pcd handler(owners:%u)!", 156 p_dev->owners); 157 return; 158 } 159 160 free(p_dev); 161 162 _fml_dbg("Finishing."); 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..."); 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."); 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..."); 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."); 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..."); 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."); 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..."); 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."); 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..."); 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)", 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."); 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..."); 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)", 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."); 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..."); 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."); 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..."); 409 410 close(p_dev->fd); 411 free(p_dev->h_user_priv); 412 free(p_dev); 413 414 _fml_dbg("Finishing."); 415 } 416 417 uint32_t 418 fm_port_disable(t_handle h_fm_port) 419 { 420 t_device *p_dev = (t_device *)h_fm_port; 421 422 _fml_dbg("Calling..."); 423 424 if (ioctl(p_dev->fd, FM_PORT_IOC_DISABLE)) 425 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG); 426 427 _fml_dbg("Finishing."); 428 429 return E_OK; 430 } 431 432 uint32_t 433 fm_port_enable(t_handle h_fm_port) 434 { 435 t_device *p_dev = (t_device *)h_fm_port; 436 437 _fml_dbg("Calling..."); 438 439 if (ioctl(p_dev->fd, FM_PORT_IOC_ENABLE)) 440 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG); 441 442 _fml_dbg("Finishing."); 443 444 return E_OK; 445 } 446 447 uint32_t 448 fm_port_set_pcd(t_handle h_fm_port, 449 ioc_fm_port_pcd_params_t *p) 450 { 451 t_device *p_dev = (t_device *)h_fm_port; 452 453 _fml_dbg("Calling..."); 454 455 /* correct h_net_env param from t_fm_portPcdParams */ 456 DEV_TO_ID(p->net_env_id); 457 458 /* correct pcd structures according to what support was set */ 459 if (p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC || 460 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR || 461 p->pcd_support == e_IOC_FM_PCD_PRS_CC) { 462 if (p->p_cc_params && p->p_cc_params->cc_tree_id) 463 DEV_TO_ID(p->p_cc_params->cc_tree_id); 464 else 465 DPAA_PMD_WARN("Coarse Classification not set !"); 466 } 467 468 if (p->pcd_support == e_IOC_FM_PCD_PRS_KG || 469 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC || 470 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR || 471 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_PLCR){ 472 if (p->p_kg_params) { 473 uint32_t i; 474 ioc_fm_port_pcd_kg_params_t *kg_params; 475 476 kg_params = p->p_kg_params; 477 478 for (i = 0; i < kg_params->num_schemes; i++) 479 if (kg_params->scheme_ids[i]) 480 DEV_TO_ID(kg_params->scheme_ids[i]); 481 else 482 DPAA_PMD_WARN("Scheme:%u not set!!", i); 483 484 if (kg_params->direct_scheme) 485 DEV_TO_ID(kg_params->direct_scheme_id); 486 } else { 487 DPAA_PMD_WARN("KeyGen not set !"); 488 } 489 } 490 491 if (p->pcd_support == e_IOC_FM_PCD_PLCR_ONLY || 492 p->pcd_support == e_IOC_FM_PCD_PRS_PLCR || 493 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_CC_AND_PLCR || 494 p->pcd_support == e_IOC_FM_PCD_PRS_KG_AND_PLCR) { 495 if (p->p_plcr_params) { 496 if (p->p_plcr_params->plcr_profile_id) 497 DEV_TO_ID(p->p_plcr_params->plcr_profile_id); 498 else 499 DPAA_PMD_WARN("Policer not set !"); 500 } 501 } 502 503 if (p->p_ip_reassembly_manip) 504 DEV_TO_ID(p->p_ip_reassembly_manip); 505 506 if (p->p_capwap_reassembly_manip) 507 DEV_TO_ID(p->p_capwap_reassembly_manip); 508 509 if (ioctl(p_dev->fd, FM_PORT_IOC_SET_PCD, p)) 510 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG); 511 512 _fml_dbg("Finishing."); 513 514 return E_OK; 515 } 516 517 uint32_t 518 fm_port_delete_pcd(t_handle h_fm_port) 519 { 520 t_device *p_dev = (t_device *)h_fm_port; 521 522 _fml_dbg("Calling..."); 523 524 if (ioctl(p_dev->fd, FM_PORT_IOC_DELETE_PCD)) 525 RETURN_ERROR(MINOR, E_INVALID_OPERATION, NO_MSG); 526 527 _fml_dbg("Finishing."); 528 529 return E_OK; 530 } 531 532 t_handle 533 create_device(t_handle h_user_priv, t_handle h_dev_id) 534 { 535 t_device *p_user_priv_dev = (t_device *)h_user_priv; 536 t_device *p_dev = NULL; 537 538 _fml_dbg("Calling..."); 539 540 p_dev = (t_device *)malloc(sizeof(t_device)); 541 if (p_dev == NULL) 542 return NULL; 543 544 memset(p_dev, 0, sizeof(t_device)); 545 p_dev->h_user_priv = h_user_priv; 546 p_user_priv_dev->owners++; 547 p_dev->id = PTR_TO_UINT(h_dev_id); 548 549 _fml_dbg("Finishing."); 550 551 return (t_handle)p_dev; 552 } 553 554 t_handle 555 get_device_id(t_handle h_dev) 556 { 557 t_device *p_dev = (t_device *)h_dev; 558 559 return (t_handle)p_dev->id; 560 } 561