1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2024 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 #include <rte_common.h> 8 #include <rte_errno.h> 9 #include <rte_log.h> 10 #include "tf_core.h" 11 #include "tf_util.h" 12 #include "tf_common.h" 13 #include "tf_em.h" 14 #include "tf_msg.h" 15 #include "tfp.h" 16 #include "tf_ext_flow_handle.h" 17 18 #include "bnxt.h" 19 20 #define TF_EM_DB_EM_REC 0 21 22 /** 23 * EM Pool 24 */ 25 #include "dpool.h" 26 27 /** 28 * Insert EM internal entry API 29 * 30 * returns: 31 * 0 - Success 32 */ 33 int 34 tf_em_insert_int_entry(struct tf *tfp, 35 struct tf_insert_em_entry_parms *parms) 36 { 37 int rc; 38 uint32_t gfid; 39 uint16_t rptr_index = 0; 40 uint8_t rptr_entry = 0; 41 uint8_t num_of_entries = 0; 42 struct tf_session *tfs; 43 struct dpool *pool; 44 uint32_t index; 45 46 /* Retrieve the session information */ 47 rc = tf_session_get_session(tfp, &tfs); 48 if (rc) { 49 TFP_DRV_LOG(ERR, 50 "%s: Failed to lookup session, rc:%s\n", 51 tf_dir_2_str(parms->dir), 52 strerror(-rc)); 53 return rc; 54 } 55 56 pool = (struct dpool *)tfs->em_pool[parms->dir]; 57 index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0); 58 if (index == DP_INVALID_INDEX) { 59 PMD_DRV_LOG_LINE(ERR, 60 "%s, EM entry index allocation failed", 61 tf_dir_2_str(parms->dir)); 62 return -1; 63 } 64 65 rptr_index = index; 66 rc = tf_msg_insert_em_internal_entry(tfp, 67 parms, 68 &rptr_index, 69 &rptr_entry, 70 &num_of_entries); 71 if (rc) { 72 /* Free the allocated index before returning */ 73 dpool_free(pool, index); 74 return -1; 75 } 76 77 TF_SET_GFID(gfid, 78 ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) | 79 rptr_entry), 80 0); /* N/A for internal table */ 81 82 TF_SET_FLOW_ID(parms->flow_id, 83 gfid, 84 TF_GFID_TABLE_INTERNAL, 85 parms->dir); 86 87 TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle, 88 (uint32_t)num_of_entries, 89 0, 90 TF_FLAGS_FLOW_HANDLE_INTERNAL, 91 rptr_index, 92 rptr_entry, 93 0); 94 return 0; 95 } 96 97 /** Delete EM internal entry API 98 * 99 * returns: 100 * 0 101 * -EINVAL 102 */ 103 int 104 tf_em_delete_int_entry(struct tf *tfp, 105 struct tf_delete_em_entry_parms *parms) 106 { 107 int rc = 0; 108 struct tf_session *tfs; 109 struct dpool *pool; 110 /* Retrieve the session information */ 111 rc = tf_session_get_session(tfp, &tfs); 112 if (rc) { 113 TFP_DRV_LOG(ERR, 114 "%s: Failed to lookup session, rc:%s\n", 115 tf_dir_2_str(parms->dir), 116 strerror(-rc)); 117 return rc; 118 } 119 120 rc = tf_msg_delete_em_entry(tfp, parms); 121 122 /* Return resource to pool */ 123 if (rc == 0) { 124 pool = (struct dpool *)tfs->em_pool[parms->dir]; 125 dpool_free(pool, parms->index); 126 } 127 128 return rc; 129 } 130 131 static int 132 tf_em_move_callback(void *user_data, 133 uint64_t entry_data, 134 uint32_t new_index) 135 { 136 int rc; 137 struct tf *tfp = (struct tf *)user_data; 138 struct tf_move_em_entry_parms parms; 139 struct tf_dev_info *dev; 140 struct tf_session *tfs; 141 142 memset(&parms, 0, sizeof(parms)); 143 144 parms.tbl_scope_id = 0; 145 parms.flow_handle = entry_data; 146 parms.new_index = new_index; 147 TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir); 148 parms.mem = TF_MEM_INTERNAL; 149 150 /* Retrieve the session information */ 151 rc = tf_session_get_session(tfp, &tfs); 152 if (rc) { 153 TFP_DRV_LOG(ERR, 154 "%s: Failed to lookup session, rc:%s\n", 155 tf_dir_2_str(parms.dir), 156 strerror(-rc)); 157 return rc; 158 } 159 160 /* Retrieve the device information */ 161 rc = tf_session_get_device(tfs, &dev); 162 if (rc) { 163 TFP_DRV_LOG(ERR, 164 "%s: Failed to lookup device, rc:%s\n", 165 tf_dir_2_str(parms.dir), 166 strerror(-rc)); 167 return rc; 168 } 169 170 if (dev->ops->tf_dev_move_int_em_entry != NULL) 171 rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms); 172 else 173 rc = -EOPNOTSUPP; 174 175 return rc; 176 } 177 178 int 179 tf_em_int_bind(struct tf *tfp, 180 struct tf_em_cfg_parms *parms) 181 { 182 int rc; 183 int db_rc[TF_DIR_MAX] = { 0 }; 184 int i; 185 struct tf_rm_create_db_parms db_cfg = { 0 }; 186 struct tf_rm_get_alloc_info_parms iparms; 187 struct tf_rm_alloc_info info; 188 struct em_rm_db *em_db; 189 struct tfp_calloc_parms cparms; 190 struct tf_session *tfs; 191 192 TF_CHECK_PARMS2(tfp, parms); 193 194 /* Retrieve the session information */ 195 rc = tf_session_get_session_internal(tfp, &tfs); 196 if (rc) 197 return rc; 198 199 memset(&db_cfg, 0, sizeof(db_cfg)); 200 cparms.nitems = 1; 201 cparms.size = sizeof(struct em_rm_db); 202 cparms.alignment = 0; 203 if (tfp_calloc(&cparms) != 0) { 204 TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n", 205 strerror(ENOMEM)); 206 return -ENOMEM; 207 } 208 209 em_db = cparms.mem_va; 210 for (i = 0; i < TF_DIR_MAX; i++) 211 em_db->em_db[i] = NULL; 212 tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db); 213 214 db_cfg.module = TF_MODULE_TYPE_EM; 215 db_cfg.num_elements = parms->num_elements; 216 db_cfg.cfg = parms->cfg; 217 218 for (i = 0; i < TF_DIR_MAX; i++) { 219 db_cfg.dir = i; 220 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt; 221 222 /* Check if we got any request to support EEM, if so 223 * we build an EM Int DB holding Table Scopes. 224 */ 225 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0) 226 continue; 227 228 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] % 229 TF_SESSION_EM_ENTRY_SIZE != 0) { 230 rc = -ENOMEM; 231 TFP_DRV_LOG(ERR, 232 "%s, EM Allocation must be in blocks of %d, failure %s\n", 233 tf_dir_2_str(i), 234 TF_SESSION_EM_ENTRY_SIZE, 235 strerror(-rc)); 236 237 return rc; 238 } 239 240 db_cfg.rm_db = (void *)&em_db->em_db[i]; 241 if (tf_session_is_shared_session(tfs) && 242 (!tf_session_is_shared_session_creator(tfs))) 243 db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg); 244 else 245 db_rc[i] = tf_rm_create_db(tfp, &db_cfg); 246 } 247 248 /* No db created */ 249 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { 250 TFP_DRV_LOG(ERR, "EM Int DB creation failed\n"); 251 return db_rc[TF_DIR_RX]; 252 } 253 254 if (!tf_session_is_shared_session(tfs)) { 255 for (i = 0; i < TF_DIR_MAX; i++) { 256 iparms.rm_db = em_db->em_db[i]; 257 iparms.subtype = TF_EM_DB_EM_REC; 258 iparms.info = &info; 259 260 rc = tf_rm_get_info(&iparms); 261 if (rc) { 262 TFP_DRV_LOG(ERR, 263 "%s: EM DB get info failed\n", 264 tf_dir_2_str(i)); 265 return rc; 266 } 267 268 /* 269 * Allocate stack pool 270 */ 271 cparms.nitems = 1; 272 cparms.size = sizeof(struct dpool); 273 cparms.alignment = 0; 274 275 rc = tfp_calloc(&cparms); 276 277 if (rc) { 278 TFP_DRV_LOG(ERR, 279 "%s, EM stack allocation failure %s\n", 280 tf_dir_2_str(i), 281 strerror(-rc)); 282 return rc; 283 } 284 285 tfs->em_pool[i] = (struct dpool *)cparms.mem_va; 286 287 rc = dpool_init(tfs->em_pool[i], 288 iparms.info->entry.start, 289 iparms.info->entry.stride, 290 7, 291 (void *)tfp, 292 tf_em_move_callback); 293 /* Logging handled in tf_create_em_pool */ 294 if (rc) 295 return rc; 296 297 #ifdef TF_FLOW_SCALE_QUERY 298 /* Initialize the usage state buffer for EM */ 299 tf_em_usage_init(tfp, 300 i, 301 iparms.info->entry.stride); 302 #endif /* TF_FLOW_SCALE_QUERY */ 303 } 304 305 if (rc) { 306 TFP_DRV_LOG(ERR, 307 "%s: EM pool init failed\n", 308 tf_dir_2_str(i)); 309 return rc; 310 } 311 } 312 313 return 0; 314 } 315 316 int 317 tf_em_int_unbind(struct tf *tfp) 318 { 319 int rc; 320 int i; 321 struct tf_rm_free_db_parms fparms = { 0 }; 322 struct em_rm_db *em_db; 323 void *em_db_ptr = NULL; 324 struct tf_session *tfs; 325 326 TF_CHECK_PARMS1(tfp); 327 328 /* Retrieve the session information */ 329 rc = tf_session_get_session_internal(tfp, &tfs); 330 if (rc) 331 return rc; 332 333 if (!tf_session_is_shared_session(tfs)) { 334 for (i = 0; i < TF_DIR_MAX; i++) { 335 if (tfs->em_pool[i] == NULL) 336 continue; 337 dpool_free_all(tfs->em_pool[i]); 338 } 339 } 340 341 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr); 342 if (rc) 343 return 0; 344 345 em_db = (struct em_rm_db *)em_db_ptr; 346 for (i = 0; i < TF_DIR_MAX; i++) { 347 if (em_db->em_db[i] == NULL) 348 continue; 349 fparms.dir = i; 350 fparms.rm_db = em_db->em_db[i]; 351 rc = tf_rm_free_db(tfp, &fparms); 352 if (rc) 353 return rc; 354 355 em_db->em_db[i] = NULL; 356 } 357 358 return 0; 359 } 360 361 int 362 tf_em_get_resc_info(struct tf *tfp, 363 struct tf_em_resource_info *em) 364 { 365 int rc; 366 int d; 367 struct tf_resource_info *dinfo; 368 struct tf_rm_get_alloc_info_parms ainfo; 369 void *em_db_ptr = NULL; 370 struct em_rm_db *em_db; 371 372 TF_CHECK_PARMS2(tfp, em); 373 374 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr); 375 if (rc == -ENOMEM) 376 return 0; /* db does not exist */ 377 else if (rc) 378 return rc; /* db error */ 379 380 em_db = (struct em_rm_db *)em_db_ptr; 381 382 /* check if reserved resource for EM is multiple of num_slices */ 383 for (d = 0; d < TF_DIR_MAX; d++) { 384 ainfo.rm_db = em_db->em_db[d]; 385 dinfo = em[d].info; 386 387 if (!ainfo.rm_db) 388 continue; 389 390 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 391 ainfo.subtype = 0; 392 rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX); 393 if (rc && rc != -ENOTSUP) 394 return rc; 395 } 396 397 return 0; 398 } 399