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