1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2017-2023 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 FMC_OUTPUT_FORMAT_VER 0x106 18 19 #define FMC_NAME_LEN 64 20 #define FMC_FMAN_NUM 2 21 #define FMC_PORTS_PER_FMAN 16 22 #define FMC_SCHEMES_NUM 32 23 #define FMC_SCHEME_PROTOCOLS_NUM 16 24 #define FMC_CC_NODES_NUM 512 25 #define FMC_REPLICATORS_NUM 16 26 #define FMC_PLC_NUM 64 27 #define MAX_SP_CODE_SIZE 0x7C0 28 #define FMC_MANIP_MAX 64 29 #define FMC_HMANIP_MAX 512 30 #define FMC_INSERT_MAX 56 31 #define FM_PCD_MAX_REPS 64 32 33 typedef struct fmc_port_t { 34 e_fm_port_type type; 35 unsigned int number; 36 struct fm_pcd_net_env_params_t distinction_units; 37 struct ioc_fm_port_pcd_params_t pcd_param; 38 struct ioc_fm_port_pcd_prs_params_t prs_param; 39 struct ioc_fm_port_pcd_kg_params_t kg_param; 40 struct ioc_fm_port_pcd_cc_params_t cc_param; 41 char name[FMC_NAME_LEN]; 42 char cctree_name[FMC_NAME_LEN]; 43 t_handle handle; 44 t_handle env_id_handle; 45 t_handle env_id_dev_id; 46 t_handle cctree_handle; 47 t_handle cctree_dev_id; 48 49 unsigned int schemes_count; 50 unsigned int schemes[FMC_SCHEMES_NUM]; 51 unsigned int ccnodes_count; 52 unsigned int ccnodes[FMC_CC_NODES_NUM]; 53 unsigned int htnodes_count; 54 unsigned int htnodes[FMC_CC_NODES_NUM]; 55 56 unsigned int replicators_count; 57 unsigned int replicators[FMC_REPLICATORS_NUM]; 58 ioc_fm_port_vsp_alloc_params_t vsp_param; 59 60 unsigned int ccroot_count; 61 unsigned int ccroot[FMC_CC_NODES_NUM]; 62 enum ioc_fm_pcd_engine ccroot_type[FMC_CC_NODES_NUM]; 63 unsigned int ccroot_manip[FMC_CC_NODES_NUM]; 64 65 unsigned int reasm_index; 66 } fmc_port; 67 68 typedef struct fmc_fman_t { 69 unsigned int number; 70 unsigned int port_count; 71 unsigned int ports[FMC_PORTS_PER_FMAN]; 72 char name[FMC_NAME_LEN]; 73 t_handle handle; 74 char pcd_name[FMC_NAME_LEN]; 75 t_handle pcd_handle; 76 unsigned int kg_payload_offset; 77 78 unsigned int offload_support; 79 80 unsigned int reasm_count; 81 struct fm_pcd_manip_params_t reasm[FMC_MANIP_MAX]; 82 char reasm_name[FMC_MANIP_MAX][FMC_NAME_LEN]; 83 t_handle reasm_handle[FMC_MANIP_MAX]; 84 t_handle reasm_dev_id[FMC_MANIP_MAX]; 85 86 unsigned int frag_count; 87 struct fm_pcd_manip_params_t frag[FMC_MANIP_MAX]; 88 char frag_name[FMC_MANIP_MAX][FMC_NAME_LEN]; 89 t_handle frag_handle[FMC_MANIP_MAX]; 90 t_handle frag_dev_id[FMC_MANIP_MAX]; 91 92 unsigned int hdr_count; 93 struct fm_pcd_manip_params_t hdr[FMC_HMANIP_MAX]; 94 uint8_t insert_data[FMC_HMANIP_MAX][FMC_INSERT_MAX]; 95 char hdr_name[FMC_HMANIP_MAX][FMC_NAME_LEN]; 96 t_handle hdr_handle[FMC_HMANIP_MAX]; 97 t_handle hdr_dev_id[FMC_HMANIP_MAX]; 98 unsigned int hdr_has_next[FMC_HMANIP_MAX]; 99 unsigned int hdr_next[FMC_HMANIP_MAX]; 100 } fmc_fman; 101 102 typedef enum fmc_apply_order_e { 103 fmcengine_start, 104 fmcengine_end, 105 fmcport_start, 106 fmcport_end, 107 fmcscheme, 108 fmcccnode, 109 fmchtnode, 110 fmccctree, 111 fmcpolicer, 112 fmcreplicator, 113 fmcmanipulation 114 } fmc_apply_order_e; 115 116 typedef struct fmc_apply_order_t { 117 fmc_apply_order_e type; 118 unsigned int index; 119 } fmc_apply_order; 120 121 struct fmc_model_t { 122 unsigned int format_version; 123 unsigned int sp_enable; 124 t_fm_pcd_prs_sw_params sp; 125 uint8_t spcode[MAX_SP_CODE_SIZE]; 126 127 unsigned int fman_count; 128 fmc_fman fman[FMC_FMAN_NUM]; 129 130 unsigned int port_count; 131 fmc_port port[FMC_FMAN_NUM * FMC_PORTS_PER_FMAN]; 132 133 unsigned int scheme_count; 134 char scheme_name[FMC_SCHEMES_NUM][FMC_NAME_LEN]; 135 t_handle scheme_handle[FMC_SCHEMES_NUM]; 136 t_handle scheme_dev_id[FMC_SCHEMES_NUM]; 137 struct fm_pcd_kg_scheme_params_t scheme[FMC_SCHEMES_NUM]; 138 139 unsigned int ccnode_count; 140 char ccnode_name[FMC_CC_NODES_NUM][FMC_NAME_LEN]; 141 t_handle ccnode_handle[FMC_CC_NODES_NUM]; 142 t_handle ccnode_dev_id[FMC_CC_NODES_NUM]; 143 struct fm_pcd_cc_node_params_t ccnode[FMC_CC_NODES_NUM]; 144 uint8_t cckeydata[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS] 145 [FM_PCD_MAX_SIZE_OF_KEY]; 146 unsigned char ccmask[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS] 147 [FM_PCD_MAX_SIZE_OF_KEY]; 148 unsigned int 149 ccentry_action_index[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 150 enum ioc_fm_pcd_engine 151 ccentry_action_type[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 152 unsigned char ccentry_frag[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 153 unsigned int ccentry_manip[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 154 unsigned int ccmiss_action_index[FMC_CC_NODES_NUM]; 155 enum ioc_fm_pcd_engine ccmiss_action_type[FMC_CC_NODES_NUM]; 156 unsigned char ccmiss_frag[FMC_CC_NODES_NUM]; 157 unsigned int ccmiss_manip[FMC_CC_NODES_NUM]; 158 159 unsigned int htnode_count; 160 char htnode_name[FMC_CC_NODES_NUM][FMC_NAME_LEN]; 161 t_handle htnode_handle[FMC_CC_NODES_NUM]; 162 t_handle htnode_dev_id[FMC_CC_NODES_NUM]; 163 struct fm_pcd_hash_table_params_t htnode[FMC_CC_NODES_NUM]; 164 165 unsigned int htentry_count[FMC_CC_NODES_NUM]; 166 struct ioc_fm_pcd_cc_key_params_t 167 htentry[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 168 uint8_t htkeydata[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS] 169 [FM_PCD_MAX_SIZE_OF_KEY]; 170 unsigned int 171 htentry_action_index[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 172 enum ioc_fm_pcd_engine 173 htentry_action_type[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 174 unsigned char htentry_frag[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 175 unsigned int htentry_manip[FMC_CC_NODES_NUM][FM_PCD_MAX_NUM_OF_KEYS]; 176 177 unsigned int htmiss_action_index[FMC_CC_NODES_NUM]; 178 enum ioc_fm_pcd_engine htmiss_action_type[FMC_CC_NODES_NUM]; 179 unsigned char htmiss_frag[FMC_CC_NODES_NUM]; 180 unsigned int htmiss_manip[FMC_CC_NODES_NUM]; 181 182 unsigned int replicator_count; 183 char replicator_name[FMC_REPLICATORS_NUM][FMC_NAME_LEN]; 184 t_handle replicator_handle[FMC_REPLICATORS_NUM]; 185 t_handle replicator_dev_id[FMC_REPLICATORS_NUM]; 186 struct fm_pcd_frm_replic_group_params_t replicator[FMC_REPLICATORS_NUM]; 187 unsigned int 188 repentry_action_index[FMC_REPLICATORS_NUM][FM_PCD_MAX_REPS]; 189 unsigned char repentry_frag[FMC_REPLICATORS_NUM][FM_PCD_MAX_REPS]; 190 unsigned int repentry_manip[FMC_REPLICATORS_NUM][FM_PCD_MAX_REPS]; 191 192 unsigned int policer_count; 193 char policer_name[FMC_PLC_NUM][FMC_NAME_LEN]; 194 struct fm_pcd_plcr_profile_params_t policer[FMC_PLC_NUM]; 195 t_handle policer_handle[FMC_PLC_NUM]; 196 t_handle policer_dev_id[FMC_PLC_NUM]; 197 unsigned int policer_action_index[FMC_PLC_NUM][3]; 198 199 unsigned int apply_order_count; 200 fmc_apply_order apply_order[FMC_FMAN_NUM * 201 FMC_PORTS_PER_FMAN * 202 (FMC_SCHEMES_NUM + FMC_CC_NODES_NUM)]; 203 }; 204 205 struct fmc_model_t *g_fmc_model; 206 207 static int 208 dpaa_port_fmc_port_parse(struct fman_if *fif, 209 const struct fmc_model_t *fmc_model, 210 int apply_idx) 211 { 212 int current_port = fmc_model->apply_order[apply_idx].index; 213 const fmc_port *pport = &fmc_model->port[current_port]; 214 uint32_t num; 215 216 if (pport->type == e_FM_PORT_TYPE_OH_OFFLINE_PARSING && 217 pport->number == fif->mac_idx && 218 (fif->mac_type == fman_offline_internal || 219 fif->mac_type == fman_onic)) 220 return current_port; 221 222 if (fif->mac_type == fman_mac_1g) { 223 if (pport->type != e_FM_PORT_TYPE_RX) 224 return -ENODEV; 225 num = pport->number + DPAA_1G_MAC_START_IDX; 226 if (fif->mac_idx == num) 227 return current_port; 228 229 return -ENODEV; 230 } 231 232 if (fif->mac_type == fman_mac_2_5g) { 233 if (pport->type != e_FM_PORT_TYPE_RX_2_5G) 234 return -ENODEV; 235 num = pport->number + DPAA_2_5G_MAC_START_IDX; 236 if (fif->mac_idx == num) 237 return current_port; 238 239 return -ENODEV; 240 } 241 242 if (fif->mac_type == fman_mac_10g) { 243 if (pport->type != e_FM_PORT_TYPE_RX_10G) 244 return -ENODEV; 245 num = pport->number + DPAA_10G_MAC_START_IDX; 246 if (fif->mac_idx == num) 247 return current_port; 248 249 return -ENODEV; 250 } 251 252 DPAA_PMD_ERR("Invalid MAC(mac_idx=%d) type(%d)", 253 fif->mac_idx, fif->mac_type); 254 255 return -EINVAL; 256 } 257 258 static int 259 dpaa_fq_is_in_kernel(uint32_t fqid, 260 struct fman_if *fif) 261 { 262 if (!fif->is_shared_mac) 263 return false; 264 265 if ((fqid == fif->fqid_rx_def || 266 (fqid >= fif->fqid_rx_pcd && 267 fqid < (fif->fqid_rx_pcd + fif->fqid_rx_pcd_count)) || 268 fqid == fif->fqid_rx_err || 269 fqid == fif->fqid_tx_err)) 270 return true; 271 272 return false; 273 } 274 275 static int 276 dpaa_vsp_id_is_in_kernel(uint8_t vsp_id, 277 struct fman_if *fif) 278 { 279 if (!fif->is_shared_mac) 280 return false; 281 282 if (vsp_id == fif->base_profile_id) 283 return true; 284 285 return false; 286 } 287 288 static uint8_t 289 dpaa_enqueue_vsp_id(struct fman_if *fif, 290 const struct ioc_fm_pcd_cc_next_enqueue_params_t *eq_param) 291 { 292 if (eq_param->override_fqid) 293 return eq_param->new_relative_storage_profile_id; 294 295 return fif->base_profile_id; 296 } 297 298 static int 299 dpaa_kg_storage_is_in_kernel(struct fman_if *fif, 300 const struct ioc_fm_pcd_kg_storage_profile_t *kg_storage) 301 { 302 if (!fif->is_shared_mac) 303 return false; 304 305 if (!kg_storage->direct || 306 (kg_storage->direct && 307 kg_storage->profile_select.direct_relative_profile_id == 308 fif->base_profile_id)) 309 return true; 310 311 return false; 312 } 313 314 static void 315 dpaa_fmc_remove_fq_from_allocated(uint32_t *fqids, 316 uint16_t *rxq_idx, uint32_t rm_fqid) 317 { 318 uint32_t i; 319 320 for (i = 0; i < (*rxq_idx); i++) { 321 if (fqids[i] != rm_fqid) 322 continue; 323 DPAA_PMD_WARN("Remove fq(0x%08x) allocated.", 324 rm_fqid); 325 if ((*rxq_idx) > (i + 1)) { 326 memmove(&fqids[i], &fqids[i + 1], 327 ((*rxq_idx) - (i + 1)) * sizeof(uint32_t)); 328 } 329 (*rxq_idx)--; 330 break; 331 } 332 } 333 334 static int 335 dpaa_port_fmc_scheme_parse(struct fman_if *fif, 336 const struct fmc_model_t *fmc, 337 int apply_idx, 338 uint16_t *rxq_idx, int max_nb_rxq, 339 uint32_t *fqids, int8_t *vspids) 340 { 341 int scheme_idx = fmc->apply_order[apply_idx].index; 342 int k, found = 0; 343 uint32_t i, num_rxq, fqid, rxq_idx_start = *rxq_idx; 344 const struct fm_pcd_kg_scheme_params_t *scheme; 345 const struct ioc_fm_pcd_kg_key_extract_and_hash_params_t *params; 346 const struct ioc_fm_pcd_kg_storage_profile_t *kg_storage; 347 uint8_t vsp_id; 348 349 scheme = &fmc->scheme[scheme_idx]; 350 params = &scheme->key_ext_and_hash; 351 num_rxq = params->hash_dist_num_of_fqids; 352 kg_storage = &scheme->storage_profile; 353 354 if (scheme->override_storage_profile && kg_storage->direct) 355 vsp_id = kg_storage->profile_select.direct_relative_profile_id; 356 else 357 vsp_id = fif->base_profile_id; 358 359 if (dpaa_kg_storage_is_in_kernel(fif, kg_storage)) { 360 DPAA_PMD_WARN("Scheme[%d]'s VSP is in kernel", 361 scheme_idx); 362 /* The FQ may be allocated from previous CC or scheme, 363 * find and remove it. 364 */ 365 for (i = 0; i < num_rxq; i++) { 366 fqid = scheme->base_fqid + i; 367 DPAA_PMD_WARN("Removed fqid(0x%08x) of Scheme[%d]", 368 fqid, scheme_idx); 369 dpaa_fmc_remove_fq_from_allocated(fqids, 370 rxq_idx, fqid); 371 if (!dpaa_fq_is_in_kernel(fqid, fif)) { 372 char reason_msg[128]; 373 char result_msg[128]; 374 375 sprintf(reason_msg, 376 "NOT handled in kernel"); 377 sprintf(result_msg, 378 "will DRAIN kernel pool!"); 379 DPAA_PMD_WARN("Traffic to FQ(%08x)(%s) %s", 380 fqid, reason_msg, result_msg); 381 } 382 } 383 384 return 0; 385 } 386 387 if (e_IOC_FM_PCD_DONE != scheme->next_engine) { 388 /* Do nothing.*/ 389 DPAA_PMD_DEBUG("Will parse scheme[%d]'s next engine(%d)", 390 scheme_idx, scheme->next_engine); 391 return 0; 392 } 393 394 for (i = 0; i < num_rxq; i++) { 395 fqid = scheme->base_fqid + i; 396 found = 0; 397 398 if (dpaa_fq_is_in_kernel(fqid, fif)) { 399 DPAA_PMD_WARN("FQ(0x%08x) is handled in kernel.", 400 fqid); 401 /* The FQ may be allocated from previous CC or scheme, 402 * remove it. 403 */ 404 dpaa_fmc_remove_fq_from_allocated(fqids, 405 rxq_idx, fqid); 406 continue; 407 } 408 409 if ((*rxq_idx) >= max_nb_rxq) { 410 DPAA_PMD_WARN("Too many queues(%d) >= MAX number(%d)", 411 (*rxq_idx), max_nb_rxq); 412 413 break; 414 } 415 416 for (k = 0; k < (*rxq_idx); k++) { 417 if (fqids[k] == fqid) { 418 found = 1; 419 break; 420 } 421 } 422 423 if (found) 424 continue; 425 fqids[(*rxq_idx)] = fqid; 426 vspids[(*rxq_idx)] = vsp_id; 427 428 (*rxq_idx)++; 429 } 430 431 return (*rxq_idx) - rxq_idx_start; 432 } 433 434 static int 435 dpaa_port_fmc_ccnode_parse(struct fman_if *fif, 436 const struct fmc_model_t *fmc, 437 int apply_idx, 438 uint16_t *rxq_idx, int max_nb_rxq, 439 uint32_t *fqids, int8_t *vspids) 440 { 441 uint16_t j, k, found = 0; 442 const struct ioc_keys_params_t *keys_params; 443 const struct ioc_fm_pcd_cc_next_engine_params_t *params; 444 uint32_t fqid, cc_idx = fmc->apply_order[apply_idx].index; 445 uint32_t rxq_idx_start = *rxq_idx; 446 uint8_t vsp_id; 447 448 keys_params = &fmc->ccnode[cc_idx].keys_params; 449 450 for (j = 0; j < keys_params->num_of_keys; ++j) { 451 if ((*rxq_idx) >= max_nb_rxq) { 452 DPAA_PMD_WARN("Too many queues(%d) >= MAX number(%d)", 453 (*rxq_idx), max_nb_rxq); 454 455 break; 456 } 457 found = 0; 458 params = &keys_params->key_params[j].cc_next_engine_params; 459 460 /* We read DPDK queue from last classification rule present in 461 * FMC policy file. Hence, this check is required here. 462 * Also, the last classification rule in FMC policy file must 463 * have userspace queue so that it can be used by DPDK 464 * application. 465 */ 466 if (params->next_engine != e_IOC_FM_PCD_DONE) { 467 DPAA_PMD_WARN("CC next engine(%d) not support", 468 params->next_engine); 469 continue; 470 } 471 if (params->params.enqueue_params.action != 472 e_IOC_FM_PCD_ENQ_FRAME) 473 continue; 474 475 fqid = params->params.enqueue_params.new_fqid; 476 vsp_id = dpaa_enqueue_vsp_id(fif, 477 ¶ms->params.enqueue_params); 478 if (dpaa_fq_is_in_kernel(fqid, fif) || 479 dpaa_vsp_id_is_in_kernel(vsp_id, fif)) { 480 DPAA_PMD_DEBUG("FQ(0x%08x)/VSP(%d) is in kernel.", 481 fqid, vsp_id); 482 /* The FQ may be allocated from previous CC or scheme, 483 * remove it. 484 */ 485 dpaa_fmc_remove_fq_from_allocated(fqids, 486 rxq_idx, fqid); 487 continue; 488 } 489 490 for (k = 0; k < (*rxq_idx); k++) { 491 if (fqids[k] == fqid) { 492 found = 1; 493 break; 494 } 495 } 496 if (found) 497 continue; 498 499 fqids[(*rxq_idx)] = fqid; 500 vspids[(*rxq_idx)] = vsp_id; 501 502 (*rxq_idx)++; 503 } 504 505 return (*rxq_idx) - rxq_idx_start; 506 } 507 508 int 509 dpaa_port_fmc_init(struct fman_if *fif, 510 uint32_t *fqids, int8_t *vspids, int max_nb_rxq) 511 { 512 int current_port = -1, ret; 513 uint16_t rxq_idx = 0; 514 const struct fmc_model_t *fmc; 515 uint32_t i; 516 517 if (!g_fmc_model) { 518 size_t bytes_read; 519 FILE *fp = fopen(FMC_FILE, "rb"); 520 521 if (!fp) { 522 DPAA_PMD_ERR("%s not exists", FMC_FILE); 523 return -ENOENT; 524 } 525 526 g_fmc_model = rte_malloc(NULL, sizeof(struct fmc_model_t), 64); 527 if (!g_fmc_model) { 528 DPAA_PMD_ERR("FMC memory alloc failed"); 529 fclose(fp); 530 return -ENOBUFS; 531 } 532 533 bytes_read = fread(g_fmc_model, 534 sizeof(struct fmc_model_t), 1, fp); 535 if (!bytes_read) { 536 DPAA_PMD_ERR("No bytes read"); 537 fclose(fp); 538 rte_free(g_fmc_model); 539 g_fmc_model = NULL; 540 return -EIO; 541 } 542 fclose(fp); 543 } 544 545 fmc = g_fmc_model; 546 547 if (fmc->format_version != FMC_OUTPUT_FORMAT_VER) { 548 DPAA_PMD_ERR("FMC version(0x%08x) != Supported ver(0x%08x)", 549 fmc->format_version, FMC_OUTPUT_FORMAT_VER); 550 return -EINVAL; 551 } 552 553 for (i = 0; i < fmc->apply_order_count; i++) { 554 switch (fmc->apply_order[i].type) { 555 case fmcengine_start: 556 break; 557 case fmcengine_end: 558 break; 559 case fmcport_start: 560 current_port = dpaa_port_fmc_port_parse(fif, 561 fmc, i); 562 break; 563 case fmcport_end: 564 break; 565 case fmcscheme: 566 if (current_port < 0) 567 break; 568 569 ret = dpaa_port_fmc_scheme_parse(fif, fmc, 570 i, &rxq_idx, max_nb_rxq, fqids, vspids); 571 DPAA_PMD_INFO("%s %d RXQ(s) from scheme[%d]", 572 ret >= 0 ? "Alloc" : "Remove", 573 ret >= 0 ? ret : -ret, 574 fmc->apply_order[i].index); 575 576 break; 577 case fmcccnode: 578 if (current_port < 0) 579 break; 580 581 ret = dpaa_port_fmc_ccnode_parse(fif, fmc, 582 i, &rxq_idx, max_nb_rxq, fqids, vspids); 583 DPAA_PMD_INFO("%s %d RXQ(s) from cc[%d]", 584 ret >= 0 ? "Alloc" : "Remove", 585 ret >= 0 ? ret : -ret, 586 fmc->apply_order[i].index); 587 588 break; 589 case fmchtnode: 590 break; 591 case fmcreplicator: 592 break; 593 case fmccctree: 594 break; 595 case fmcpolicer: 596 break; 597 case fmcmanipulation: 598 break; 599 default: 600 break; 601 } 602 } 603 604 return rxq_idx; 605 } 606