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 int tf_check_tcam_entry(enum tf_tcam_tbl_type tcam_tbl_type,
23 enum tf_device_type device,
24 uint16_t key_sz_in_bits,
25 uint16_t *num_slice_per_row)
28 uint16_t slice_sz = 0;
30 #define CFA_P4_WC_TCAM_SLICES_PER_ROW 2
31 #define CFA_P4_WC_TCAM_SLICE_SIZE 12
33 if (tcam_tbl_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
34 key_bytes = TF_BITS2BYTES_WORD_ALIGN(key_sz_in_bits);
35 if (device == TF_DEVICE_TYPE_WH) {
36 slice_sz = CFA_P4_WC_TCAM_SLICE_SIZE;
37 *num_slice_per_row = CFA_P4_WC_TCAM_SLICES_PER_ROW;
40 "Unsupported device type %d\n",
45 if (key_bytes > *num_slice_per_row * slice_sz) {
47 "%s: Key size %d is not supported\n",
48 tf_tcam_tbl_2_str(tcam_tbl_type),
52 } else { /* for other type of tcam */
53 *num_slice_per_row = 1;
60 * Create EM Tbl pool of memory indexes.
67 * number of entries to write
70 * 0 - Success, entry allocated - no search support
71 * -ENOMEM -EINVAL -EOPNOTSUPP
72 * - Failure, entry not allocated, out of resources
75 tf_create_em_pool(struct tf_session *session,
79 struct tfp_calloc_parms parms;
82 struct stack *pool = &session->em_pool[dir];
84 parms.nitems = num_entries;
85 parms.size = sizeof(uint32_t);
88 if (tfp_calloc(&parms) != 0) {
89 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
96 rc = stack_init(num_entries, (uint32_t *)parms.mem_va, pool);
99 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
104 /* Fill pool with indexes
108 for (i = 0; i < num_entries; i++) {
109 rc = stack_push(pool, j);
111 TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
118 if (!stack_is_full(pool)) {
120 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
127 tfp_free((void *)parms.mem_va);
132 * Create EM Tbl pool of memory indexes.
142 tf_free_em_pool(struct tf_session *session,
145 struct stack *pool = &session->em_pool[dir];
148 ptr = stack_items(pool);
154 tf_open_session(struct tf *tfp,
155 struct tf_open_session_parms *parms)
158 struct tf_session *session;
159 struct tfp_calloc_parms alloc_parms;
160 unsigned int domain, bus, slot, device;
161 uint8_t fw_session_id;
164 TF_CHECK_PARMS(tfp, parms);
166 /* Filter out any non-supported device types on the Core
167 * side. It is assumed that the Firmware will be supported if
168 * firmware open session succeeds.
170 if (parms->device_type != TF_DEVICE_TYPE_WH) {
172 "Unsupported device type %d\n",
177 /* Build the beginning of session_id */
178 rc = sscanf(parms->ctrl_chan_name,
186 "Failed to scan device ctrl_chan_name\n");
190 /* open FW session and get a new session_id */
191 rc = tf_msg_session_open(tfp,
192 parms->ctrl_chan_name,
198 "Session is already open, rc:%s\n",
202 "Open message send failed, rc:%s\n",
205 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
209 /* Allocate session */
210 alloc_parms.nitems = 1;
211 alloc_parms.size = sizeof(struct tf_session_info);
212 alloc_parms.alignment = 0;
213 rc = tfp_calloc(&alloc_parms);
217 "Failed to allocate session info, rc:%s\n",
222 tfp->session = (struct tf_session_info *)alloc_parms.mem_va;
224 /* Allocate core data for the session */
225 alloc_parms.nitems = 1;
226 alloc_parms.size = sizeof(struct tf_session);
227 alloc_parms.alignment = 0;
228 rc = tfp_calloc(&alloc_parms);
232 "Failed to allocate session data, rc:%s\n",
237 tfp->session->core_data = alloc_parms.mem_va;
239 session = (struct tf_session *)tfp->session->core_data;
240 tfp_memcpy(session->ctrl_chan_name,
241 parms->ctrl_chan_name,
242 TF_SESSION_NAME_MAX);
244 /* Initialize Session */
248 /* Construct the Session ID */
249 session->session_id.internal.domain = domain;
250 session->session_id.internal.bus = bus;
251 session->session_id.internal.device = device;
252 session->session_id.internal.fw_session_id = fw_session_id;
254 /* Query for Session Config
256 rc = tf_msg_session_qcfg(tfp);
259 "Query config message send failed, rc:%s\n",
264 /* Shadow DB configuration */
265 if (parms->shadow_copy) {
266 /* Ignore shadow_copy setting */
267 session->shadow_copy = 0;/* parms->shadow_copy; */
269 rc = tf_rm_shadow_db_init(tfs);
272 "Shadow DB Initialization failed\n, rc:%s",
274 /* Add additional processing */
275 #endif /* TF_SHADOW */
278 /* Adjust the Session with what firmware allowed us to get */
279 rc = tf_rm_allocate_validate(tfp);
282 "Rm allocate validate failed, rc:%s\n",
287 /* Initialize EM pool */
288 for (dir = 0; dir < TF_DIR_MAX; dir++) {
289 rc = tf_create_em_pool(session,
291 TF_SESSION_EM_POOL_SIZE);
294 "EM Pool initialization failed\n");
299 session->ref_count++;
301 /* Return session ID */
302 parms->session_id = session->session_id;
305 "Session created, session_id:%d\n",
306 parms->session_id.id);
309 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
310 parms->session_id.internal.domain,
311 parms->session_id.internal.bus,
312 parms->session_id.internal.device,
313 parms->session_id.internal.fw_session_id);
318 tfp_free(tfp->session->core_data);
319 tfp_free(tfp->session);
324 tf_close_session(tfp);
329 tf_open_session_new(struct tf *tfp,
330 struct tf_open_session_parms *parms)
333 unsigned int domain, bus, slot, device;
334 struct tf_session_open_session_parms oparms;
336 TF_CHECK_PARMS(tfp, parms);
338 /* Filter out any non-supported device types on the Core
339 * side. It is assumed that the Firmware will be supported if
340 * firmware open session succeeds.
342 if (parms->device_type != TF_DEVICE_TYPE_WH) {
344 "Unsupported device type %d\n",
349 /* Verify control channel and build the beginning of session_id */
350 rc = sscanf(parms->ctrl_chan_name,
358 "Failed to scan device ctrl_chan_name\n");
362 parms->session_id.internal.domain = domain;
363 parms->session_id.internal.bus = bus;
364 parms->session_id.internal.device = device;
365 oparms.open_cfg = parms;
367 rc = tf_session_open_session(tfp, &oparms);
368 /* Logging handled by tf_session_open_session */
373 "Session created, session_id:%d\n",
374 parms->session_id.id);
377 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
378 parms->session_id.internal.domain,
379 parms->session_id.internal.bus,
380 parms->session_id.internal.device,
381 parms->session_id.internal.fw_session_id);
387 tf_attach_session(struct tf *tfp __rte_unused,
388 struct tf_attach_session_parms *parms __rte_unused)
393 TF_CHECK_PARMS_SESSION(tfp, parms);
395 /* - Open the shared memory for the attach_chan_name
396 * - Point to the shared session for this Device instance
397 * - Check that session is valid
398 * - Attach to the firmware so it can record there is more
399 * than one client of the session.
402 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
403 rc = tf_msg_session_attach(tfp,
404 parms->ctrl_chan_name,
407 #endif /* TF_SHARED */
412 tf_attach_session_new(struct tf *tfp,
413 struct tf_attach_session_parms *parms)
416 unsigned int domain, bus, slot, device;
417 struct tf_session_attach_session_parms aparms;
419 TF_CHECK_PARMS2(tfp, parms);
421 /* Verify control channel */
422 rc = sscanf(parms->ctrl_chan_name,
430 "Failed to scan device ctrl_chan_name\n");
434 /* Verify 'attach' channel */
435 rc = sscanf(parms->attach_chan_name,
443 "Failed to scan device attach_chan_name\n");
447 /* Prepare return value of session_id, using ctrl_chan_name
448 * device values as it becomes the session id.
450 parms->session_id.internal.domain = domain;
451 parms->session_id.internal.bus = bus;
452 parms->session_id.internal.device = device;
453 aparms.attach_cfg = parms;
454 rc = tf_session_attach_session(tfp,
456 /* Logging handled by dev_bind */
461 "Attached to session, session_id:%d\n",
462 parms->session_id.id);
465 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
466 parms->session_id.internal.domain,
467 parms->session_id.internal.bus,
468 parms->session_id.internal.device,
469 parms->session_id.internal.fw_session_id);
475 tf_close_session(struct tf *tfp)
479 struct tf_session *tfs;
480 union tf_session_id session_id;
483 TF_CHECK_TFP_SESSION(tfp);
485 tfs = (struct tf_session *)(tfp->session->core_data);
487 /* Cleanup if we're last user of the session */
488 if (tfs->ref_count == 1) {
489 /* Cleanup any outstanding resources */
490 rc_close = tf_rm_close(tfp);
493 if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
494 rc = tf_msg_session_close(tfp);
498 "Message send failed, rc:%s\n",
502 /* Update the ref_count */
506 session_id = tfs->session_id;
508 /* Final cleanup as we're last user of the session */
509 if (tfs->ref_count == 0) {
511 for (dir = 0; dir < TF_DIR_MAX; dir++)
512 tf_free_em_pool(tfs, (enum tf_dir)dir);
514 tfp_free(tfp->session->core_data);
515 tfp_free(tfp->session);
520 "Session closed, session_id:%d\n",
524 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
525 session_id.internal.domain,
526 session_id.internal.bus,
527 session_id.internal.device,
528 session_id.internal.fw_session_id);
534 tf_close_session_new(struct tf *tfp)
537 struct tf_session_close_session_parms cparms = { 0 };
538 union tf_session_id session_id = { 0 };
541 TF_CHECK_PARMS1(tfp);
543 cparms.ref_count = &ref_count;
544 cparms.session_id = &session_id;
545 rc = tf_session_close_session(tfp,
547 /* Logging handled by tf_session_close_session */
552 "Closed session, session_id:%d, ref_count:%d\n",
553 cparms.session_id->id,
557 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
558 cparms.session_id->internal.domain,
559 cparms.session_id->internal.bus,
560 cparms.session_id->internal.device,
561 cparms.session_id->internal.fw_session_id);
566 /** insert EM hash entry API
572 int tf_insert_em_entry(struct tf *tfp,
573 struct tf_insert_em_entry_parms *parms)
575 struct tf_session *tfs;
576 struct tf_dev_info *dev;
579 TF_CHECK_PARMS_SESSION(tfp, parms);
581 /* Retrieve the session information */
582 rc = tf_session_get_session(tfp, &tfs);
585 "%s: Failed to lookup session, rc:%s\n",
586 tf_dir_2_str(parms->dir),
591 /* Retrieve the device information */
592 rc = tf_session_get_device(tfs, &dev);
595 "%s: Failed to lookup device, rc:%s\n",
596 tf_dir_2_str(parms->dir),
601 rc = dev->ops->tf_dev_insert_em_entry(tfp, parms);
604 "%s: EM insert failed, rc:%s\n",
605 tf_dir_2_str(parms->dir),
613 /** Delete EM hash entry API
619 int tf_delete_em_entry(struct tf *tfp,
620 struct tf_delete_em_entry_parms *parms)
622 struct tf_session *tfs;
623 struct tf_dev_info *dev;
626 TF_CHECK_PARMS_SESSION(tfp, parms);
628 /* Retrieve the session information */
629 rc = tf_session_get_session(tfp, &tfs);
632 "%s: Failed to lookup session, rc:%s\n",
633 tf_dir_2_str(parms->dir),
638 /* Retrieve the device information */
639 rc = tf_session_get_device(tfs, &dev);
642 "%s: Failed to lookup device, rc:%s\n",
643 tf_dir_2_str(parms->dir),
648 rc = dev->ops->tf_dev_delete_em_entry(tfp, parms);
651 "%s: EM delete failed, rc:%s\n",
652 tf_dir_2_str(parms->dir),
660 int tf_alloc_identifier(struct tf *tfp,
661 struct tf_alloc_identifier_parms *parms)
663 struct bitalloc *session_pool;
664 struct tf_session *tfs;
668 TF_CHECK_PARMS_SESSION(tfp, parms);
670 tfs = (struct tf_session *)(tfp->session->core_data);
672 switch (parms->ident_type) {
673 case TF_IDENT_TYPE_L2_CTXT:
674 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
675 TF_L2_CTXT_REMAP_POOL_NAME,
678 case TF_IDENT_TYPE_PROF_FUNC:
679 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
680 TF_PROF_FUNC_POOL_NAME,
683 case TF_IDENT_TYPE_EM_PROF:
684 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
685 TF_EM_PROF_ID_POOL_NAME,
688 case TF_IDENT_TYPE_WC_PROF:
689 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
690 TF_WC_TCAM_PROF_ID_POOL_NAME,
693 case TF_IDENT_TYPE_L2_FUNC:
694 TFP_DRV_LOG(ERR, "%s: unsupported %s\n",
695 tf_dir_2_str(parms->dir),
696 tf_ident_2_str(parms->ident_type));
700 TFP_DRV_LOG(ERR, "%s: %s\n",
701 tf_dir_2_str(parms->dir),
702 tf_ident_2_str(parms->ident_type));
708 TFP_DRV_LOG(ERR, "%s: identifier pool %s failure, rc:%s\n",
709 tf_dir_2_str(parms->dir),
710 tf_ident_2_str(parms->ident_type),
715 id = ba_alloc(session_pool);
718 TFP_DRV_LOG(ERR, "%s: %s: No resource available\n",
719 tf_dir_2_str(parms->dir),
720 tf_ident_2_str(parms->ident_type));
728 tf_alloc_identifier_new(struct tf *tfp,
729 struct tf_alloc_identifier_parms *parms)
732 struct tf_session *tfs;
733 struct tf_dev_info *dev;
734 struct tf_ident_alloc_parms aparms;
737 TF_CHECK_PARMS2(tfp, parms);
739 /* Can't do static initialization due to UT enum check */
740 memset(&aparms, 0, sizeof(struct tf_ident_alloc_parms));
742 /* Retrieve the session information */
743 rc = tf_session_get_session(tfp, &tfs);
746 "%s: Failed to lookup session, rc:%s\n",
747 tf_dir_2_str(parms->dir),
752 /* Retrieve the device information */
753 rc = tf_session_get_device(tfs, &dev);
756 "%s: Failed to lookup device, rc:%s\n",
757 tf_dir_2_str(parms->dir),
762 if (dev->ops->tf_dev_alloc_ident == NULL) {
765 "%s: Operation not supported, rc:%s\n",
766 tf_dir_2_str(parms->dir),
771 aparms.dir = parms->dir;
772 aparms.ident_type = parms->ident_type;
774 rc = dev->ops->tf_dev_alloc_ident(tfp, &aparms);
777 "%s: Identifier allocation failed, rc:%s\n",
778 tf_dir_2_str(parms->dir),
788 int tf_free_identifier(struct tf *tfp,
789 struct tf_free_identifier_parms *parms)
791 struct bitalloc *session_pool;
794 struct tf_session *tfs;
796 TF_CHECK_PARMS_SESSION(tfp, parms);
798 tfs = (struct tf_session *)(tfp->session->core_data);
800 switch (parms->ident_type) {
801 case TF_IDENT_TYPE_L2_CTXT:
802 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
803 TF_L2_CTXT_REMAP_POOL_NAME,
806 case TF_IDENT_TYPE_PROF_FUNC:
807 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
808 TF_PROF_FUNC_POOL_NAME,
811 case TF_IDENT_TYPE_EM_PROF:
812 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
813 TF_EM_PROF_ID_POOL_NAME,
816 case TF_IDENT_TYPE_WC_PROF:
817 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
818 TF_WC_TCAM_PROF_ID_POOL_NAME,
821 case TF_IDENT_TYPE_L2_FUNC:
822 TFP_DRV_LOG(ERR, "%s: unsupported %s\n",
823 tf_dir_2_str(parms->dir),
824 tf_ident_2_str(parms->ident_type));
828 TFP_DRV_LOG(ERR, "%s: invalid %s\n",
829 tf_dir_2_str(parms->dir),
830 tf_ident_2_str(parms->ident_type));
836 "%s: %s Identifier pool access failed, rc:%s\n",
837 tf_dir_2_str(parms->dir),
838 tf_ident_2_str(parms->ident_type),
843 ba_rc = ba_inuse(session_pool, (int)parms->id);
845 if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
846 TFP_DRV_LOG(ERR, "%s: %s: Entry %d already free",
847 tf_dir_2_str(parms->dir),
848 tf_ident_2_str(parms->ident_type),
853 ba_free(session_pool, (int)parms->id);
859 tf_free_identifier_new(struct tf *tfp,
860 struct tf_free_identifier_parms *parms)
863 struct tf_session *tfs;
864 struct tf_dev_info *dev;
865 struct tf_ident_free_parms fparms;
867 TF_CHECK_PARMS2(tfp, parms);
869 /* Can't do static initialization due to UT enum check */
870 memset(&fparms, 0, sizeof(struct tf_ident_free_parms));
872 /* Retrieve the session information */
873 rc = tf_session_get_session(tfp, &tfs);
876 "%s: Failed to lookup session, rc:%s\n",
877 tf_dir_2_str(parms->dir),
882 /* Retrieve the device information */
883 rc = tf_session_get_device(tfs, &dev);
886 "%s: Failed to lookup device, rc:%s\n",
887 tf_dir_2_str(parms->dir),
892 if (dev->ops->tf_dev_free_ident == NULL) {
895 "%s: Operation not supported, rc:%s\n",
896 tf_dir_2_str(parms->dir),
901 fparms.dir = parms->dir;
902 fparms.ident_type = parms->ident_type;
903 fparms.id = parms->id;
904 rc = dev->ops->tf_dev_free_ident(tfp, &fparms);
907 "%s: Identifier allocation failed, rc:%s\n",
908 tf_dir_2_str(parms->dir),
917 tf_alloc_tcam_entry(struct tf *tfp,
918 struct tf_alloc_tcam_entry_parms *parms)
922 struct tf_session *tfs;
923 struct bitalloc *session_pool;
924 uint16_t num_slice_per_row;
926 /* TEMP, due to device design. When tcam is modularized device
927 * should be retrieved from the session
929 enum tf_device_type device_type;
931 device_type = TF_DEVICE_TYPE_WH;
933 TF_CHECK_PARMS_SESSION(tfp, parms);
935 tfs = (struct tf_session *)(tfp->session->core_data);
937 rc = tf_check_tcam_entry(parms->tcam_tbl_type,
939 parms->key_sz_in_bits,
941 /* Error logging handled by tf_check_tcam_entry */
945 rc = tf_rm_lookup_tcam_type_pool(tfs,
947 parms->tcam_tbl_type,
949 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
953 index = ba_alloc(session_pool);
954 if (index == BA_FAIL) {
955 TFP_DRV_LOG(ERR, "%s: %s: No resource available\n",
956 tf_dir_2_str(parms->dir),
957 tf_tcam_tbl_2_str(parms->tcam_tbl_type));
961 index *= num_slice_per_row;
968 tf_set_tcam_entry(struct tf *tfp,
969 struct tf_set_tcam_entry_parms *parms)
974 struct tf_session *tfs;
975 struct bitalloc *session_pool;
976 uint16_t num_slice_per_row;
978 /* TEMP, due to device design. When tcam is modularized device
979 * should be retrieved from the session
981 enum tf_device_type device_type;
983 device_type = TF_DEVICE_TYPE_WH;
985 TF_CHECK_PARMS_SESSION(tfp, parms);
987 tfs = (struct tf_session *)(tfp->session->core_data);
989 rc = tf_check_tcam_entry(parms->tcam_tbl_type,
991 parms->key_sz_in_bits,
993 /* Error logging handled by tf_check_tcam_entry */
997 rc = tf_rm_lookup_tcam_type_pool(tfs,
999 parms->tcam_tbl_type,
1001 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1005 /* Verify that the entry has been previously allocated */
1006 index = parms->idx / num_slice_per_row;
1008 id = ba_inuse(session_pool, index);
1011 "%s: %s: Invalid or not allocated index, idx:%d\n",
1012 tf_dir_2_str(parms->dir),
1013 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1018 rc = tf_msg_tcam_entry_set(tfp, parms);
1024 tf_get_tcam_entry(struct tf *tfp __rte_unused,
1025 struct tf_get_tcam_entry_parms *parms __rte_unused)
1027 TF_CHECK_PARMS_SESSION(tfp, parms);
1032 tf_free_tcam_entry(struct tf *tfp,
1033 struct tf_free_tcam_entry_parms *parms)
1037 struct tf_session *tfs;
1038 struct bitalloc *session_pool;
1039 uint16_t num_slice_per_row = 1;
1041 /* TEMP, due to device design. When tcam is modularized device
1042 * should be retrieved from the session
1044 enum tf_device_type device_type;
1046 device_type = TF_DEVICE_TYPE_WH;
1048 TF_CHECK_PARMS_SESSION(tfp, parms);
1049 tfs = (struct tf_session *)(tfp->session->core_data);
1051 rc = tf_check_tcam_entry(parms->tcam_tbl_type,
1054 &num_slice_per_row);
1055 /* Error logging handled by tf_check_tcam_entry */
1059 rc = tf_rm_lookup_tcam_type_pool(tfs,
1061 parms->tcam_tbl_type,
1063 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1067 index = parms->idx / num_slice_per_row;
1069 rc = ba_inuse(session_pool, index);
1070 if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
1071 TFP_DRV_LOG(ERR, "%s: %s: Entry %d already free",
1072 tf_dir_2_str(parms->dir),
1073 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1078 ba_free(session_pool, index);
1080 rc = tf_msg_tcam_entry_free(tfp, parms);
1083 TFP_DRV_LOG(ERR, "%s: %s: Entry %d free failed with err %s",
1084 tf_dir_2_str(parms->dir),
1085 tf_tcam_tbl_2_str(parms->tcam_tbl_type),