1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2020 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 18 struct tf; 19 20 /** 21 * TCAM DBs. 22 */ 23 static void *tcam_db[TF_DIR_MAX]; 24 25 /** 26 * TCAM Shadow DBs 27 */ 28 /* static void *shadow_tcam_db[TF_DIR_MAX]; */ 29 30 /** 31 * Init flag, set on bind and cleared on unbind 32 */ 33 static uint8_t init; 34 35 /** 36 * Shadow init flag, set on bind and cleared on unbind 37 */ 38 /* static uint8_t shadow_init; */ 39 40 int 41 tf_tcam_bind(struct tf *tfp, 42 struct tf_tcam_cfg_parms *parms) 43 { 44 int rc; 45 int i; 46 struct tf_tcam_resources *tcam_cnt; 47 struct tf_rm_create_db_parms db_cfg = { 0 }; 48 49 TF_CHECK_PARMS2(tfp, parms); 50 51 if (init) { 52 TFP_DRV_LOG(ERR, 53 "TCAM DB already initialized\n"); 54 return -EINVAL; 55 } 56 57 tcam_cnt = parms->resources->tcam_cnt; 58 if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2) || 59 (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2)) { 60 TFP_DRV_LOG(ERR, 61 "Number of WC TCAM entries cannot be odd num\n"); 62 return -EINVAL; 63 } 64 65 db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM; 66 db_cfg.num_elements = parms->num_elements; 67 db_cfg.cfg = parms->cfg; 68 69 for (i = 0; i < TF_DIR_MAX; i++) { 70 db_cfg.dir = i; 71 db_cfg.alloc_cnt = parms->resources->tcam_cnt[i].cnt; 72 db_cfg.rm_db = &tcam_db[i]; 73 rc = tf_rm_create_db(tfp, &db_cfg); 74 if (rc) { 75 TFP_DRV_LOG(ERR, 76 "%s: TCAM DB creation failed\n", 77 tf_dir_2_str(i)); 78 return rc; 79 } 80 } 81 82 init = 1; 83 84 TFP_DRV_LOG(INFO, 85 "TCAM - initialized\n"); 86 87 return 0; 88 } 89 90 int 91 tf_tcam_unbind(struct tf *tfp) 92 { 93 int rc; 94 int i; 95 struct tf_rm_free_db_parms fparms = { 0 }; 96 97 TF_CHECK_PARMS1(tfp); 98 99 /* Bail if nothing has been initialized */ 100 if (!init) { 101 TFP_DRV_LOG(INFO, 102 "No TCAM DBs created\n"); 103 return 0; 104 } 105 106 for (i = 0; i < TF_DIR_MAX; i++) { 107 fparms.dir = i; 108 fparms.rm_db = tcam_db[i]; 109 rc = tf_rm_free_db(tfp, &fparms); 110 if (rc) 111 return rc; 112 113 tcam_db[i] = NULL; 114 } 115 116 init = 0; 117 118 return 0; 119 } 120 121 int 122 tf_tcam_alloc(struct tf *tfp, 123 struct tf_tcam_alloc_parms *parms) 124 { 125 int rc; 126 struct tf_session *tfs; 127 struct tf_dev_info *dev; 128 struct tf_rm_allocate_parms aparms = { 0 }; 129 uint16_t num_slice_per_row = 1; 130 131 TF_CHECK_PARMS2(tfp, parms); 132 133 if (!init) { 134 TFP_DRV_LOG(ERR, 135 "%s: No TCAM DBs created\n", 136 tf_dir_2_str(parms->dir)); 137 return -EINVAL; 138 } 139 140 /* Retrieve the session information */ 141 rc = tf_session_get_session(tfp, &tfs); 142 if (rc) 143 return rc; 144 145 /* Retrieve the device information */ 146 rc = tf_session_get_device(tfs, &dev); 147 if (rc) 148 return rc; 149 150 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 151 rc = -EOPNOTSUPP; 152 TFP_DRV_LOG(ERR, 153 "%s: Operation not supported, rc:%s\n", 154 tf_dir_2_str(parms->dir), 155 strerror(-rc)); 156 return rc; 157 } 158 159 /* Need to retrieve row size etc */ 160 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 161 parms->type, 162 parms->key_size, 163 &num_slice_per_row); 164 if (rc) 165 return rc; 166 167 /* Allocate requested element */ 168 aparms.rm_db = tcam_db[parms->dir]; 169 aparms.db_index = parms->type; 170 aparms.priority = parms->priority; 171 aparms.index = (uint32_t *)&parms->idx; 172 rc = tf_rm_allocate(&aparms); 173 if (rc) { 174 TFP_DRV_LOG(ERR, 175 "%s: Failed tcam, type:%d\n", 176 tf_dir_2_str(parms->dir), 177 parms->type); 178 return rc; 179 } 180 181 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM && 182 (parms->idx % 2) != 0) { 183 rc = tf_rm_allocate(&aparms); 184 if (rc) { 185 TFP_DRV_LOG(ERR, 186 "%s: Failed tcam, type:%d\n", 187 tf_dir_2_str(parms->dir), 188 parms->type); 189 return rc; 190 } 191 } 192 193 parms->idx *= num_slice_per_row; 194 195 return 0; 196 } 197 198 int 199 tf_tcam_free(struct tf *tfp, 200 struct tf_tcam_free_parms *parms) 201 { 202 int rc; 203 struct tf_session *tfs; 204 struct tf_dev_info *dev; 205 struct tf_rm_is_allocated_parms aparms = { 0 }; 206 struct tf_rm_free_parms fparms = { 0 }; 207 struct tf_rm_get_hcapi_parms hparms = { 0 }; 208 uint16_t num_slice_per_row = 1; 209 int allocated = 0; 210 211 TF_CHECK_PARMS2(tfp, parms); 212 213 if (!init) { 214 TFP_DRV_LOG(ERR, 215 "%s: No TCAM DBs created\n", 216 tf_dir_2_str(parms->dir)); 217 return -EINVAL; 218 } 219 220 /* Retrieve the session information */ 221 rc = tf_session_get_session(tfp, &tfs); 222 if (rc) 223 return rc; 224 225 /* Retrieve the device information */ 226 rc = tf_session_get_device(tfs, &dev); 227 if (rc) 228 return rc; 229 230 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 231 rc = -EOPNOTSUPP; 232 TFP_DRV_LOG(ERR, 233 "%s: Operation not supported, rc:%s\n", 234 tf_dir_2_str(parms->dir), 235 strerror(-rc)); 236 return rc; 237 } 238 239 /* Need to retrieve row size etc */ 240 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 241 parms->type, 242 0, 243 &num_slice_per_row); 244 if (rc) 245 return rc; 246 247 /* Check if element is in use */ 248 aparms.rm_db = tcam_db[parms->dir]; 249 aparms.db_index = parms->type; 250 aparms.index = parms->idx / num_slice_per_row; 251 aparms.allocated = &allocated; 252 rc = tf_rm_is_allocated(&aparms); 253 if (rc) 254 return rc; 255 256 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 257 TFP_DRV_LOG(ERR, 258 "%s: Entry already free, type:%d, index:%d\n", 259 tf_dir_2_str(parms->dir), 260 parms->type, 261 parms->idx); 262 return -EINVAL; 263 } 264 265 /* Free requested element */ 266 fparms.rm_db = tcam_db[parms->dir]; 267 fparms.db_index = parms->type; 268 fparms.index = parms->idx / num_slice_per_row; 269 rc = tf_rm_free(&fparms); 270 if (rc) { 271 TFP_DRV_LOG(ERR, 272 "%s: Free failed, type:%d, index:%d\n", 273 tf_dir_2_str(parms->dir), 274 parms->type, 275 parms->idx); 276 return rc; 277 } 278 279 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM) { 280 int i; 281 282 for (i = -1; i < 3; i += 3) { 283 aparms.index += i; 284 rc = tf_rm_is_allocated(&aparms); 285 if (rc) 286 return rc; 287 288 if (allocated == TF_RM_ALLOCATED_ENTRY_IN_USE) { 289 /* Free requested element */ 290 fparms.index = aparms.index; 291 rc = tf_rm_free(&fparms); 292 if (rc) { 293 TFP_DRV_LOG(ERR, 294 "%s: Free failed, type:%d, index:%d\n", 295 tf_dir_2_str(parms->dir), 296 parms->type, 297 fparms.index); 298 return rc; 299 } 300 } 301 } 302 } 303 304 /* Convert TF type to HCAPI RM type */ 305 hparms.rm_db = tcam_db[parms->dir]; 306 hparms.db_index = parms->type; 307 hparms.hcapi_type = &parms->hcapi_type; 308 309 rc = tf_rm_get_hcapi_type(&hparms); 310 if (rc) 311 return rc; 312 313 rc = tf_msg_tcam_entry_free(tfp, parms); 314 if (rc) { 315 /* Log error */ 316 TFP_DRV_LOG(ERR, 317 "%s: %s: Entry %d free failed, rc:%s\n", 318 tf_dir_2_str(parms->dir), 319 tf_tcam_tbl_2_str(parms->type), 320 parms->idx, 321 strerror(-rc)); 322 } 323 324 return 0; 325 } 326 327 int 328 tf_tcam_alloc_search(struct tf *tfp __rte_unused, 329 struct tf_tcam_alloc_search_parms *parms __rte_unused) 330 { 331 return 0; 332 } 333 334 int 335 tf_tcam_set(struct tf *tfp __rte_unused, 336 struct tf_tcam_set_parms *parms __rte_unused) 337 { 338 int rc; 339 struct tf_session *tfs; 340 struct tf_dev_info *dev; 341 struct tf_rm_is_allocated_parms aparms = { 0 }; 342 struct tf_rm_get_hcapi_parms hparms = { 0 }; 343 uint16_t num_slice_per_row = 1; 344 int allocated = 0; 345 346 TF_CHECK_PARMS2(tfp, parms); 347 348 if (!init) { 349 TFP_DRV_LOG(ERR, 350 "%s: No TCAM DBs created\n", 351 tf_dir_2_str(parms->dir)); 352 return -EINVAL; 353 } 354 355 /* Retrieve the session information */ 356 rc = tf_session_get_session(tfp, &tfs); 357 if (rc) 358 return rc; 359 360 /* Retrieve the device information */ 361 rc = tf_session_get_device(tfs, &dev); 362 if (rc) 363 return rc; 364 365 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 366 rc = -EOPNOTSUPP; 367 TFP_DRV_LOG(ERR, 368 "%s: Operation not supported, rc:%s\n", 369 tf_dir_2_str(parms->dir), 370 strerror(-rc)); 371 return rc; 372 } 373 374 /* Need to retrieve row size etc */ 375 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 376 parms->type, 377 parms->key_size, 378 &num_slice_per_row); 379 if (rc) 380 return rc; 381 382 /* Check if element is in use */ 383 aparms.rm_db = tcam_db[parms->dir]; 384 aparms.db_index = parms->type; 385 aparms.index = parms->idx / num_slice_per_row; 386 aparms.allocated = &allocated; 387 rc = tf_rm_is_allocated(&aparms); 388 if (rc) 389 return rc; 390 391 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 392 TFP_DRV_LOG(ERR, 393 "%s: Entry is not allocated, type:%d, index:%d\n", 394 tf_dir_2_str(parms->dir), 395 parms->type, 396 parms->idx); 397 return -EINVAL; 398 } 399 400 /* Convert TF type to HCAPI RM type */ 401 hparms.rm_db = tcam_db[parms->dir]; 402 hparms.db_index = parms->type; 403 hparms.hcapi_type = &parms->hcapi_type; 404 405 rc = tf_rm_get_hcapi_type(&hparms); 406 if (rc) 407 return rc; 408 409 rc = tf_msg_tcam_entry_set(tfp, parms); 410 if (rc) { 411 /* Log error */ 412 TFP_DRV_LOG(ERR, 413 "%s: %s: Entry %d set failed, rc:%s", 414 tf_dir_2_str(parms->dir), 415 tf_tcam_tbl_2_str(parms->type), 416 parms->idx, 417 strerror(-rc)); 418 } 419 420 return 0; 421 } 422 423 int 424 tf_tcam_get(struct tf *tfp __rte_unused, 425 struct tf_tcam_get_parms *parms __rte_unused) 426 { 427 return 0; 428 } 429