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, (uint32_t *)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 */
237 /* Construct the Session ID */
238 session->session_id.internal.domain = domain;
239 session->session_id.internal.bus = bus;
240 session->session_id.internal.device = device;
241 session->session_id.internal.fw_session_id = fw_session_id;
243 rc = tf_msg_session_qcfg(tfp);
247 "Query config message send failed, rc:%d\n",
252 /* Shadow DB configuration */
253 if (parms->shadow_copy) {
254 /* Ignore shadow_copy setting */
255 session->shadow_copy = 0;/* parms->shadow_copy; */
257 rc = tf_rm_shadow_db_init(tfs);
260 "Shadow DB Initialization failed\n, rc:%d",
262 /* Add additional processing */
263 #endif /* TF_SHADOW */
266 /* Adjust the Session with what firmware allowed us to get */
267 rc = tf_rm_allocate_validate(tfp);
273 /* Setup hash seeds */
274 tf_seeds_init(session);
276 /* Initialize EM pool */
277 for (dir = 0; dir < TF_DIR_MAX; dir++) {
278 rc = tf_create_em_pool(session,
280 TF_SESSION_EM_POOL_SIZE);
283 "EM Pool initialization failed\n");
288 session->ref_count++;
290 /* Return session ID */
291 parms->session_id = session->session_id;
294 "Session created, session_id:%d\n",
295 parms->session_id.id);
298 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
299 parms->session_id.internal.domain,
300 parms->session_id.internal.bus,
301 parms->session_id.internal.device,
302 parms->session_id.internal.fw_session_id);
307 tfp_free(tfp->session->core_data);
308 tfp_free(tfp->session);
313 tf_close_session(tfp);
318 tf_open_session_new(struct tf *tfp,
319 struct tf_open_session_parms *parms)
322 unsigned int domain, bus, slot, device;
323 struct tf_session_open_session_parms oparms;
325 TF_CHECK_PARMS(tfp, parms);
327 /* Filter out any non-supported device types on the Core
328 * side. It is assumed that the Firmware will be supported if
329 * firmware open session succeeds.
331 if (parms->device_type != TF_DEVICE_TYPE_WH) {
333 "Unsupported device type %d\n",
338 /* Verify control channel and build the beginning of session_id */
339 rc = sscanf(parms->ctrl_chan_name,
347 "Failed to scan device ctrl_chan_name\n");
351 parms->session_id.internal.domain = domain;
352 parms->session_id.internal.bus = bus;
353 parms->session_id.internal.device = device;
354 oparms.open_cfg = parms;
356 rc = tf_session_open_session(tfp, &oparms);
357 /* Logging handled by tf_session_open_session */
362 "Session created, session_id:%d\n",
363 parms->session_id.id);
366 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
367 parms->session_id.internal.domain,
368 parms->session_id.internal.bus,
369 parms->session_id.internal.device,
370 parms->session_id.internal.fw_session_id);
376 tf_attach_session(struct tf *tfp __rte_unused,
377 struct tf_attach_session_parms *parms __rte_unused)
385 /* - Open the shared memory for the attach_chan_name
386 * - Point to the shared session for this Device instance
387 * - Check that session is valid
388 * - Attach to the firmware so it can record there is more
389 * than one client of the session.
393 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
394 rc = tf_msg_session_attach(tfp,
395 parms->ctrl_chan_name,
399 #endif /* TF_SHARED */
404 tf_attach_session_new(struct tf *tfp,
405 struct tf_attach_session_parms *parms)
408 unsigned int domain, bus, slot, device;
409 struct tf_session_attach_session_parms aparms;
411 TF_CHECK_PARMS2(tfp, parms);
413 /* Verify control channel */
414 rc = sscanf(parms->ctrl_chan_name,
422 "Failed to scan device ctrl_chan_name\n");
426 /* Verify 'attach' channel */
427 rc = sscanf(parms->attach_chan_name,
435 "Failed to scan device attach_chan_name\n");
439 /* Prepare return value of session_id, using ctrl_chan_name
440 * device values as it becomes the session id.
442 parms->session_id.internal.domain = domain;
443 parms->session_id.internal.bus = bus;
444 parms->session_id.internal.device = device;
445 aparms.attach_cfg = parms;
446 rc = tf_session_attach_session(tfp,
448 /* Logging handled by dev_bind */
453 "Attached to session, session_id:%d\n",
454 parms->session_id.id);
457 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
458 parms->session_id.internal.domain,
459 parms->session_id.internal.bus,
460 parms->session_id.internal.device,
461 parms->session_id.internal.fw_session_id);
467 tf_close_session(struct tf *tfp)
471 struct tf_session *tfs;
472 union tf_session_id session_id;
475 if (tfp == NULL || tfp->session == NULL)
478 tfs = (struct tf_session *)(tfp->session->core_data);
480 /* Cleanup if we're last user of the session */
481 if (tfs->ref_count == 1) {
482 /* Cleanup any outstanding resources */
483 rc_close = tf_rm_close(tfp);
486 if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
487 rc = tf_msg_session_close(tfp);
491 "Message send failed, rc:%d\n",
495 /* Update the ref_count */
499 session_id = tfs->session_id;
501 /* Final cleanup as we're last user of the session */
502 if (tfs->ref_count == 0) {
504 for (dir = 0; dir < TF_DIR_MAX; dir++)
505 tf_free_em_pool(tfs, (enum tf_dir)dir);
507 tfp_free(tfp->session->core_data);
508 tfp_free(tfp->session);
513 "Session closed, session_id:%d\n",
517 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
518 session_id.internal.domain,
519 session_id.internal.bus,
520 session_id.internal.device,
521 session_id.internal.fw_session_id);
527 tf_close_session_new(struct tf *tfp)
530 struct tf_session_close_session_parms cparms = { 0 };
531 union tf_session_id session_id = { 0 };
534 TF_CHECK_PARMS1(tfp);
536 cparms.ref_count = &ref_count;
537 cparms.session_id = &session_id;
538 rc = tf_session_close_session(tfp,
540 /* Logging handled by tf_session_close_session */
545 "Closed session, session_id:%d, ref_count:%d\n",
546 cparms.session_id->id,
550 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
551 cparms.session_id->internal.domain,
552 cparms.session_id->internal.bus,
553 cparms.session_id->internal.device,
554 cparms.session_id->internal.fw_session_id);
559 /** insert EM hash entry API
565 int tf_insert_em_entry(struct tf *tfp,
566 struct tf_insert_em_entry_parms *parms)
568 struct tf_tbl_scope_cb *tbl_scope_cb;
570 if (tfp == NULL || parms == NULL)
573 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
574 (tfp->session->core_data),
575 parms->tbl_scope_id);
576 if (tbl_scope_cb == NULL)
579 /* Process the EM entry per Table Scope type */
580 if (parms->mem == TF_MEM_EXTERNAL) {
582 return tf_insert_eem_entry((struct tf_session *)
583 (tfp->session->core_data),
586 } else if (parms->mem == TF_MEM_INTERNAL) {
588 return tf_insert_em_internal_entry(tfp, parms);
594 /** Delete EM hash entry API
600 int tf_delete_em_entry(struct tf *tfp,
601 struct tf_delete_em_entry_parms *parms)
603 struct tf_tbl_scope_cb *tbl_scope_cb;
605 if (tfp == NULL || parms == NULL)
608 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
609 (tfp->session->core_data),
610 parms->tbl_scope_id);
611 if (tbl_scope_cb == NULL)
614 if (parms->mem == TF_MEM_EXTERNAL)
615 return tf_delete_eem_entry(tfp, parms);
617 return tf_delete_em_internal_entry(tfp, parms);
620 /** allocate identifier resource
622 * Returns success or failure code.
624 int tf_alloc_identifier(struct tf *tfp,
625 struct tf_alloc_identifier_parms *parms)
627 struct bitalloc *session_pool;
628 struct tf_session *tfs;
632 if (parms == NULL || tfp == NULL)
635 if (tfp->session == NULL || tfp->session->core_data == NULL) {
636 PMD_DRV_LOG(ERR, "%s: session error\n",
637 tf_dir_2_str(parms->dir));
641 tfs = (struct tf_session *)(tfp->session->core_data);
643 switch (parms->ident_type) {
644 case TF_IDENT_TYPE_L2_CTXT:
645 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
646 TF_L2_CTXT_REMAP_POOL_NAME,
649 case TF_IDENT_TYPE_PROF_FUNC:
650 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
651 TF_PROF_FUNC_POOL_NAME,
654 case TF_IDENT_TYPE_EM_PROF:
655 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
656 TF_EM_PROF_ID_POOL_NAME,
659 case TF_IDENT_TYPE_WC_PROF:
660 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
661 TF_WC_TCAM_PROF_ID_POOL_NAME,
664 case TF_IDENT_TYPE_L2_FUNC:
665 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
666 tf_dir_2_str(parms->dir),
667 tf_ident_2_str(parms->ident_type));
671 PMD_DRV_LOG(ERR, "%s: %s\n",
672 tf_dir_2_str(parms->dir),
673 tf_ident_2_str(parms->ident_type));
679 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
680 tf_dir_2_str(parms->dir),
681 tf_ident_2_str(parms->ident_type));
685 id = ba_alloc(session_pool);
688 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
689 tf_dir_2_str(parms->dir),
690 tf_ident_2_str(parms->ident_type));
698 tf_alloc_identifier_new(struct tf *tfp,
699 struct tf_alloc_identifier_parms *parms)
702 struct tf_session *tfs;
703 struct tf_dev_info *dev;
704 struct tf_ident_alloc_parms aparms;
707 TF_CHECK_PARMS2(tfp, parms);
709 /* Can't do static initialization due to UT enum check */
710 memset(&aparms, 0, sizeof(struct tf_ident_alloc_parms));
712 /* Retrieve the session information */
713 rc = tf_session_get_session(tfp, &tfs);
716 "%s: Failed to lookup session, rc:%s\n",
717 tf_dir_2_str(parms->dir),
722 /* Retrieve the device information */
723 rc = tf_session_get_device(tfs, &dev);
726 "%s: Failed to lookup device, rc:%s\n",
727 tf_dir_2_str(parms->dir),
732 if (dev->ops->tf_dev_alloc_ident == NULL) {
735 "%s: Operation not supported, rc:%s\n",
736 tf_dir_2_str(parms->dir),
741 aparms.dir = parms->dir;
742 aparms.ident_type = parms->ident_type;
744 rc = dev->ops->tf_dev_alloc_ident(tfp, &aparms);
747 "%s: Identifier allocation failed, rc:%s\n",
748 tf_dir_2_str(parms->dir),
758 int tf_free_identifier(struct tf *tfp,
759 struct tf_free_identifier_parms *parms)
761 struct bitalloc *session_pool;
764 struct tf_session *tfs;
766 if (parms == NULL || tfp == NULL)
769 if (tfp->session == NULL || tfp->session->core_data == NULL) {
770 PMD_DRV_LOG(ERR, "%s: Session error\n",
771 tf_dir_2_str(parms->dir));
775 tfs = (struct tf_session *)(tfp->session->core_data);
777 switch (parms->ident_type) {
778 case TF_IDENT_TYPE_L2_CTXT:
779 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
780 TF_L2_CTXT_REMAP_POOL_NAME,
783 case TF_IDENT_TYPE_PROF_FUNC:
784 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
785 TF_PROF_FUNC_POOL_NAME,
788 case TF_IDENT_TYPE_EM_PROF:
789 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
790 TF_EM_PROF_ID_POOL_NAME,
793 case TF_IDENT_TYPE_WC_PROF:
794 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
795 TF_WC_TCAM_PROF_ID_POOL_NAME,
798 case TF_IDENT_TYPE_L2_FUNC:
799 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
800 tf_dir_2_str(parms->dir),
801 tf_ident_2_str(parms->ident_type));
805 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
806 tf_dir_2_str(parms->dir),
807 tf_ident_2_str(parms->ident_type));
812 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
813 tf_dir_2_str(parms->dir),
814 tf_ident_2_str(parms->ident_type));
818 ba_rc = ba_inuse(session_pool, (int)parms->id);
820 if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
821 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
822 tf_dir_2_str(parms->dir),
823 tf_ident_2_str(parms->ident_type),
828 ba_free(session_pool, (int)parms->id);
834 tf_free_identifier_new(struct tf *tfp,
835 struct tf_free_identifier_parms *parms)
838 struct tf_session *tfs;
839 struct tf_dev_info *dev;
840 struct tf_ident_free_parms fparms;
842 TF_CHECK_PARMS2(tfp, parms);
844 /* Can't do static initialization due to UT enum check */
845 memset(&fparms, 0, sizeof(struct tf_ident_free_parms));
847 /* Retrieve the session information */
848 rc = tf_session_get_session(tfp, &tfs);
851 "%s: Failed to lookup session, rc:%s\n",
852 tf_dir_2_str(parms->dir),
857 /* Retrieve the device information */
858 rc = tf_session_get_device(tfs, &dev);
861 "%s: Failed to lookup device, rc:%s\n",
862 tf_dir_2_str(parms->dir),
867 if (dev->ops->tf_dev_free_ident == NULL) {
870 "%s: Operation not supported, rc:%s\n",
871 tf_dir_2_str(parms->dir),
876 fparms.dir = parms->dir;
877 fparms.ident_type = parms->ident_type;
878 fparms.id = parms->id;
879 rc = dev->ops->tf_dev_free_ident(tfp, &fparms);
882 "%s: Identifier allocation failed, rc:%s\n",
883 tf_dir_2_str(parms->dir),
892 tf_alloc_tcam_entry(struct tf *tfp,
893 struct tf_alloc_tcam_entry_parms *parms)
897 struct tf_session *tfs;
898 struct bitalloc *session_pool;
900 if (parms == NULL || tfp == NULL)
903 if (tfp->session == NULL || tfp->session->core_data == NULL) {
904 PMD_DRV_LOG(ERR, "%s: session error\n",
905 tf_dir_2_str(parms->dir));
909 tfs = (struct tf_session *)(tfp->session->core_data);
911 rc = tf_rm_lookup_tcam_type_pool(tfs,
913 parms->tcam_tbl_type,
915 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
920 * priority 0: allocate from top of the tcam i.e. high
921 * priority !0: allocate index from bottom i.e lowest
923 if (parms->priority) {
924 for (index = session_pool->size - 1; index >= 0; index--) {
925 if (ba_inuse(session_pool,
926 index) == BA_ENTRY_FREE) {
930 if (ba_alloc_index(session_pool,
933 "%s: %s: ba_alloc index %d failed\n",
934 tf_dir_2_str(parms->dir),
935 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
940 index = ba_alloc(session_pool);
941 if (index == BA_FAIL) {
942 TFP_DRV_LOG(ERR, "%s: %s: Out of resource\n",
943 tf_dir_2_str(parms->dir),
944 tf_tcam_tbl_2_str(parms->tcam_tbl_type));
954 tf_set_tcam_entry(struct tf *tfp,
955 struct tf_set_tcam_entry_parms *parms)
959 struct tf_session *tfs;
960 struct bitalloc *session_pool;
962 if (tfp == NULL || parms == NULL) {
963 PMD_DRV_LOG(ERR, "Invalid parameters\n");
967 if (tfp->session == NULL || tfp->session->core_data == NULL) {
969 "%s, Session info invalid\n",
970 tf_dir_2_str(parms->dir));
974 tfs = (struct tf_session *)(tfp->session->core_data);
977 * Each tcam send msg function should check for key sizes range
980 rc = tf_rm_lookup_tcam_type_pool(tfs,
982 parms->tcam_tbl_type,
984 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
989 /* Verify that the entry has been previously allocated */
990 id = ba_inuse(session_pool, parms->idx);
993 "%s: %s: Invalid or not allocated index, idx:%d\n",
994 tf_dir_2_str(parms->dir),
995 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1000 rc = tf_msg_tcam_entry_set(tfp, parms);
1006 tf_get_tcam_entry(struct tf *tfp __rte_unused,
1007 struct tf_get_tcam_entry_parms *parms __rte_unused)
1009 int rc = -EOPNOTSUPP;
1011 if (tfp == NULL || parms == NULL) {
1012 PMD_DRV_LOG(ERR, "Invalid parameters\n");
1016 if (tfp->session == NULL || tfp->session->core_data == NULL) {
1018 "%s, Session info invalid\n",
1019 tf_dir_2_str(parms->dir));
1027 tf_free_tcam_entry(struct tf *tfp,
1028 struct tf_free_tcam_entry_parms *parms)
1031 struct tf_session *tfs;
1032 struct bitalloc *session_pool;
1034 if (parms == NULL || tfp == NULL)
1037 if (tfp->session == NULL || tfp->session->core_data == NULL) {
1038 PMD_DRV_LOG(ERR, "%s: Session error\n",
1039 tf_dir_2_str(parms->dir));
1043 tfs = (struct tf_session *)(tfp->session->core_data);
1045 rc = tf_rm_lookup_tcam_type_pool(tfs,
1047 parms->tcam_tbl_type,
1049 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1053 rc = ba_inuse(session_pool, (int)parms->idx);
1054 if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
1055 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
1056 tf_dir_2_str(parms->dir),
1057 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1062 ba_free(session_pool, (int)parms->idx);
1064 rc = tf_msg_tcam_entry_free(tfp, parms);
1067 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
1068 tf_dir_2_str(parms->dir),
1069 tf_tcam_tbl_2_str(parms->tcam_tbl_type),