1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
10 #include "tf_session.h"
19 #include "tf_common.h"
22 static inline uint32_t SWAP_WORDS32(uint32_t val32)
24 return (((val32 & 0x0000ffff) << 16) |
25 ((val32 & 0xffff0000) >> 16));
28 static void tf_seeds_init(struct tf_session *session)
33 /* Initialize the lfsr */
36 /* RX and TX use the same seed values */
37 session->lkup_lkup3_init_cfg[TF_DIR_RX] =
38 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
39 SWAP_WORDS32(rand32());
41 for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
42 r = SWAP_WORDS32(rand32());
43 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
44 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
45 r = SWAP_WORDS32(rand32());
46 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
47 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
52 * Create EM Tbl pool of memory indexes.
59 * number of entries to write
62 * 0 - Success, entry allocated - no search support
63 * -ENOMEM -EINVAL -EOPNOTSUPP
64 * - Failure, entry not allocated, out of resources
67 tf_create_em_pool(struct tf_session *session,
71 struct tfp_calloc_parms parms;
74 struct stack *pool = &session->em_pool[dir];
76 parms.nitems = num_entries;
77 parms.size = sizeof(uint32_t);
80 if (tfp_calloc(&parms) != 0) {
81 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
88 rc = stack_init(num_entries, parms.mem_va, pool);
91 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
96 /* Fill pool with indexes
100 for (i = 0; i < num_entries; i++) {
101 rc = stack_push(pool, j);
103 TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
110 if (!stack_is_full(pool)) {
112 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
119 tfp_free((void *)parms.mem_va);
124 * Create EM Tbl pool of memory indexes.
134 tf_free_em_pool(struct tf_session *session,
137 struct stack *pool = &session->em_pool[dir];
140 ptr = stack_items(pool);
146 tf_open_session(struct tf *tfp,
147 struct tf_open_session_parms *parms)
150 struct tf_session *session;
151 struct tfp_calloc_parms alloc_parms;
152 unsigned int domain, bus, slot, device;
153 uint8_t fw_session_id;
156 if (tfp == NULL || parms == NULL)
159 /* Filter out any non-supported device types on the Core
160 * side. It is assumed that the Firmware will be supported if
161 * firmware open session succeeds.
163 if (parms->device_type != TF_DEVICE_TYPE_WH)
166 /* Build the beginning of session_id */
167 rc = sscanf(parms->ctrl_chan_name,
175 "Failed to scan device ctrl_chan_name\n");
179 /* open FW session and get a new session_id */
180 rc = tf_msg_session_open(tfp,
181 parms->ctrl_chan_name,
187 "Session is already open, rc:%d\n",
191 "Open message send failed, rc:%d\n",
194 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
198 /* Allocate session */
199 alloc_parms.nitems = 1;
200 alloc_parms.size = sizeof(struct tf_session_info);
201 alloc_parms.alignment = 0;
202 rc = tfp_calloc(&alloc_parms);
206 "Failed to allocate session info, rc:%d\n",
211 tfp->session = alloc_parms.mem_va;
213 /* Allocate core data for the session */
214 alloc_parms.nitems = 1;
215 alloc_parms.size = sizeof(struct tf_session);
216 alloc_parms.alignment = 0;
217 rc = tfp_calloc(&alloc_parms);
221 "Failed to allocate session data, rc:%d\n",
226 tfp->session->core_data = alloc_parms.mem_va;
228 session = (struct tf_session *)tfp->session->core_data;
229 tfp_memcpy(session->ctrl_chan_name,
230 parms->ctrl_chan_name,
231 TF_SESSION_NAME_MAX);
233 /* Initialize Session */
234 session->device_type = parms->device_type;
238 /* Construct the Session ID */
239 session->session_id.internal.domain = domain;
240 session->session_id.internal.bus = bus;
241 session->session_id.internal.device = device;
242 session->session_id.internal.fw_session_id = fw_session_id;
244 rc = tf_msg_session_qcfg(tfp);
248 "Query config message send failed, rc:%d\n",
253 /* Shadow DB configuration */
254 if (parms->shadow_copy) {
255 /* Ignore shadow_copy setting */
256 session->shadow_copy = 0;/* parms->shadow_copy; */
258 rc = tf_rm_shadow_db_init(tfs);
261 "Shadow DB Initialization failed\n, rc:%d",
263 /* Add additional processing */
264 #endif /* TF_SHADOW */
267 /* Adjust the Session with what firmware allowed us to get */
268 rc = tf_rm_allocate_validate(tfp);
274 /* Setup hash seeds */
275 tf_seeds_init(session);
277 /* Initialize EM pool */
278 for (dir = 0; dir < TF_DIR_MAX; dir++) {
279 rc = tf_create_em_pool(session, dir, TF_SESSION_EM_POOL_SIZE);
282 "EM Pool initialization failed\n");
287 session->ref_count++;
289 /* Return session ID */
290 parms->session_id = session->session_id;
293 "Session created, session_id:%d\n",
294 parms->session_id.id);
297 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
298 parms->session_id.internal.domain,
299 parms->session_id.internal.bus,
300 parms->session_id.internal.device,
301 parms->session_id.internal.fw_session_id);
306 tfp_free(tfp->session->core_data);
307 tfp_free(tfp->session);
312 tf_close_session(tfp);
317 tf_attach_session(struct tf *tfp __rte_unused,
318 struct tf_attach_session_parms *parms __rte_unused)
326 /* - Open the shared memory for the attach_chan_name
327 * - Point to the shared session for this Device instance
328 * - Check that session is valid
329 * - Attach to the firmware so it can record there is more
330 * than one client of the session.
334 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
335 rc = tf_msg_session_attach(tfp,
336 parms->ctrl_chan_name,
340 #endif /* TF_SHARED */
345 tf_close_session(struct tf *tfp)
349 struct tf_session *tfs;
350 union tf_session_id session_id;
353 if (tfp == NULL || tfp->session == NULL)
356 tfs = (struct tf_session *)(tfp->session->core_data);
358 /* Cleanup if we're last user of the session */
359 if (tfs->ref_count == 1) {
360 /* Cleanup any outstanding resources */
361 rc_close = tf_rm_close(tfp);
364 if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
365 rc = tf_msg_session_close(tfp);
369 "Message send failed, rc:%d\n",
373 /* Update the ref_count */
377 session_id = tfs->session_id;
379 /* Final cleanup as we're last user of the session */
380 if (tfs->ref_count == 0) {
382 for (dir = 0; dir < TF_DIR_MAX; dir++)
383 tf_free_em_pool(tfs, dir);
385 tfp_free(tfp->session->core_data);
386 tfp_free(tfp->session);
391 "Session closed, session_id:%d\n",
395 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
396 session_id.internal.domain,
397 session_id.internal.bus,
398 session_id.internal.device,
399 session_id.internal.fw_session_id);
404 /** insert EM hash entry API
410 int tf_insert_em_entry(struct tf *tfp,
411 struct tf_insert_em_entry_parms *parms)
413 struct tf_tbl_scope_cb *tbl_scope_cb;
415 if (tfp == NULL || parms == NULL)
418 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
419 (tfp->session->core_data),
420 parms->tbl_scope_id);
421 if (tbl_scope_cb == NULL)
424 /* Process the EM entry per Table Scope type */
425 if (parms->mem == TF_MEM_EXTERNAL) {
427 return tf_insert_eem_entry((struct tf_session *)
428 (tfp->session->core_data),
431 } else if (parms->mem == TF_MEM_INTERNAL) {
433 return tf_insert_em_internal_entry(tfp, parms);
439 /** Delete EM hash entry API
445 int tf_delete_em_entry(struct tf *tfp,
446 struct tf_delete_em_entry_parms *parms)
448 struct tf_tbl_scope_cb *tbl_scope_cb;
450 if (tfp == NULL || parms == NULL)
453 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
454 (tfp->session->core_data),
455 parms->tbl_scope_id);
456 if (tbl_scope_cb == NULL)
459 if (parms->mem == TF_MEM_EXTERNAL)
460 return tf_delete_eem_entry(tfp, parms);
462 return tf_delete_em_internal_entry(tfp, parms);
465 /** allocate identifier resource
467 * Returns success or failure code.
469 int tf_alloc_identifier(struct tf *tfp,
470 struct tf_alloc_identifier_parms *parms)
472 struct bitalloc *session_pool;
473 struct tf_session *tfs;
477 if (parms == NULL || tfp == NULL)
480 if (tfp->session == NULL || tfp->session->core_data == NULL) {
481 PMD_DRV_LOG(ERR, "%s: session error\n",
482 tf_dir_2_str(parms->dir));
486 tfs = (struct tf_session *)(tfp->session->core_data);
488 switch (parms->ident_type) {
489 case TF_IDENT_TYPE_L2_CTXT:
490 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
491 TF_L2_CTXT_REMAP_POOL_NAME,
494 case TF_IDENT_TYPE_PROF_FUNC:
495 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
496 TF_PROF_FUNC_POOL_NAME,
499 case TF_IDENT_TYPE_EM_PROF:
500 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
501 TF_EM_PROF_ID_POOL_NAME,
504 case TF_IDENT_TYPE_WC_PROF:
505 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
506 TF_WC_TCAM_PROF_ID_POOL_NAME,
509 case TF_IDENT_TYPE_L2_FUNC:
510 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
511 tf_dir_2_str(parms->dir),
512 tf_ident_2_str(parms->ident_type));
516 PMD_DRV_LOG(ERR, "%s: %s\n",
517 tf_dir_2_str(parms->dir),
518 tf_ident_2_str(parms->ident_type));
524 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
525 tf_dir_2_str(parms->dir),
526 tf_ident_2_str(parms->ident_type));
530 id = ba_alloc(session_pool);
533 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
534 tf_dir_2_str(parms->dir),
535 tf_ident_2_str(parms->ident_type));
542 /** free identifier resource
544 * Returns success or failure code.
546 int tf_free_identifier(struct tf *tfp,
547 struct tf_free_identifier_parms *parms)
549 struct bitalloc *session_pool;
552 struct tf_session *tfs;
554 if (parms == NULL || tfp == NULL)
557 if (tfp->session == NULL || tfp->session->core_data == NULL) {
558 PMD_DRV_LOG(ERR, "%s: Session error\n",
559 tf_dir_2_str(parms->dir));
563 tfs = (struct tf_session *)(tfp->session->core_data);
565 switch (parms->ident_type) {
566 case TF_IDENT_TYPE_L2_CTXT:
567 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
568 TF_L2_CTXT_REMAP_POOL_NAME,
571 case TF_IDENT_TYPE_PROF_FUNC:
572 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
573 TF_PROF_FUNC_POOL_NAME,
576 case TF_IDENT_TYPE_EM_PROF:
577 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
578 TF_EM_PROF_ID_POOL_NAME,
581 case TF_IDENT_TYPE_WC_PROF:
582 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
583 TF_WC_TCAM_PROF_ID_POOL_NAME,
586 case TF_IDENT_TYPE_L2_FUNC:
587 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
588 tf_dir_2_str(parms->dir),
589 tf_ident_2_str(parms->ident_type));
593 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
594 tf_dir_2_str(parms->dir),
595 tf_ident_2_str(parms->ident_type));
600 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
601 tf_dir_2_str(parms->dir),
602 tf_ident_2_str(parms->ident_type));
606 ba_rc = ba_inuse(session_pool, (int)parms->id);
608 if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
609 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
610 tf_dir_2_str(parms->dir),
611 tf_ident_2_str(parms->ident_type),
616 ba_free(session_pool, (int)parms->id);
622 tf_alloc_tcam_entry(struct tf *tfp,
623 struct tf_alloc_tcam_entry_parms *parms)
627 struct tf_session *tfs;
628 struct bitalloc *session_pool;
630 if (parms == NULL || tfp == NULL)
633 if (tfp->session == NULL || tfp->session->core_data == NULL) {
634 PMD_DRV_LOG(ERR, "%s: session error\n",
635 tf_dir_2_str(parms->dir));
639 tfs = (struct tf_session *)(tfp->session->core_data);
641 rc = tf_rm_lookup_tcam_type_pool(tfs,
643 parms->tcam_tbl_type,
645 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
649 index = ba_alloc(session_pool);
650 if (index == BA_FAIL) {
651 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
652 tf_dir_2_str(parms->dir),
653 tf_tcam_tbl_2_str(parms->tcam_tbl_type));
662 tf_set_tcam_entry(struct tf *tfp,
663 struct tf_set_tcam_entry_parms *parms)
667 struct tf_session *tfs;
668 struct bitalloc *session_pool;
670 if (tfp == NULL || parms == NULL) {
671 PMD_DRV_LOG(ERR, "Invalid parameters\n");
675 if (tfp->session == NULL || tfp->session->core_data == NULL) {
677 "%s, Session info invalid\n",
678 tf_dir_2_str(parms->dir));
682 tfs = (struct tf_session *)(tfp->session->core_data);
685 * Each tcam send msg function should check for key sizes range
688 rc = tf_rm_lookup_tcam_type_pool(tfs,
690 parms->tcam_tbl_type,
692 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
697 /* Verify that the entry has been previously allocated */
698 id = ba_inuse(session_pool, parms->idx);
701 "%s: %s: Invalid or not allocated index, idx:%d\n",
702 tf_dir_2_str(parms->dir),
703 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
708 rc = tf_msg_tcam_entry_set(tfp, parms);
714 tf_get_tcam_entry(struct tf *tfp __rte_unused,
715 struct tf_get_tcam_entry_parms *parms __rte_unused)
717 int rc = -EOPNOTSUPP;
719 if (tfp == NULL || parms == NULL) {
720 PMD_DRV_LOG(ERR, "Invalid parameters\n");
724 if (tfp->session == NULL || tfp->session->core_data == NULL) {
726 "%s, Session info invalid\n",
727 tf_dir_2_str(parms->dir));
735 tf_free_tcam_entry(struct tf *tfp,
736 struct tf_free_tcam_entry_parms *parms)
739 struct tf_session *tfs;
740 struct bitalloc *session_pool;
742 if (parms == NULL || tfp == NULL)
745 if (tfp->session == NULL || tfp->session->core_data == NULL) {
746 PMD_DRV_LOG(ERR, "%s: Session error\n",
747 tf_dir_2_str(parms->dir));
751 tfs = (struct tf_session *)(tfp->session->core_data);
753 rc = tf_rm_lookup_tcam_type_pool(tfs,
755 parms->tcam_tbl_type,
757 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
761 rc = ba_inuse(session_pool, (int)parms->idx);
762 if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
763 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
764 tf_dir_2_str(parms->dir),
765 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
770 ba_free(session_pool, (int)parms->idx);
772 rc = tf_msg_tcam_entry_free(tfp, parms);
775 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
776 tf_dir_2_str(parms->dir),
777 tf_tcam_tbl_2_str(parms->tcam_tbl_type),