1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_log.h> 7 #include <rte_malloc.h> 8 #include "tf_core.h" 9 #include "tfp.h" 10 #include "ulp_mapper.h" 11 #include "ulp_flow_db.h" 12 13 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 14 #include "ulp_template_debug_proto.h" 15 #include "ulp_tf_debug.h" 16 #endif 17 18 /* Retrieve the generic table initialization parameters for the tbl_idx */ 19 static struct bnxt_ulp_generic_tbl_params* 20 ulp_mapper_gen_tbl_params_get(uint32_t tbl_idx) 21 { 22 if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) 23 return NULL; 24 25 return &ulp_generic_tbl_params[tbl_idx]; 26 } 27 28 /* 29 * Initialize the generic table list 30 * 31 * mapper_data [in] Pointer to the mapper data and the generic table is 32 * part of it 33 * 34 * returns 0 on success 35 */ 36 int32_t 37 ulp_mapper_generic_tbl_list_init(struct bnxt_ulp_mapper_data *mapper_data) 38 { 39 struct bnxt_ulp_generic_tbl_params *tbl; 40 struct ulp_mapper_gen_tbl_list *entry; 41 struct ulp_hash_create_params cparams; 42 uint32_t idx, size; 43 44 /* Allocate the generic tables. */ 45 for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) { 46 tbl = ulp_mapper_gen_tbl_params_get(idx); 47 if (!tbl) { 48 BNXT_TF_DBG(ERR, "Failed to get gen table parms %d\n", 49 idx); 50 return -EINVAL; 51 } 52 entry = &mapper_data->gen_tbl_list[idx]; 53 if (tbl->result_num_entries != 0) { 54 /* assign the name */ 55 entry->gen_tbl_name = tbl->name; 56 /* add 4 bytes for reference count */ 57 entry->mem_data_size = (tbl->result_num_entries + 1) * 58 (tbl->result_num_bytes + sizeof(uint32_t)); 59 60 /* allocate the big chunk of memory */ 61 entry->mem_data = rte_zmalloc("ulp mapper gen tbl", 62 entry->mem_data_size, 0); 63 if (!entry->mem_data) { 64 BNXT_TF_DBG(ERR, 65 "%s:Failed to alloc gen table %d\n", 66 tbl->name, idx); 67 return -ENOMEM; 68 } 69 /* Populate the generic table container */ 70 entry->container.num_elem = tbl->result_num_entries; 71 entry->container.byte_data_size = tbl->result_num_bytes; 72 entry->container.ref_count = 73 (uint32_t *)entry->mem_data; 74 size = sizeof(uint32_t) * (tbl->result_num_entries + 1); 75 entry->container.byte_data = &entry->mem_data[size]; 76 entry->container.byte_order = tbl->result_byte_order; 77 } else { 78 BNXT_TF_DBG(ERR, "%s:Invalid gen table num of ent %d\n", 79 tbl->name, idx); 80 return -EINVAL; 81 } 82 if (tbl->hash_tbl_entries) { 83 cparams.key_size = tbl->key_num_bytes; 84 cparams.num_buckets = tbl->num_buckets; 85 cparams.num_hash_tbl_entries = tbl->hash_tbl_entries; 86 cparams.num_key_entries = tbl->result_num_entries; 87 if (ulp_gen_hash_tbl_list_init(&cparams, 88 &entry->hash_tbl)) { 89 BNXT_TF_DBG(ERR, 90 "%s: Failed to alloc hash tbl %d\n", 91 tbl->name, idx); 92 return -ENOMEM; 93 } 94 } 95 } 96 /* success */ 97 return 0; 98 } 99 100 /* 101 * Free the generic table list 102 * 103 * mapper_data [in] Pointer to the mapper data and the generic table is 104 * part of it 105 * 106 * returns 0 on success 107 */ 108 int32_t 109 ulp_mapper_generic_tbl_list_deinit(struct bnxt_ulp_mapper_data *mapper_data) 110 { 111 struct ulp_mapper_gen_tbl_list *tbl_list; 112 uint32_t idx; 113 114 /* iterate the generic table. */ 115 for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) { 116 tbl_list = &mapper_data->gen_tbl_list[idx]; 117 if (tbl_list->mem_data) { 118 rte_free(tbl_list->mem_data); 119 tbl_list->mem_data = NULL; 120 } 121 if (tbl_list->hash_tbl) { 122 ulp_gen_hash_tbl_list_deinit(tbl_list->hash_tbl); 123 tbl_list->hash_tbl = NULL; 124 } 125 } 126 /* success */ 127 return 0; 128 } 129 130 /* 131 * Get the generic table list entry 132 * 133 * tbl_list [in] - Ptr to generic table 134 * key [in] - Key index to the table 135 * entry [out] - output will include the entry if found 136 * 137 * returns 0 on success. 138 */ 139 int32_t 140 ulp_mapper_gen_tbl_entry_get(struct ulp_mapper_gen_tbl_list *tbl_list, 141 uint32_t key, 142 struct ulp_mapper_gen_tbl_entry *entry) 143 { 144 /* populate the output and return the values */ 145 if (key > tbl_list->container.num_elem) { 146 BNXT_TF_DBG(ERR, "%s: invalid key %x:%x\n", 147 tbl_list->gen_tbl_name, key, 148 tbl_list->container.num_elem); 149 return -EINVAL; 150 } 151 entry->ref_count = &tbl_list->container.ref_count[key]; 152 entry->byte_data_size = tbl_list->container.byte_data_size; 153 entry->byte_data = &tbl_list->container.byte_data[key * 154 entry->byte_data_size]; 155 entry->byte_order = tbl_list->container.byte_order; 156 return 0; 157 } 158 159 /* 160 * utility function to calculate the table idx 161 * 162 * res_sub_type [in] - Resource sub type 163 * dir [in] - Direction 164 * 165 * returns None 166 */ 167 int32_t 168 ulp_mapper_gen_tbl_idx_calculate(uint32_t res_sub_type, uint32_t dir) 169 { 170 int32_t tbl_idx; 171 172 /* Validate for direction */ 173 if (dir >= TF_DIR_MAX) { 174 BNXT_TF_DBG(ERR, "invalid argument %x\n", dir); 175 return -EINVAL; 176 } 177 tbl_idx = (res_sub_type << 1) | (dir & 0x1); 178 if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) { 179 BNXT_TF_DBG(ERR, "invalid table index %x\n", tbl_idx); 180 return -EINVAL; 181 } 182 return tbl_idx; 183 } 184 185 /* 186 * Set the data in the generic table entry, Data is in Big endian format 187 * 188 * entry [in] - generic table entry 189 * len [in] - The length of the data in bits to be set 190 * data [in] - pointer to the data to be used for setting the value. 191 * data_size [in] - length of the data pointer in bytes. 192 * 193 * returns 0 on success 194 */ 195 int32_t 196 ulp_mapper_gen_tbl_entry_data_set(struct ulp_mapper_gen_tbl_entry *entry, 197 uint32_t len, uint8_t *data, 198 uint32_t data_size) 199 { 200 /* validate the null arguments */ 201 if (!entry || !data) { 202 BNXT_TF_DBG(ERR, "invalid argument\n"); 203 return -EINVAL; 204 } 205 206 /* check the size of the buffer for validation */ 207 if (len > ULP_BYTE_2_BITS(entry->byte_data_size) || 208 data_size < ULP_BITS_2_BYTE(len)) { 209 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x\n", 210 len, entry->byte_data_size); 211 return -EINVAL; 212 } 213 memcpy(entry->byte_data, data, ULP_BITS_2_BYTE(len)); 214 return 0; 215 } 216 217 /* 218 * Get the data in the generic table entry, Data is in Big endian format 219 * 220 * entry [in] - generic table entry 221 * offset [in] - The offset in bits where the data has to get 222 * len [in] - The length of the data in bits to be get 223 * data [out] - pointer to the data to be used for setting the value. 224 * data_size [in] - The size of data in bytes 225 * 226 * returns 0 on success 227 */ 228 int32_t 229 ulp_mapper_gen_tbl_entry_data_get(struct ulp_mapper_gen_tbl_entry *entry, 230 uint32_t offset, uint32_t len, uint8_t *data, 231 uint32_t data_size) 232 { 233 /* validate the null arguments */ 234 if (!entry || !data) { 235 BNXT_TF_DBG(ERR, "invalid argument\n"); 236 return -EINVAL; 237 } 238 239 /* check the size of the buffer for validation */ 240 if ((offset + len) > ULP_BYTE_2_BITS(entry->byte_data_size) || 241 len > ULP_BYTE_2_BITS(data_size)) { 242 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n", 243 offset, len, entry->byte_data_size); 244 return -EINVAL; 245 } 246 if (entry->byte_order == BNXT_ULP_BYTE_ORDER_LE) 247 ulp_bs_pull_lsb(entry->byte_data, data, data_size, offset, len); 248 else 249 ulp_bs_pull_msb(entry->byte_data, data, offset, len); 250 251 return 0; 252 } 253 254 /* Free the generic table list entry 255 * 256 * ulp_ctx [in] - Pointer to the ulp context 257 * tbl_idx [in] - Index of the generic table 258 * ckey [in] - Key for the entry in the table 259 * 260 * returns 0 on success 261 */ 262 int32_t 263 ulp_mapper_gen_tbl_entry_free(struct bnxt_ulp_context *ulp_ctx, 264 uint32_t tbl_idx, uint32_t ckey) 265 { 266 struct ulp_flow_db_res_params res; 267 268 res.direction = tbl_idx & 0x1; 269 res.resource_sub_type = tbl_idx >> 1; 270 res.resource_hndl = ckey; 271 272 return ulp_mapper_gen_tbl_res_free(ulp_ctx, &res); 273 } 274 275 /* Free the generic table list resource 276 * 277 * ulp_ctx [in] - Pointer to the ulp context 278 * res [in] - Pointer to flow db resource entry 279 * 280 * returns 0 on success 281 */ 282 int32_t 283 ulp_mapper_gen_tbl_res_free(struct bnxt_ulp_context *ulp_ctx, 284 struct ulp_flow_db_res_params *res) 285 { 286 struct bnxt_ulp_mapper_data *mapper_data; 287 struct ulp_mapper_gen_tbl_list *gen_tbl_list; 288 struct ulp_mapper_gen_tbl_entry entry; 289 struct ulp_gen_hash_entry_params hash_entry; 290 int32_t tbl_idx; 291 uint32_t fid = 0; 292 uint32_t key_idx; 293 294 /* Extract the resource sub type and direction */ 295 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(res->resource_sub_type, 296 res->direction); 297 if (tbl_idx < 0) { 298 BNXT_TF_DBG(ERR, "invalid argument %x:%x\n", 299 res->resource_sub_type, res->direction); 300 return -EINVAL; 301 } 302 303 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 304 if (!mapper_data) { 305 BNXT_TF_DBG(ERR, "invalid ulp context %x\n", tbl_idx); 306 return -EINVAL; 307 } 308 /* get the generic table */ 309 gen_tbl_list = &mapper_data->gen_tbl_list[tbl_idx]; 310 311 /* Get the generic table entry*/ 312 if (gen_tbl_list->hash_tbl) { 313 /* use the hash index to get the value */ 314 hash_entry.hash_index = (uint32_t)res->resource_hndl; 315 if (ulp_gen_hash_tbl_list_index_search(gen_tbl_list->hash_tbl, 316 &hash_entry)) { 317 BNXT_TF_DBG(ERR, "Unable to find has entry %x:%x\n", 318 tbl_idx, hash_entry.hash_index); 319 return -EINVAL; 320 } 321 key_idx = hash_entry.key_idx; 322 323 } else { 324 key_idx = (uint32_t)res->resource_hndl; 325 } 326 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_idx, &entry)) { 327 BNXT_TF_DBG(ERR, "Gen tbl entry get failed %x:%" PRIX64 "\n", 328 tbl_idx, res->resource_hndl); 329 return -EINVAL; 330 } 331 332 /* Decrement the reference count */ 333 if (!ULP_GEN_TBL_REF_CNT(&entry)) { 334 BNXT_TF_DBG(ERR, "generic table corrupt %x:%" PRIX64 "\n", 335 tbl_idx, res->resource_hndl); 336 return -EINVAL; 337 } 338 ULP_GEN_TBL_REF_CNT_DEC(&entry); 339 340 /* retain the details since there are other users */ 341 if (ULP_GEN_TBL_REF_CNT(&entry)) 342 return 0; 343 344 /* Delete the generic table entry. First extract the fid */ 345 if (ulp_mapper_gen_tbl_entry_data_get(&entry, ULP_GEN_TBL_FID_OFFSET, 346 ULP_GEN_TBL_FID_SIZE_BITS, 347 (uint8_t *)&fid, 348 sizeof(fid))) { 349 BNXT_TF_DBG(ERR, "Unable to get fid %x:%" PRIX64 "\n", 350 tbl_idx, res->resource_hndl); 351 return -EINVAL; 352 } 353 fid = tfp_be_to_cpu_32(fid); 354 /* no need to del if fid is 0 since there is no associated resource */ 355 if (fid) { 356 /* Destroy the flow associated with the shared flow id */ 357 if (ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID, 358 fid)) 359 BNXT_TF_DBG(ERR, 360 "Error in deleting shared flow id %x\n", 361 fid); 362 } 363 364 /* Delete the entry from the hash table */ 365 if (gen_tbl_list->hash_tbl) 366 ulp_gen_hash_tbl_list_del(gen_tbl_list->hash_tbl, &hash_entry); 367 368 /* clear the byte data of the generic table entry */ 369 memset(entry.byte_data, 0, entry.byte_data_size); 370 371 return 0; 372 } 373 374 /* 375 * Write the generic table list hash entry 376 * 377 * tbl_list [in] - pointer to the generic table list 378 * hash_entry [in] - Hash table entry 379 * gen_tbl_ent [out] - generic table entry 380 * 381 * returns 0 on success. 382 */ 383 int32_t 384 ulp_mapper_gen_tbl_hash_entry_add(struct ulp_mapper_gen_tbl_list *tbl_list, 385 struct ulp_gen_hash_entry_params *hash_entry, 386 struct ulp_mapper_gen_tbl_entry *gen_tbl_ent) 387 { 388 uint32_t key; 389 int32_t rc = 0; 390 391 switch (hash_entry->search_flag) { 392 case ULP_GEN_HASH_SEARCH_FOUND: 393 BNXT_TF_DBG(ERR, "%s: gen hash entry already present\n", 394 tbl_list->gen_tbl_name); 395 return -EINVAL; 396 case ULP_GEN_HASH_SEARCH_FULL: 397 BNXT_TF_DBG(ERR, "%s: gen hash table is full\n", 398 tbl_list->gen_tbl_name); 399 return -EINVAL; 400 case ULP_GEN_HASH_SEARCH_MISSED: 401 rc = ulp_gen_hash_tbl_list_add(tbl_list->hash_tbl, hash_entry); 402 if (rc) { 403 BNXT_TF_DBG(ERR, "%s: gen hash table add failed\n", 404 tbl_list->gen_tbl_name); 405 return -EINVAL; 406 } 407 key = hash_entry->key_idx; 408 gen_tbl_ent->ref_count = &tbl_list->container.ref_count[key]; 409 gen_tbl_ent->byte_data_size = 410 tbl_list->container.byte_data_size; 411 gen_tbl_ent->byte_data = &tbl_list->container.byte_data[key * 412 gen_tbl_ent->byte_data_size]; 413 gen_tbl_ent->byte_order = tbl_list->container.byte_order; 414 break; 415 default: 416 BNXT_TF_DBG(ERR, "%s: invalid search flag\n", 417 tbl_list->gen_tbl_name); 418 return -EINVAL; 419 } 420 421 return rc; 422 } 423