1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 #include <stdio.h> 6 7 #include "bnxt.h" 8 #include "bnxt_mpc.h" 9 10 #include "tfc.h" 11 #include "cfa_bld_mpc_field_ids.h" 12 #include "cfa_bld_mpcops.h" 13 #include "tfo.h" 14 #include "tfc_em.h" 15 #include "tfc_cpm.h" 16 #include "tfc_msg.h" 17 #include "tfc_priv.h" 18 #include "cfa_types.h" 19 #include "cfa_mm.h" 20 #include "tfc_action_handle.h" 21 #include "sys_util.h" 22 #include "tfc_util.h" 23 24 /* 25 * The read/write granularity is 32B 26 */ 27 #define TFC_ACT_RW_GRANULARITY 32 28 29 #define TFC_ACT_CACHE_OPT_EN 0 30 31 /* Max additional data size in bytes */ 32 #define TFC_ACT_DISCARD_DATA_SIZE 128 33 34 int tfc_act_alloc(struct tfc *tfcp, 35 uint8_t tsid, 36 struct tfc_cmm_info *cmm_info, 37 uint16_t num_contig_rec) 38 { 39 int rc = 0; 40 struct tfc_cpm *cpm_lkup = NULL; 41 struct tfc_cpm *cpm_act = NULL; 42 uint16_t pool_id; 43 struct tfc_ts_mem_cfg mem_cfg; 44 bool is_bs_owner; 45 struct tfc_cmm *cmm; 46 uint32_t entry_offset; 47 struct cfa_mm_alloc_parms aparms; 48 bool is_shared; 49 struct tfc_ts_pool_info pi; 50 bool valid; 51 uint16_t max_pools; 52 53 rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, &max_pools); 54 if (unlikely(rc)) { 55 PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc)); 56 return -EINVAL; 57 } 58 59 if (unlikely(!valid)) { 60 PMD_DRV_LOG_LINE(ERR, "tsid(%d) not allocated", tsid); 61 return -EINVAL; 62 } 63 64 if (unlikely(max_pools == 0)) { 65 PMD_DRV_LOG_LINE(ERR, "tsid(%d) Max pools must be greater than 0 %d", 66 tsid, max_pools); 67 return -EINVAL; 68 } 69 70 tfo_ts_get_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi); 71 72 /* Get CPM instances */ 73 rc = tfo_ts_get_cpm_inst(tfcp->tfo, tsid, cmm_info->dir, &cpm_lkup, &cpm_act); 74 if (unlikely(rc)) { 75 PMD_DRV_LOG_LINE(ERR, "failed to get CPM instances: %s", 76 strerror(-rc)); 77 return -EINVAL; 78 } 79 80 rc = tfo_ts_get_mem_cfg(tfcp->tfo, tsid, 81 cmm_info->dir, 82 CFA_REGION_TYPE_ACT, 83 &is_bs_owner, 84 &mem_cfg); 85 if (unlikely(rc)) { 86 PMD_DRV_LOG_LINE(ERR, "tfo_ts_get_mem_cfg() failed: %s", strerror(-rc)); 87 return -EINVAL; 88 } 89 90 /* if no pool available locally or all pools full */ 91 rc = tfc_cpm_get_avail_pool(cpm_act, &pool_id); 92 93 if (rc) { 94 /* Allocate a pool */ 95 struct cfa_mm_query_parms qparms; 96 struct cfa_mm_open_parms oparms; 97 uint16_t fid; 98 99 /* There is only 1 pool for a non-shared table scope 100 * and it is full. 101 */ 102 if (unlikely(!is_shared)) { 103 PMD_DRV_LOG_LINE(ERR, "no records remain"); 104 return -ENOMEM; 105 } 106 rc = tfc_get_fid(tfcp, &fid); 107 if (unlikely(rc)) 108 return rc; 109 110 rc = tfc_tbl_scope_pool_alloc(tfcp, 111 fid, 112 tsid, 113 CFA_REGION_TYPE_ACT, 114 cmm_info->dir, 115 NULL, 116 &pool_id); 117 118 if (unlikely(rc)) { 119 PMD_DRV_LOG_LINE(ERR, "table scope pool alloc failed: %s", 120 strerror(-rc)); 121 return -EINVAL; 122 } 123 124 /* Create pool CMM instance */ 125 qparms.max_records = mem_cfg.rec_cnt; 126 qparms.max_contig_records = pi.act_max_contig_rec; 127 rc = cfa_mm_query(&qparms); 128 if (unlikely(rc)) { 129 PMD_DRV_LOG_LINE(ERR, "cfa_mm_query() failed: %s", strerror(-rc)); 130 return rc; 131 } 132 133 cmm = rte_zmalloc("tf", qparms.db_size, 0); 134 oparms.db_mem_size = qparms.db_size; 135 oparms.max_contig_records = qparms.max_contig_records; 136 oparms.max_records = qparms.max_records / max_pools; 137 rc = cfa_mm_open(cmm, &oparms); 138 if (unlikely(rc)) { 139 PMD_DRV_LOG_LINE(ERR, "cfa_mm_open() failed: %d", rc); 140 return -EINVAL; 141 } 142 143 /* Store CMM instance in the CPM */ 144 rc = tfc_cpm_set_cmm_inst(cpm_act, pool_id, cmm); 145 if (unlikely(rc)) { 146 PMD_DRV_LOG_LINE(ERR, "tfc_cpm_set_cmm_inst() failed: %d", rc); 147 return -EINVAL; 148 } 149 /* store updated pool info */ 150 tfo_ts_set_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi); 151 152 } else { 153 /* Get the pool instance and allocate an act rec index from the pool */ 154 rc = tfc_cpm_get_cmm_inst(cpm_act, pool_id, &cmm); 155 if (unlikely(rc)) { 156 PMD_DRV_LOG_LINE(ERR, "tfc_cpm_get_cmm_inst() failed: %d", rc); 157 return -EINVAL; 158 } 159 } 160 161 aparms.num_contig_records = 1 << next_pow2(num_contig_rec); 162 rc = cfa_mm_alloc(cmm, &aparms); 163 if (unlikely(rc)) { 164 PMD_DRV_LOG_LINE(ERR, "cfa_mm_alloc() failed: %d", rc); 165 return -EINVAL; 166 } 167 168 /* Update CPM info so it will determine best pool to use next alloc */ 169 rc = tfc_cpm_set_usage(pi.act_cpm, pool_id, aparms.used_count, aparms.all_used); 170 if (unlikely(rc)) 171 PMD_DRV_LOG_LINE(ERR, "EM insert tfc_cpm_set_usage() failed: %d", rc); 172 173 CREATE_OFFSET(&entry_offset, pi.act_pool_sz_exp, pool_id, aparms.record_offset); 174 175 /* Create Action handle */ 176 cmm_info->act_handle = tfc_create_action_handle(tsid, 177 num_contig_rec, 178 entry_offset); 179 return rc; 180 } 181 182 int tfc_act_set_response(struct cfa_bld_mpcinfo *mpc_info, 183 struct bnxt_mpc_mbuf *mpc_msg_out, 184 uint8_t *rx_msg) 185 { 186 int rc; 187 int i; 188 struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_WRITE_CMP_MAX_FLD]; 189 190 /* Process response */ 191 for (i = 0; i < CFA_BLD_MPC_WRITE_CMP_MAX_FLD; i++) 192 fields_cmp[i].field_id = INVALID_U16; 193 194 fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].field_id = 195 CFA_BLD_MPC_WRITE_CMP_STATUS_FLD; 196 197 rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_write(rx_msg, 198 mpc_msg_out->msg_size, 199 fields_cmp); 200 201 if (unlikely(rc)) { 202 PMD_DRV_LOG_LINE(ERR, "write parse failed: %d", rc); 203 rc = -EINVAL; 204 } 205 206 if (unlikely(fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK)) { 207 PMD_DRV_LOG_LINE(ERR, "failed with status code:%d", 208 (uint32_t)fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val); 209 rc = ((int)fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val) * -1; 210 } 211 212 return rc; 213 } 214 215 int tfc_act_set(struct tfc *tfcp, 216 struct tfc_mpc_batch_info_t *batch_info, 217 const struct tfc_cmm_info *cmm_info, 218 const uint8_t *data, 219 uint16_t data_sz_words) 220 { 221 int rc = 0; 222 uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES]; 223 uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES]; 224 uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT; 225 uint32_t i; 226 uint32_t buff_len; 227 struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_WRITE_CMD_MAX_FLD]; 228 uint32_t entry_offset; 229 struct bnxt_mpc_mbuf mpc_msg_in; 230 struct bnxt_mpc_mbuf mpc_msg_out; 231 struct cfa_bld_mpcinfo *mpc_info; 232 uint32_t record_size; 233 uint8_t tsid; 234 bool is_shared; 235 bool valid; 236 237 tfo_mpcinfo_get(tfcp->tfo, &mpc_info); 238 239 /* Check that MPC APIs are bound */ 240 if (unlikely(mpc_info->mpcops == NULL)) { 241 PMD_DRV_LOG_LINE(ERR, "MPC not initialized"); 242 return -EINVAL; 243 } 244 245 tfc_get_fields_from_action_handle(&cmm_info->act_handle, 246 &tsid, 247 &record_size, 248 &entry_offset); 249 250 rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL); 251 if (unlikely(rc)) { 252 PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc)); 253 return -EINVAL; 254 } 255 if (unlikely(!valid)) { 256 PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid); 257 return -EINVAL; 258 } 259 260 /* Create MPC EM insert command using builder */ 261 for (i = 0; i < CFA_BLD_MPC_WRITE_CMD_MAX_FLD; i++) 262 fields_cmd[i].field_id = INVALID_U16; 263 264 fields_cmd[CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD].field_id = 265 CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD; 266 fields_cmd[CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD].val = 0xAA; 267 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD].field_id = 268 CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD; 269 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD].val = CFA_BLD_MPC_HW_TABLE_TYPE_ACTION; 270 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD].field_id = 271 CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD; 272 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD].val = tsid; 273 fields_cmd[CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD].field_id = 274 CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD; 275 fields_cmd[CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD].val = data_sz_words; 276 #if TFC_ACT_CACHE_OPT_EN 277 fields_cmd[CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD].field_id = 278 CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD; 279 fields_cmd[CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD].val = 0x01; 280 #endif 281 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD].field_id = 282 CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD; 283 fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD].val = entry_offset; 284 285 buff_len = TFC_MPC_MAX_TX_BYTES; 286 287 rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_write(tx_msg, 288 &buff_len, 289 data, 290 fields_cmd); 291 292 if (unlikely(rc)) { 293 PMD_DRV_LOG_LINE(ERR, "write build failed: %d", rc); 294 goto cleanup; 295 } 296 297 /* Send MPC */ 298 mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ? 299 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA : 300 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA); 301 mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 302 mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES; 303 mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT; 304 mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 305 mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES; 306 307 rc = tfc_mpc_send(tfcp->bp, 308 &mpc_msg_in, 309 &mpc_msg_out, 310 &msg_count, 311 TFC_MPC_TABLE_WRITE, 312 batch_info); 313 314 if (unlikely(rc)) { 315 PMD_DRV_LOG_LINE(ERR, "write MPC send failed: %d", rc); 316 goto cleanup; 317 } 318 319 if (batch_info && !batch_info->enabled) 320 rc = tfc_act_set_response(mpc_info, &mpc_msg_out, rx_msg); 321 322 return rc; 323 324 cleanup: 325 326 return rc; 327 } 328 329 int tfc_act_get_only_response(struct cfa_bld_mpcinfo *mpc_info, 330 struct bnxt_mpc_mbuf *mpc_msg_out, 331 uint8_t *rx_msg, 332 uint16_t *data_sz_words) 333 { 334 int i; 335 int rc; 336 uint8_t discard_data[TFC_ACT_DISCARD_DATA_SIZE]; 337 struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_READ_CMP_MAX_FLD] = { {0} }; 338 339 /* Process response */ 340 for (i = 0; i < CFA_BLD_MPC_READ_CMP_MAX_FLD; i++) 341 fields_cmp[i].field_id = INVALID_U16; 342 343 fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].field_id = 344 CFA_BLD_MPC_READ_CMP_STATUS_FLD; 345 346 rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_read(rx_msg, 347 mpc_msg_out->msg_size, 348 discard_data, 349 *data_sz_words * TFC_MPC_BYTES_PER_WORD, 350 fields_cmp); 351 352 if (unlikely(rc)) { 353 PMD_DRV_LOG_LINE(ERR, "Action read parse failed: %d", rc); 354 return -1; 355 } 356 357 if (fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK) { 358 PMD_DRV_LOG_LINE(ERR, "Action read failed with status code:%d", 359 (uint32_t)fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val); 360 rc = ((int)fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val) * -1; 361 return -1; 362 } 363 364 return 0; 365 } 366 367 static int tfc_act_get_only(struct tfc *tfcp, 368 struct tfc_mpc_batch_info_t *batch_info, 369 const struct tfc_cmm_info *cmm_info, 370 uint64_t *host_address, 371 uint16_t *data_sz_words) 372 { 373 int rc = 0; 374 uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES] = { 0 }; 375 uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES] = { 0 }; 376 uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT; 377 int i; 378 uint32_t buff_len; 379 struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_READ_CMD_MAX_FLD] = { {0} }; 380 uint32_t entry_offset; 381 struct bnxt_mpc_mbuf mpc_msg_in; 382 struct bnxt_mpc_mbuf mpc_msg_out; 383 uint32_t record_size; 384 uint8_t tsid; 385 bool is_shared; 386 struct cfa_bld_mpcinfo *mpc_info; 387 bool valid; 388 389 tfo_mpcinfo_get(tfcp->tfo, &mpc_info); 390 391 tfc_get_fields_from_action_handle(&cmm_info->act_handle, 392 &tsid, 393 &record_size, 394 &entry_offset); 395 396 rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL); 397 if (unlikely(rc)) { 398 PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc)); 399 return -EINVAL; 400 } 401 if (unlikely(!valid)) { 402 PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid); 403 return -EINVAL; 404 } 405 406 /* Check that data pointer is word aligned */ 407 if (unlikely(*host_address & 0x3ULL)) { 408 PMD_DRV_LOG_LINE(ERR, "data pointer not word aligned"); 409 return -EINVAL; 410 } 411 412 /* Check that MPC APIs are bound */ 413 if (unlikely(mpc_info->mpcops == NULL)) { 414 PMD_DRV_LOG_LINE(ERR, "MPC not initialized"); 415 return -EINVAL; 416 } 417 418 /* Create MPC EM insert command using builder */ 419 for (i = 0; i < CFA_BLD_MPC_READ_CMD_MAX_FLD; i++) 420 fields_cmd[i].field_id = INVALID_U16; 421 422 fields_cmd[CFA_BLD_MPC_READ_CMD_OPAQUE_FLD].field_id = 423 CFA_BLD_MPC_READ_CMD_OPAQUE_FLD; 424 fields_cmd[CFA_BLD_MPC_READ_CMD_OPAQUE_FLD].val = 0xAA; 425 426 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD].field_id = 427 CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD; 428 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD].val = 429 CFA_BLD_MPC_HW_TABLE_TYPE_ACTION; 430 431 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD].field_id = 432 CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD; 433 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD].val = tsid; 434 435 fields_cmd[CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD].field_id = 436 CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD; 437 fields_cmd[CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD].val = *data_sz_words; 438 439 #if TFC_ACT_CACHE_OPT_EN 440 fields_cmd[CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD].field_id = 441 CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD; 442 fields_cmd[CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD].val = 0x0; 443 #endif 444 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD].field_id = 445 CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD; 446 fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD].val = entry_offset; 447 448 fields_cmd[CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD].field_id = 449 CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD; 450 fields_cmd[CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD].val = *host_address; 451 452 buff_len = TFC_MPC_MAX_TX_BYTES; 453 454 rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_read(tx_msg, 455 &buff_len, 456 fields_cmd); 457 458 if (unlikely(rc)) { 459 PMD_DRV_LOG_LINE(ERR, "read build failed: %d", rc); 460 goto cleanup; 461 } 462 463 /* Send MPC */ 464 mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ? 465 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA : 466 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA); 467 mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 468 mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES; 469 mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT; 470 mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 471 mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES; 472 473 rc = tfc_mpc_send(tfcp->bp, 474 &mpc_msg_in, 475 &mpc_msg_out, 476 &msg_count, 477 TFC_MPC_TABLE_READ, 478 batch_info); 479 480 if (unlikely(rc)) { 481 PMD_DRV_LOG_LINE(ERR, "read MPC send failed: %d", rc); 482 goto cleanup; 483 } 484 485 if ((batch_info && !batch_info->enabled) || !batch_info) { 486 rc = tfc_act_get_only_response(mpc_info, 487 &mpc_msg_out, 488 rx_msg, 489 data_sz_words); 490 if (rc) { 491 PMD_DRV_LOG_LINE(ERR, "Action response failed: %d", rc); 492 goto cleanup; 493 } 494 } else { 495 batch_info->comp_info[batch_info->count - 1].read_words = *data_sz_words; 496 } 497 498 return 0; 499 500 cleanup: 501 502 return rc; 503 } 504 505 int tfc_act_get_clear_response(struct cfa_bld_mpcinfo *mpc_info, 506 struct bnxt_mpc_mbuf *mpc_msg_out, 507 uint8_t *rx_msg, 508 uint16_t *data_sz_words) 509 { 510 int i; 511 int rc; 512 uint8_t discard_data[TFC_ACT_DISCARD_DATA_SIZE]; 513 struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_MAX_FLD] = { {0} }; 514 515 /* Process response */ 516 for (i = 0; i < CFA_BLD_MPC_READ_CLR_CMP_MAX_FLD; i++) 517 fields_cmp[i].field_id = INVALID_U16; 518 519 fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].field_id = 520 CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD; 521 522 rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_read_clr(rx_msg, 523 mpc_msg_out->msg_size, 524 discard_data, 525 *data_sz_words * 526 TFC_MPC_BYTES_PER_WORD, 527 fields_cmp); 528 529 if (unlikely(rc)) { 530 PMD_DRV_LOG_LINE(ERR, "Action read clear parse failed: %d", rc); 531 return -1; 532 } 533 534 if (fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK) { 535 PMD_DRV_LOG_LINE(ERR, "Action read clear failed with status code:%d", 536 (uint32_t)fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val); 537 rc = ((int)fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val) * -1; 538 return rc; 539 } 540 541 return 0; 542 } 543 544 static int tfc_act_get_clear(struct tfc *tfcp, 545 struct tfc_mpc_batch_info_t *batch_info, 546 const struct tfc_cmm_info *cmm_info, 547 uint64_t *host_address, 548 uint16_t *data_sz_words, 549 uint8_t clr_offset, 550 uint8_t clr_size) 551 { 552 int rc = 0; 553 uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES] = { 0 }; 554 uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES] = { 0 }; 555 uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT; 556 int i; 557 uint32_t buff_len; 558 struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_MAX_FLD] = { {0} }; 559 uint32_t entry_offset; 560 struct bnxt_mpc_mbuf mpc_msg_in; 561 struct bnxt_mpc_mbuf mpc_msg_out; 562 uint32_t record_size; 563 uint8_t tsid; 564 bool is_shared; 565 struct cfa_bld_mpcinfo *mpc_info; 566 bool valid; 567 uint16_t mask = 0; 568 569 tfo_mpcinfo_get(tfcp->tfo, &mpc_info); 570 571 tfc_get_fields_from_action_handle(&cmm_info->act_handle, 572 &tsid, 573 &record_size, 574 &entry_offset); 575 576 rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL); 577 if (unlikely(rc)) { 578 PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", 579 strerror(-rc)); 580 return -EINVAL; 581 } 582 if (unlikely(!valid)) { 583 PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid); 584 return -EINVAL; 585 } 586 587 /* Check that data pointer is word aligned */ 588 if (unlikely(*host_address & 0x3ULL)) { 589 PMD_DRV_LOG_LINE(ERR, "data pointer not word aligned"); 590 return -EINVAL; 591 } 592 593 /* Check that MPC APIs are bound */ 594 if (unlikely(mpc_info->mpcops == NULL)) { 595 PMD_DRV_LOG_LINE(ERR, "MPC not initialized"); 596 return -EINVAL; 597 } 598 599 /* Create MPC EM insert command using builder */ 600 for (i = 0; i < CFA_BLD_MPC_READ_CLR_CMD_MAX_FLD; i++) 601 fields_cmd[i].field_id = INVALID_U16; 602 603 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD].field_id = 604 CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD; 605 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD].val = 0xAA; 606 607 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD].field_id = 608 CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD; 609 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD].val = 610 CFA_BLD_MPC_HW_TABLE_TYPE_ACTION; 611 612 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD].field_id = 613 CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD; 614 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD].val = tsid; 615 616 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD].field_id = 617 CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD; 618 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD].val = *data_sz_words; 619 620 #if TFC_ACT_CACHE_OPT_EN 621 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD].field_id = 622 CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD; 623 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD].val = 0x0; 624 #endif 625 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD].field_id = 626 CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD; 627 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD].val = entry_offset; 628 629 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD].field_id = 630 CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD; 631 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD].val = *host_address; 632 633 for (i = clr_offset; i < clr_size; i++) 634 mask |= (1 << i); 635 636 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD].field_id = 637 CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD; 638 fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD].val = mask; 639 640 buff_len = TFC_MPC_MAX_TX_BYTES; 641 642 rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_read_clr(tx_msg, 643 &buff_len, 644 fields_cmd); 645 646 if (unlikely(rc)) { 647 PMD_DRV_LOG_LINE(ERR, "read clear build failed: %d", rc); 648 goto cleanup; 649 } 650 651 /* Send MPC */ 652 mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ? 653 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA : 654 HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA); 655 mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 656 mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES; 657 mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT; 658 mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES]; 659 mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES; 660 661 rc = tfc_mpc_send(tfcp->bp, 662 &mpc_msg_in, 663 &mpc_msg_out, 664 &msg_count, 665 TFC_MPC_TABLE_READ_CLEAR, 666 batch_info); 667 668 if (unlikely(rc)) { 669 PMD_DRV_LOG_LINE(ERR, "read clear MPC send failed: %d", rc); 670 goto cleanup; 671 } 672 673 if ((batch_info && !batch_info->enabled) || !batch_info) { 674 rc = tfc_act_get_clear_response(mpc_info, 675 &mpc_msg_out, 676 rx_msg, 677 data_sz_words); 678 if (rc) { 679 PMD_DRV_LOG_LINE(ERR, "Action response failed: %d", rc); 680 goto cleanup; 681 } 682 } else { 683 batch_info->comp_info[batch_info->count - 1].read_words = *data_sz_words; 684 } 685 686 return 0; 687 688 cleanup: 689 690 return rc; 691 } 692 693 int tfc_act_get(struct tfc *tfcp, 694 struct tfc_mpc_batch_info_t *batch_info, 695 const struct tfc_cmm_info *cmm_info, 696 struct tfc_cmm_clr *clr, 697 uint64_t *host_address, 698 uint16_t *data_sz_words) 699 { 700 /* It's not an error to pass clr as a Null pointer, just means that read 701 * and clear is not being requested. Also allow the user to manage 702 * clear via the clr flag. 703 */ 704 if (clr && clr->clr) { 705 /* Clear offset and size have to be two bytes aligned */ 706 if (clr->offset_in_byte % 2 || clr->sz_in_byte % 2) { 707 PMD_DRV_LOG_LINE(ERR, 708 "clr offset(%d) or size(%d) is not two bytes aligned", 709 clr->offset_in_byte, clr->sz_in_byte); 710 return -EINVAL; 711 } 712 713 return tfc_act_get_clear(tfcp, 714 batch_info, 715 cmm_info, 716 host_address, 717 data_sz_words, 718 clr->offset_in_byte / 2, 719 clr->sz_in_byte / 2); 720 } else { 721 return tfc_act_get_only(tfcp, 722 batch_info, 723 cmm_info, 724 host_address, 725 data_sz_words); 726 } 727 } 728 729 int tfc_act_free(struct tfc *tfcp, 730 const struct tfc_cmm_info *cmm_info) 731 { 732 int rc = 0; 733 struct tfc_cpm *cpm_lkup = NULL; 734 struct tfc_cpm *cpm_act = NULL; 735 struct tfc_cmm *cmm; 736 uint32_t pool_id; 737 struct tfc_ts_pool_info pi; 738 uint32_t record_size; 739 uint32_t record_offset; 740 struct cfa_mm_free_parms fparms; 741 uint8_t tsid; 742 bool is_shared; 743 bool valid; 744 bool is_bs_owner; 745 struct tfc_ts_mem_cfg mem_cfg; 746 747 /* Get fields from MPC Action handle */ 748 tfc_get_fields_from_action_handle(&cmm_info->act_handle, 749 &tsid, 750 &record_size, 751 &record_offset); 752 753 rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL); 754 if (unlikely(rc)) { 755 PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc)); 756 return -EINVAL; 757 } 758 if (unlikely(!valid)) { 759 PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid); 760 return -EINVAL; 761 } 762 tfo_ts_get_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi); 763 764 pool_id = TFC_ACTION_GET_POOL_ID(record_offset, pi.act_pool_sz_exp); 765 766 rc = tfo_ts_get_mem_cfg(tfcp->tfo, tsid, 767 cmm_info->dir, 768 CFA_REGION_TYPE_ACT, 769 &is_bs_owner, 770 &mem_cfg); /* Gets rec_cnt */ 771 if (unlikely(rc)) { 772 PMD_DRV_LOG_LINE(ERR, "tfo_ts_get_mem_cfg() failed: %s", 773 strerror(-rc)); 774 return -EINVAL; 775 } 776 777 /* Get CPM instance for this table scope */ 778 rc = tfo_ts_get_cpm_inst(tfcp->tfo, tsid, cmm_info->dir, &cpm_lkup, &cpm_act); 779 if (unlikely(rc)) { 780 PMD_DRV_LOG_LINE(ERR, "failed to get CPM instance: %d", rc); 781 return -EINVAL; 782 } 783 784 rc = tfc_cpm_get_cmm_inst(cpm_act, pool_id, &cmm); 785 if (unlikely(rc)) { 786 PMD_DRV_LOG_LINE(ERR, "failed to get CMM instance: %d", rc); 787 return -EINVAL; 788 } 789 790 fparms.record_offset = record_offset; 791 fparms.num_contig_records = 1 << next_pow2(record_size); 792 rc = cfa_mm_free(cmm, &fparms); 793 if (unlikely(rc)) { 794 PMD_DRV_LOG_LINE(ERR, "failed to free record: %d", rc); 795 return -EINVAL; 796 } 797 798 rc = tfc_cpm_set_usage(cpm_act, pool_id, 0, false); 799 if (unlikely(rc)) 800 PMD_DRV_LOG_LINE(ERR, "failed to set usage: %d", rc); 801 802 return rc; 803 } 804