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 9 #include "tf_tcam.h" 10 #include "tf_common.h" 11 #include "tf_util.h" 12 #include "tf_rm.h" 13 #include "tf_device.h" 14 #include "tfp.h" 15 #include "tf_session.h" 16 #include "tf_msg.h" 17 #include "tf_tcam_mgr_msg.h" 18 19 struct tf; 20 21 int 22 tf_tcam_bind(struct tf *tfp, 23 struct tf_tcam_cfg_parms *parms) 24 { 25 int rc; 26 int db_rc[TF_DIR_MAX] = { 0 }; 27 int d, t; 28 struct tf_rm_alloc_info info; 29 struct tf_rm_free_db_parms fparms; 30 struct tf_rm_create_db_parms db_cfg = { 0 }; 31 struct tf_tcam_resources local_tcam_cnt[TF_DIR_MAX]; 32 struct tf_tcam_resources *tcam_cnt; 33 struct tf_rm_get_alloc_info_parms ainfo; 34 uint16_t num_slices = 1; 35 struct tf_session *tfs; 36 struct tf_dev_info *dev; 37 struct tcam_rm_db *tcam_db; 38 struct tfp_calloc_parms cparms; 39 struct tf_resource_info resv_res[TF_DIR_MAX][TF_TCAM_TBL_TYPE_MAX]; 40 41 TF_CHECK_PARMS2(tfp, parms); 42 43 /* Retrieve the session information */ 44 rc = tf_session_get_session_internal(tfp, &tfs); 45 if (rc) 46 return rc; 47 48 /* Retrieve the device information */ 49 rc = tf_session_get_device(tfs, &dev); 50 if (rc) 51 return rc; 52 53 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 54 rc = -EOPNOTSUPP; 55 TFP_DRV_LOG(ERR, 56 "Operation not supported, rc:%s\n", 57 strerror(-rc)); 58 return rc; 59 } 60 61 tcam_cnt = parms->resources->tcam_cnt; 62 63 for (d = 0; d < TF_DIR_MAX; d++) { 64 for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { 65 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0, 66 &num_slices); 67 if (rc) 68 return rc; 69 70 if (num_slices == 1) 71 continue; 72 73 if (tcam_cnt[d].cnt[t] % num_slices) { 74 TFP_DRV_LOG(ERR, 75 "%s: Requested num of %s entries " 76 "has to be multiple of %d\n", 77 tf_dir_2_str(d), 78 tf_tcam_tbl_2_str(t), 79 num_slices); 80 return -EINVAL; 81 } 82 } 83 } 84 85 memset(&db_cfg, 0, sizeof(db_cfg)); 86 cparms.nitems = 1; 87 cparms.size = sizeof(struct tcam_rm_db); 88 cparms.alignment = 0; 89 if (tfp_calloc(&cparms) != 0) { 90 TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n", 91 strerror(ENOMEM)); 92 return -ENOMEM; 93 } 94 95 tcam_db = cparms.mem_va; 96 for (d = 0; d < TF_DIR_MAX; d++) 97 tcam_db->tcam_db[d] = NULL; 98 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db); 99 100 db_cfg.module = TF_MODULE_TYPE_TCAM; 101 db_cfg.num_elements = parms->num_elements; 102 db_cfg.cfg = parms->cfg; 103 104 for (d = 0; d < TF_DIR_MAX; d++) { 105 db_cfg.dir = d; 106 db_cfg.alloc_cnt = tcam_cnt[d].cnt; 107 db_cfg.rm_db = (void *)&tcam_db->tcam_db[d]; 108 if (tf_session_is_shared_session(tfs) && 109 (!tf_session_is_shared_session_creator(tfs))) 110 db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg); 111 else 112 db_rc[d] = tf_rm_create_db(tfp, &db_cfg); 113 } 114 /* No db created */ 115 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { 116 TFP_DRV_LOG(ERR, "No TCAM DB created\n"); 117 return db_rc[TF_DIR_RX]; 118 } 119 120 /* Collect info on which entries were reserved. */ 121 for (d = 0; d < TF_DIR_MAX; d++) { 122 for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) { 123 memset(&info, 0, sizeof(info)); 124 if (tcam_cnt[d].cnt[t] == 0) { 125 resv_res[d][t].start = 0; 126 resv_res[d][t].stride = 0; 127 continue; 128 } 129 ainfo.rm_db = tcam_db->tcam_db[d]; 130 ainfo.subtype = t; 131 ainfo.info = &info; 132 rc = tf_rm_get_info(&ainfo); 133 if (rc) 134 goto error; 135 136 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, t, 0, 137 &num_slices); 138 if (rc) 139 return rc; 140 141 if (num_slices > 1) { 142 /* check if reserved resource for is multiple of 143 * num_slices 144 */ 145 if (info.entry.start % num_slices != 0 || 146 info.entry.stride % num_slices != 0) { 147 TFP_DRV_LOG(ERR, 148 "%s: %s reserved resource" 149 " is not multiple of %d\n", 150 tf_dir_2_str(d), 151 tf_tcam_tbl_2_str(t), 152 num_slices); 153 rc = -EINVAL; 154 goto error; 155 } 156 } 157 158 resv_res[d][t].start = info.entry.start; 159 resv_res[d][t].stride = info.entry.stride; 160 } 161 } 162 163 rc = tf_tcam_mgr_bind_msg(tfp, dev, parms, resv_res); 164 if (rc) 165 return rc; 166 167 /* 168 * Make a local copy of tcam_cnt with only resources not managed by TCAM 169 * Manager requested. 170 */ 171 memcpy(&local_tcam_cnt, tcam_cnt, sizeof(local_tcam_cnt)); 172 tcam_cnt = local_tcam_cnt; 173 for (d = 0; d < TF_DIR_MAX; d++) 174 for (t = 0; t < TF_TCAM_TBL_TYPE_MAX; t++) 175 tcam_cnt[d].cnt[t] = 0; 176 177 TFP_DRV_LOG(INFO, 178 "TCAM - initialized\n"); 179 180 return 0; 181 error: 182 for (d = 0; d < TF_DIR_MAX; d++) { 183 if (tcam_db->tcam_db[d] != NULL) { 184 memset(&fparms, 0, sizeof(fparms)); 185 fparms.dir = d; 186 fparms.rm_db = tcam_db->tcam_db[d]; 187 /* 188 * Ignoring return here since we are in the error case 189 */ 190 (void)tf_rm_free_db(tfp, &fparms); 191 192 tcam_db->tcam_db[d] = NULL; 193 } 194 tcam_db->tcam_db[d] = NULL; 195 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL); 196 } 197 return rc; 198 } 199 200 int 201 tf_tcam_unbind(struct tf *tfp) 202 { 203 int rc; 204 int i; 205 struct tf_rm_free_db_parms fparms; 206 struct tcam_rm_db *tcam_db; 207 void *tcam_db_ptr = NULL; 208 struct tf_session *tfs; 209 struct tf_dev_info *dev; 210 TF_CHECK_PARMS1(tfp); 211 212 /* Retrieve the session information */ 213 rc = tf_session_get_session_internal(tfp, &tfs); 214 if (rc) 215 return rc; 216 217 /* Retrieve the device information */ 218 rc = tf_session_get_device(tfs, &dev); 219 if (rc) 220 return rc; 221 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 222 if (rc) 223 return 0; 224 225 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 226 227 for (i = 0; i < TF_DIR_MAX; i++) { 228 if (tcam_db->tcam_db[i] != NULL) { 229 memset(&fparms, 0, sizeof(fparms)); 230 fparms.dir = i; 231 fparms.rm_db = tcam_db->tcam_db[i]; 232 rc = tf_rm_free_db(tfp, &fparms); 233 if (rc) 234 return rc; 235 236 tcam_db->tcam_db[i] = NULL; 237 } 238 } 239 240 rc = tf_tcam_mgr_unbind_msg(tfp, dev); 241 if (rc) 242 return rc; 243 244 return 0; 245 } 246 247 int 248 tf_tcam_alloc(struct tf *tfp, 249 struct tf_tcam_alloc_parms *parms) 250 { 251 int rc; 252 struct tf_session *tfs; 253 struct tf_dev_info *dev; 254 uint16_t num_slices = 1; 255 256 TF_CHECK_PARMS2(tfp, parms); 257 258 /* Retrieve the session information */ 259 rc = tf_session_get_session_internal(tfp, &tfs); 260 if (rc) 261 return rc; 262 263 /* Retrieve the device information */ 264 rc = tf_session_get_device(tfs, &dev); 265 if (rc) 266 return rc; 267 268 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 269 rc = -EOPNOTSUPP; 270 TFP_DRV_LOG(ERR, 271 "%s: Operation not supported, rc:%s\n", 272 tf_dir_2_str(parms->dir), 273 strerror(-rc)); 274 return rc; 275 } 276 277 /* Need to retrieve number of slices based on the key_size */ 278 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 279 parms->type, 280 parms->key_size, 281 &num_slices); 282 if (rc) 283 return rc; 284 285 return tf_tcam_mgr_alloc_msg(tfp, dev, parms); 286 } 287 288 int 289 tf_tcam_free(struct tf *tfp, 290 struct tf_tcam_free_parms *parms) 291 { 292 int rc; 293 struct tf_session *tfs; 294 struct tf_dev_info *dev; 295 uint16_t num_slices = 1; 296 297 TF_CHECK_PARMS2(tfp, parms); 298 299 /* Retrieve the session information */ 300 rc = tf_session_get_session_internal(tfp, &tfs); 301 if (rc) 302 return rc; 303 304 /* Retrieve the device information */ 305 rc = tf_session_get_device(tfs, &dev); 306 if (rc) 307 return rc; 308 309 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 310 rc = -EOPNOTSUPP; 311 TFP_DRV_LOG(ERR, 312 "%s: Operation not supported, rc:%s\n", 313 tf_dir_2_str(parms->dir), 314 strerror(-rc)); 315 return rc; 316 } 317 318 /* Need to retrieve row size etc */ 319 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 320 parms->type, 321 0, 322 &num_slices); 323 if (rc) 324 return rc; 325 326 return tf_tcam_mgr_free_msg(tfp, dev, parms); 327 } 328 329 int 330 tf_tcam_set(struct tf *tfp __rte_unused, 331 struct tf_tcam_set_parms *parms __rte_unused) 332 { 333 int rc; 334 struct tf_session *tfs; 335 struct tf_dev_info *dev; 336 uint16_t num_slice_per_row = 1; 337 338 TF_CHECK_PARMS2(tfp, parms); 339 340 /* Retrieve the session information */ 341 rc = tf_session_get_session_internal(tfp, &tfs); 342 if (rc) 343 return rc; 344 345 /* Retrieve the device information */ 346 rc = tf_session_get_device(tfs, &dev); 347 if (rc) 348 return rc; 349 350 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 351 rc = -EOPNOTSUPP; 352 TFP_DRV_LOG(ERR, 353 "%s: Operation not supported, rc:%s\n", 354 tf_dir_2_str(parms->dir), 355 strerror(-rc)); 356 return rc; 357 } 358 359 /* Need to retrieve row size etc */ 360 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 361 parms->type, 362 parms->key_size, 363 &num_slice_per_row); 364 if (rc) 365 return rc; 366 367 return tf_tcam_mgr_set_msg(tfp, dev, parms); 368 } 369 370 int 371 tf_tcam_get(struct tf *tfp __rte_unused, 372 struct tf_tcam_get_parms *parms) 373 { 374 int rc; 375 struct tf_session *tfs; 376 struct tf_dev_info *dev; 377 378 TF_CHECK_PARMS2(tfp, parms); 379 380 /* Retrieve the session information */ 381 rc = tf_session_get_session_internal(tfp, &tfs); 382 if (rc) 383 return rc; 384 385 /* Retrieve the device information */ 386 rc = tf_session_get_device(tfs, &dev); 387 if (rc) 388 return rc; 389 390 return tf_tcam_mgr_get_msg(tfp, dev, parms); 391 } 392 393 int 394 tf_tcam_get_resc_info(struct tf *tfp, 395 struct tf_tcam_resource_info *tcam) 396 { 397 int rc; 398 int d; 399 struct tf_resource_info *dinfo; 400 struct tf_rm_get_alloc_info_parms ainfo; 401 void *tcam_db_ptr = NULL; 402 struct tcam_rm_db *tcam_db; 403 404 TF_CHECK_PARMS2(tfp, tcam); 405 406 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 407 if (rc == -ENOMEM) 408 return 0; /* db doesn't exist */ 409 else if (rc) 410 return rc; /* error getting db */ 411 412 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 413 414 /* check if reserved resource for WC is multiple of num_slices */ 415 for (d = 0; d < TF_DIR_MAX; d++) { 416 ainfo.rm_db = tcam_db->tcam_db[d]; 417 418 if (!ainfo.rm_db) 419 continue; 420 421 dinfo = tcam[d].info; 422 423 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 424 ainfo.subtype = 0; 425 rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX); 426 if (rc && rc != -ENOTSUP) 427 return rc; 428 } 429 430 return 0; 431 } 432