1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
9 #include "tf_session.h"
19 static inline uint32_t SWAP_WORDS32(uint32_t val32)
21 return (((val32 & 0x0000ffff) << 16) |
22 ((val32 & 0xffff0000) >> 16));
25 static void tf_seeds_init(struct tf_session *session)
30 /* Initialize the lfsr */
33 /* RX and TX use the same seed values */
34 session->lkup_lkup3_init_cfg[TF_DIR_RX] =
35 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
36 SWAP_WORDS32(rand32());
38 for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
39 r = SWAP_WORDS32(rand32());
40 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
41 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
42 r = SWAP_WORDS32(rand32());
43 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
44 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
49 * Create EM Tbl pool of memory indexes.
56 * number of entries to write
59 * 0 - Success, entry allocated - no search support
60 * -ENOMEM -EINVAL -EOPNOTSUPP
61 * - Failure, entry not allocated, out of resources
64 tf_create_em_pool(struct tf_session *session,
68 struct tfp_calloc_parms parms;
71 struct stack *pool = &session->em_pool[dir];
73 parms.nitems = num_entries;
74 parms.size = sizeof(uint32_t);
77 if (tfp_calloc(&parms) != 0) {
78 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
85 rc = stack_init(num_entries, parms.mem_va, pool);
88 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
93 /* Fill pool with indexes
97 for (i = 0; i < num_entries; i++) {
98 rc = stack_push(pool, j);
100 TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
107 if (!stack_is_full(pool)) {
109 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
116 tfp_free((void *)parms.mem_va);
121 * Create EM Tbl pool of memory indexes.
131 tf_free_em_pool(struct tf_session *session,
134 struct stack *pool = &session->em_pool[dir];
137 ptr = stack_items(pool);
143 tf_open_session(struct tf *tfp,
144 struct tf_open_session_parms *parms)
147 struct tf_session *session;
148 struct tfp_calloc_parms alloc_parms;
149 unsigned int domain, bus, slot, device;
150 uint8_t fw_session_id;
153 if (tfp == NULL || parms == NULL)
156 /* Filter out any non-supported device types on the Core
157 * side. It is assumed that the Firmware will be supported if
158 * firmware open session succeeds.
160 if (parms->device_type != TF_DEVICE_TYPE_WH)
163 /* Build the beginning of session_id */
164 rc = sscanf(parms->ctrl_chan_name,
172 "Failed to scan device ctrl_chan_name\n");
176 /* open FW session and get a new session_id */
177 rc = tf_msg_session_open(tfp,
178 parms->ctrl_chan_name,
184 "Session is already open, rc:%d\n",
188 "Open message send failed, rc:%d\n",
191 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
195 /* Allocate session */
196 alloc_parms.nitems = 1;
197 alloc_parms.size = sizeof(struct tf_session_info);
198 alloc_parms.alignment = 0;
199 rc = tfp_calloc(&alloc_parms);
203 "Failed to allocate session info, rc:%d\n",
208 tfp->session = alloc_parms.mem_va;
210 /* Allocate core data for the session */
211 alloc_parms.nitems = 1;
212 alloc_parms.size = sizeof(struct tf_session);
213 alloc_parms.alignment = 0;
214 rc = tfp_calloc(&alloc_parms);
218 "Failed to allocate session data, rc:%d\n",
223 tfp->session->core_data = alloc_parms.mem_va;
225 session = (struct tf_session *)tfp->session->core_data;
226 tfp_memcpy(session->ctrl_chan_name,
227 parms->ctrl_chan_name,
228 TF_SESSION_NAME_MAX);
230 /* Initialize Session */
231 session->device_type = parms->device_type;
234 /* Construct the Session ID */
235 session->session_id.internal.domain = domain;
236 session->session_id.internal.bus = bus;
237 session->session_id.internal.device = device;
238 session->session_id.internal.fw_session_id = fw_session_id;
240 rc = tf_msg_session_qcfg(tfp);
244 "Query config message send failed, rc:%d\n",
249 /* Shadow DB configuration */
250 if (parms->shadow_copy) {
251 /* Ignore shadow_copy setting */
252 session->shadow_copy = 0;/* parms->shadow_copy; */
254 rc = tf_rm_shadow_db_init(tfs);
257 "Shadow DB Initialization failed\n, rc:%d",
259 /* Add additional processing */
260 #endif /* TF_SHADOW */
263 /* Adjust the Session with what firmware allowed us to get */
264 rc = tf_rm_allocate_validate(tfp);
270 /* Setup hash seeds */
271 tf_seeds_init(session);
273 /* Initialize EM pool */
274 for (dir = 0; dir < TF_DIR_MAX; dir++) {
275 rc = tf_create_em_pool(session, dir, TF_SESSION_EM_POOL_SIZE);
278 "EM Pool initialization failed\n");
283 session->ref_count++;
285 /* Return session ID */
286 parms->session_id = session->session_id;
289 "Session created, session_id:%d\n",
290 parms->session_id.id);
293 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
294 parms->session_id.internal.domain,
295 parms->session_id.internal.bus,
296 parms->session_id.internal.device,
297 parms->session_id.internal.fw_session_id);
302 tfp_free(tfp->session->core_data);
303 tfp_free(tfp->session);
308 tf_close_session(tfp);
313 tf_attach_session(struct tf *tfp __rte_unused,
314 struct tf_attach_session_parms *parms __rte_unused)
322 /* - Open the shared memory for the attach_chan_name
323 * - Point to the shared session for this Device instance
324 * - Check that session is valid
325 * - Attach to the firmware so it can record there is more
326 * than one client of the session.
330 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
331 rc = tf_msg_session_attach(tfp,
332 parms->ctrl_chan_name,
336 #endif /* TF_SHARED */
341 tf_close_session(struct tf *tfp)
345 struct tf_session *tfs;
346 union tf_session_id session_id;
349 if (tfp == NULL || tfp->session == NULL)
352 tfs = (struct tf_session *)(tfp->session->core_data);
354 /* Cleanup if we're last user of the session */
355 if (tfs->ref_count == 1) {
356 /* Cleanup any outstanding resources */
357 rc_close = tf_rm_close(tfp);
360 if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
361 rc = tf_msg_session_close(tfp);
365 "Message send failed, rc:%d\n",
369 /* Update the ref_count */
373 session_id = tfs->session_id;
375 /* Final cleanup as we're last user of the session */
376 if (tfs->ref_count == 0) {
378 for (dir = 0; dir < TF_DIR_MAX; dir++)
379 tf_free_em_pool(tfs, dir);
381 tfp_free(tfp->session->core_data);
382 tfp_free(tfp->session);
387 "Session closed, session_id:%d\n",
391 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
392 session_id.internal.domain,
393 session_id.internal.bus,
394 session_id.internal.device,
395 session_id.internal.fw_session_id);
400 /** insert EM hash entry API
406 int tf_insert_em_entry(struct tf *tfp,
407 struct tf_insert_em_entry_parms *parms)
409 struct tf_tbl_scope_cb *tbl_scope_cb;
411 if (tfp == NULL || parms == NULL)
414 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
415 (tfp->session->core_data),
416 parms->tbl_scope_id);
417 if (tbl_scope_cb == NULL)
420 /* Process the EM entry per Table Scope type */
421 if (parms->mem == TF_MEM_EXTERNAL) {
423 return tf_insert_eem_entry((struct tf_session *)
424 (tfp->session->core_data),
427 } else if (parms->mem == TF_MEM_INTERNAL) {
429 return tf_insert_em_internal_entry(tfp, parms);
435 /** Delete EM hash entry API
441 int tf_delete_em_entry(struct tf *tfp,
442 struct tf_delete_em_entry_parms *parms)
444 struct tf_tbl_scope_cb *tbl_scope_cb;
446 if (tfp == NULL || parms == NULL)
449 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
450 (tfp->session->core_data),
451 parms->tbl_scope_id);
452 if (tbl_scope_cb == NULL)
455 if (parms->mem == TF_MEM_EXTERNAL)
456 return tf_delete_eem_entry(tfp, parms);
458 return tf_delete_em_internal_entry(tfp, parms);
461 /** allocate identifier resource
463 * Returns success or failure code.
465 int tf_alloc_identifier(struct tf *tfp,
466 struct tf_alloc_identifier_parms *parms)
468 struct bitalloc *session_pool;
469 struct tf_session *tfs;
473 if (parms == NULL || tfp == NULL)
476 if (tfp->session == NULL || tfp->session->core_data == NULL) {
477 PMD_DRV_LOG(ERR, "%s: session error\n",
478 tf_dir_2_str(parms->dir));
482 tfs = (struct tf_session *)(tfp->session->core_data);
484 switch (parms->ident_type) {
485 case TF_IDENT_TYPE_L2_CTXT:
486 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
487 TF_L2_CTXT_REMAP_POOL_NAME,
490 case TF_IDENT_TYPE_PROF_FUNC:
491 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
492 TF_PROF_FUNC_POOL_NAME,
495 case TF_IDENT_TYPE_EM_PROF:
496 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
497 TF_EM_PROF_ID_POOL_NAME,
500 case TF_IDENT_TYPE_WC_PROF:
501 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
502 TF_WC_TCAM_PROF_ID_POOL_NAME,
505 case TF_IDENT_TYPE_L2_FUNC:
506 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
507 tf_dir_2_str(parms->dir),
508 tf_ident_2_str(parms->ident_type));
512 PMD_DRV_LOG(ERR, "%s: %s\n",
513 tf_dir_2_str(parms->dir),
514 tf_ident_2_str(parms->ident_type));
520 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
521 tf_dir_2_str(parms->dir),
522 tf_ident_2_str(parms->ident_type));
526 id = ba_alloc(session_pool);
529 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
530 tf_dir_2_str(parms->dir),
531 tf_ident_2_str(parms->ident_type));
538 /** free identifier resource
540 * Returns success or failure code.
542 int tf_free_identifier(struct tf *tfp,
543 struct tf_free_identifier_parms *parms)
545 struct bitalloc *session_pool;
548 struct tf_session *tfs;
550 if (parms == NULL || tfp == NULL)
553 if (tfp->session == NULL || tfp->session->core_data == NULL) {
554 PMD_DRV_LOG(ERR, "%s: Session error\n",
555 tf_dir_2_str(parms->dir));
559 tfs = (struct tf_session *)(tfp->session->core_data);
561 switch (parms->ident_type) {
562 case TF_IDENT_TYPE_L2_CTXT:
563 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
564 TF_L2_CTXT_REMAP_POOL_NAME,
567 case TF_IDENT_TYPE_PROF_FUNC:
568 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
569 TF_PROF_FUNC_POOL_NAME,
572 case TF_IDENT_TYPE_EM_PROF:
573 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
574 TF_EM_PROF_ID_POOL_NAME,
577 case TF_IDENT_TYPE_WC_PROF:
578 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
579 TF_WC_TCAM_PROF_ID_POOL_NAME,
582 case TF_IDENT_TYPE_L2_FUNC:
583 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
584 tf_dir_2_str(parms->dir),
585 tf_ident_2_str(parms->ident_type));
589 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
590 tf_dir_2_str(parms->dir),
591 tf_ident_2_str(parms->ident_type));
596 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
597 tf_dir_2_str(parms->dir),
598 tf_ident_2_str(parms->ident_type));
602 ba_rc = ba_inuse(session_pool, (int)parms->id);
604 if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
605 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
606 tf_dir_2_str(parms->dir),
607 tf_ident_2_str(parms->ident_type),
612 ba_free(session_pool, (int)parms->id);
618 tf_alloc_tcam_entry(struct tf *tfp,
619 struct tf_alloc_tcam_entry_parms *parms)
623 struct tf_session *tfs;
624 struct bitalloc *session_pool;
626 if (parms == NULL || tfp == NULL)
629 if (tfp->session == NULL || tfp->session->core_data == NULL) {
630 PMD_DRV_LOG(ERR, "%s: session error\n",
631 tf_dir_2_str(parms->dir));
635 tfs = (struct tf_session *)(tfp->session->core_data);
637 rc = tf_rm_lookup_tcam_type_pool(tfs,
639 parms->tcam_tbl_type,
641 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
645 index = ba_alloc(session_pool);
646 if (index == BA_FAIL) {
647 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
648 tf_dir_2_str(parms->dir),
649 tf_tcam_tbl_2_str(parms->tcam_tbl_type));
658 tf_set_tcam_entry(struct tf *tfp,
659 struct tf_set_tcam_entry_parms *parms)
663 struct tf_session *tfs;
664 struct bitalloc *session_pool;
666 if (tfp == NULL || parms == NULL) {
667 PMD_DRV_LOG(ERR, "Invalid parameters\n");
671 if (tfp->session == NULL || tfp->session->core_data == NULL) {
673 "%s, Session info invalid\n",
674 tf_dir_2_str(parms->dir));
678 tfs = (struct tf_session *)(tfp->session->core_data);
681 * Each tcam send msg function should check for key sizes range
684 rc = tf_rm_lookup_tcam_type_pool(tfs,
686 parms->tcam_tbl_type,
688 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
693 /* Verify that the entry has been previously allocated */
694 id = ba_inuse(session_pool, parms->idx);
697 "%s: %s: Invalid or not allocated index, idx:%d\n",
698 tf_dir_2_str(parms->dir),
699 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
704 rc = tf_msg_tcam_entry_set(tfp, parms);
710 tf_get_tcam_entry(struct tf *tfp __rte_unused,
711 struct tf_get_tcam_entry_parms *parms __rte_unused)
713 int rc = -EOPNOTSUPP;
715 if (tfp == NULL || parms == NULL) {
716 PMD_DRV_LOG(ERR, "Invalid parameters\n");
720 if (tfp->session == NULL || tfp->session->core_data == NULL) {
722 "%s, Session info invalid\n",
723 tf_dir_2_str(parms->dir));
731 tf_free_tcam_entry(struct tf *tfp,
732 struct tf_free_tcam_entry_parms *parms)
735 struct tf_session *tfs;
736 struct bitalloc *session_pool;
738 if (parms == NULL || tfp == NULL)
741 if (tfp->session == NULL || tfp->session->core_data == NULL) {
742 PMD_DRV_LOG(ERR, "%s: Session error\n",
743 tf_dir_2_str(parms->dir));
747 tfs = (struct tf_session *)(tfp->session->core_data);
749 rc = tf_rm_lookup_tcam_type_pool(tfs,
751 parms->tcam_tbl_type,
753 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
757 rc = ba_inuse(session_pool, (int)parms->idx);
758 if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
759 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
760 tf_dir_2_str(parms->dir),
761 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
766 ba_free(session_pool, (int)parms->idx);
768 rc = tf_msg_tcam_entry_free(tfp, parms);
771 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
772 tf_dir_2_str(parms->dir),
773 tf_tcam_tbl_2_str(parms->tcam_tbl_type),