1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
10 #include "tf_session.h"
20 static inline uint32_t SWAP_WORDS32(uint32_t val32)
22 return (((val32 & 0x0000ffff) << 16) |
23 ((val32 & 0xffff0000) >> 16));
26 static void tf_seeds_init(struct tf_session *session)
31 /* Initialize the lfsr */
34 /* RX and TX use the same seed values */
35 session->lkup_lkup3_init_cfg[TF_DIR_RX] =
36 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
37 SWAP_WORDS32(rand32());
39 for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
40 r = SWAP_WORDS32(rand32());
41 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
42 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
43 r = SWAP_WORDS32(rand32());
44 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
45 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
50 * Create EM Tbl pool of memory indexes.
57 * number of entries to write
60 * 0 - Success, entry allocated - no search support
61 * -ENOMEM -EINVAL -EOPNOTSUPP
62 * - Failure, entry not allocated, out of resources
65 tf_create_em_pool(struct tf_session *session,
69 struct tfp_calloc_parms parms;
72 struct stack *pool = &session->em_pool[dir];
74 parms.nitems = num_entries;
75 parms.size = sizeof(uint32_t);
78 if (tfp_calloc(&parms) != 0) {
79 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
86 rc = stack_init(num_entries, parms.mem_va, pool);
89 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
94 /* Fill pool with indexes
98 for (i = 0; i < num_entries; i++) {
99 rc = stack_push(pool, j);
101 TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
108 if (!stack_is_full(pool)) {
110 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
117 tfp_free((void *)parms.mem_va);
122 * Create EM Tbl pool of memory indexes.
132 tf_free_em_pool(struct tf_session *session,
135 struct stack *pool = &session->em_pool[dir];
138 ptr = stack_items(pool);
144 tf_open_session(struct tf *tfp,
145 struct tf_open_session_parms *parms)
148 struct tf_session *session;
149 struct tfp_calloc_parms alloc_parms;
150 unsigned int domain, bus, slot, device;
151 uint8_t fw_session_id;
154 if (tfp == NULL || parms == NULL)
157 /* Filter out any non-supported device types on the Core
158 * side. It is assumed that the Firmware will be supported if
159 * firmware open session succeeds.
161 if (parms->device_type != TF_DEVICE_TYPE_WH)
164 /* Build the beginning of session_id */
165 rc = sscanf(parms->ctrl_chan_name,
173 "Failed to scan device ctrl_chan_name\n");
177 /* open FW session and get a new session_id */
178 rc = tf_msg_session_open(tfp,
179 parms->ctrl_chan_name,
185 "Session is already open, rc:%d\n",
189 "Open message send failed, rc:%d\n",
192 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
196 /* Allocate session */
197 alloc_parms.nitems = 1;
198 alloc_parms.size = sizeof(struct tf_session_info);
199 alloc_parms.alignment = 0;
200 rc = tfp_calloc(&alloc_parms);
204 "Failed to allocate session info, rc:%d\n",
209 tfp->session = alloc_parms.mem_va;
211 /* Allocate core data for the session */
212 alloc_parms.nitems = 1;
213 alloc_parms.size = sizeof(struct tf_session);
214 alloc_parms.alignment = 0;
215 rc = tfp_calloc(&alloc_parms);
219 "Failed to allocate session data, rc:%d\n",
224 tfp->session->core_data = alloc_parms.mem_va;
226 session = (struct tf_session *)tfp->session->core_data;
227 tfp_memcpy(session->ctrl_chan_name,
228 parms->ctrl_chan_name,
229 TF_SESSION_NAME_MAX);
231 /* Initialize Session */
232 session->device_type = parms->device_type;
236 /* Construct the Session ID */
237 session->session_id.internal.domain = domain;
238 session->session_id.internal.bus = bus;
239 session->session_id.internal.device = device;
240 session->session_id.internal.fw_session_id = fw_session_id;
242 rc = tf_msg_session_qcfg(tfp);
246 "Query config message send failed, rc:%d\n",
251 /* Shadow DB configuration */
252 if (parms->shadow_copy) {
253 /* Ignore shadow_copy setting */
254 session->shadow_copy = 0;/* parms->shadow_copy; */
256 rc = tf_rm_shadow_db_init(tfs);
259 "Shadow DB Initialization failed\n, rc:%d",
261 /* Add additional processing */
262 #endif /* TF_SHADOW */
265 /* Adjust the Session with what firmware allowed us to get */
266 rc = tf_rm_allocate_validate(tfp);
272 /* Setup hash seeds */
273 tf_seeds_init(session);
275 /* Initialize EM pool */
276 for (dir = 0; dir < TF_DIR_MAX; dir++) {
277 rc = tf_create_em_pool(session, dir, TF_SESSION_EM_POOL_SIZE);
280 "EM Pool initialization failed\n");
285 session->ref_count++;
287 /* Return session ID */
288 parms->session_id = session->session_id;
291 "Session created, session_id:%d\n",
292 parms->session_id.id);
295 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
296 parms->session_id.internal.domain,
297 parms->session_id.internal.bus,
298 parms->session_id.internal.device,
299 parms->session_id.internal.fw_session_id);
304 tfp_free(tfp->session->core_data);
305 tfp_free(tfp->session);
310 tf_close_session(tfp);
315 tf_attach_session(struct tf *tfp __rte_unused,
316 struct tf_attach_session_parms *parms __rte_unused)
324 /* - Open the shared memory for the attach_chan_name
325 * - Point to the shared session for this Device instance
326 * - Check that session is valid
327 * - Attach to the firmware so it can record there is more
328 * than one client of the session.
332 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
333 rc = tf_msg_session_attach(tfp,
334 parms->ctrl_chan_name,
338 #endif /* TF_SHARED */
343 tf_close_session(struct tf *tfp)
347 struct tf_session *tfs;
348 union tf_session_id session_id;
351 if (tfp == NULL || tfp->session == NULL)
354 tfs = (struct tf_session *)(tfp->session->core_data);
356 /* Cleanup if we're last user of the session */
357 if (tfs->ref_count == 1) {
358 /* Cleanup any outstanding resources */
359 rc_close = tf_rm_close(tfp);
362 if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
363 rc = tf_msg_session_close(tfp);
367 "Message send failed, rc:%d\n",
371 /* Update the ref_count */
375 session_id = tfs->session_id;
377 /* Final cleanup as we're last user of the session */
378 if (tfs->ref_count == 0) {
380 for (dir = 0; dir < TF_DIR_MAX; dir++)
381 tf_free_em_pool(tfs, dir);
383 tfp_free(tfp->session->core_data);
384 tfp_free(tfp->session);
389 "Session closed, session_id:%d\n",
393 "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
394 session_id.internal.domain,
395 session_id.internal.bus,
396 session_id.internal.device,
397 session_id.internal.fw_session_id);
402 /** insert EM hash entry API
408 int tf_insert_em_entry(struct tf *tfp,
409 struct tf_insert_em_entry_parms *parms)
411 struct tf_tbl_scope_cb *tbl_scope_cb;
413 if (tfp == NULL || parms == NULL)
416 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
417 (tfp->session->core_data),
418 parms->tbl_scope_id);
419 if (tbl_scope_cb == NULL)
422 /* Process the EM entry per Table Scope type */
423 if (parms->mem == TF_MEM_EXTERNAL) {
425 return tf_insert_eem_entry((struct tf_session *)
426 (tfp->session->core_data),
429 } else if (parms->mem == TF_MEM_INTERNAL) {
431 return tf_insert_em_internal_entry(tfp, parms);
437 /** Delete EM hash entry API
443 int tf_delete_em_entry(struct tf *tfp,
444 struct tf_delete_em_entry_parms *parms)
446 struct tf_tbl_scope_cb *tbl_scope_cb;
448 if (tfp == NULL || parms == NULL)
451 tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
452 (tfp->session->core_data),
453 parms->tbl_scope_id);
454 if (tbl_scope_cb == NULL)
457 if (parms->mem == TF_MEM_EXTERNAL)
458 return tf_delete_eem_entry(tfp, parms);
460 return tf_delete_em_internal_entry(tfp, parms);
463 /** allocate identifier resource
465 * Returns success or failure code.
467 int tf_alloc_identifier(struct tf *tfp,
468 struct tf_alloc_identifier_parms *parms)
470 struct bitalloc *session_pool;
471 struct tf_session *tfs;
475 if (parms == NULL || tfp == NULL)
478 if (tfp->session == NULL || tfp->session->core_data == NULL) {
479 PMD_DRV_LOG(ERR, "%s: session error\n",
480 tf_dir_2_str(parms->dir));
484 tfs = (struct tf_session *)(tfp->session->core_data);
486 switch (parms->ident_type) {
487 case TF_IDENT_TYPE_L2_CTXT:
488 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
489 TF_L2_CTXT_REMAP_POOL_NAME,
492 case TF_IDENT_TYPE_PROF_FUNC:
493 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
494 TF_PROF_FUNC_POOL_NAME,
497 case TF_IDENT_TYPE_EM_PROF:
498 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
499 TF_EM_PROF_ID_POOL_NAME,
502 case TF_IDENT_TYPE_WC_PROF:
503 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
504 TF_WC_TCAM_PROF_ID_POOL_NAME,
507 case TF_IDENT_TYPE_L2_FUNC:
508 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
509 tf_dir_2_str(parms->dir),
510 tf_ident_2_str(parms->ident_type));
514 PMD_DRV_LOG(ERR, "%s: %s\n",
515 tf_dir_2_str(parms->dir),
516 tf_ident_2_str(parms->ident_type));
522 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
523 tf_dir_2_str(parms->dir),
524 tf_ident_2_str(parms->ident_type));
528 id = ba_alloc(session_pool);
531 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
532 tf_dir_2_str(parms->dir),
533 tf_ident_2_str(parms->ident_type));
540 /** free identifier resource
542 * Returns success or failure code.
544 int tf_free_identifier(struct tf *tfp,
545 struct tf_free_identifier_parms *parms)
547 struct bitalloc *session_pool;
550 struct tf_session *tfs;
552 if (parms == NULL || tfp == NULL)
555 if (tfp->session == NULL || tfp->session->core_data == NULL) {
556 PMD_DRV_LOG(ERR, "%s: Session error\n",
557 tf_dir_2_str(parms->dir));
561 tfs = (struct tf_session *)(tfp->session->core_data);
563 switch (parms->ident_type) {
564 case TF_IDENT_TYPE_L2_CTXT:
565 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
566 TF_L2_CTXT_REMAP_POOL_NAME,
569 case TF_IDENT_TYPE_PROF_FUNC:
570 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
571 TF_PROF_FUNC_POOL_NAME,
574 case TF_IDENT_TYPE_EM_PROF:
575 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
576 TF_EM_PROF_ID_POOL_NAME,
579 case TF_IDENT_TYPE_WC_PROF:
580 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
581 TF_WC_TCAM_PROF_ID_POOL_NAME,
584 case TF_IDENT_TYPE_L2_FUNC:
585 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
586 tf_dir_2_str(parms->dir),
587 tf_ident_2_str(parms->ident_type));
591 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
592 tf_dir_2_str(parms->dir),
593 tf_ident_2_str(parms->ident_type));
598 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
599 tf_dir_2_str(parms->dir),
600 tf_ident_2_str(parms->ident_type));
604 ba_rc = ba_inuse(session_pool, (int)parms->id);
606 if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
607 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
608 tf_dir_2_str(parms->dir),
609 tf_ident_2_str(parms->ident_type),
614 ba_free(session_pool, (int)parms->id);
620 tf_alloc_tcam_entry(struct tf *tfp,
621 struct tf_alloc_tcam_entry_parms *parms)
625 struct tf_session *tfs;
626 struct bitalloc *session_pool;
628 if (parms == NULL || tfp == NULL)
631 if (tfp->session == NULL || tfp->session->core_data == NULL) {
632 PMD_DRV_LOG(ERR, "%s: session error\n",
633 tf_dir_2_str(parms->dir));
637 tfs = (struct tf_session *)(tfp->session->core_data);
639 rc = tf_rm_lookup_tcam_type_pool(tfs,
641 parms->tcam_tbl_type,
643 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
647 index = ba_alloc(session_pool);
648 if (index == BA_FAIL) {
649 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
650 tf_dir_2_str(parms->dir),
651 tf_tcam_tbl_2_str(parms->tcam_tbl_type));
660 tf_set_tcam_entry(struct tf *tfp,
661 struct tf_set_tcam_entry_parms *parms)
665 struct tf_session *tfs;
666 struct bitalloc *session_pool;
668 if (tfp == NULL || parms == NULL) {
669 PMD_DRV_LOG(ERR, "Invalid parameters\n");
673 if (tfp->session == NULL || tfp->session->core_data == NULL) {
675 "%s, Session info invalid\n",
676 tf_dir_2_str(parms->dir));
680 tfs = (struct tf_session *)(tfp->session->core_data);
683 * Each tcam send msg function should check for key sizes range
686 rc = tf_rm_lookup_tcam_type_pool(tfs,
688 parms->tcam_tbl_type,
690 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
695 /* Verify that the entry has been previously allocated */
696 id = ba_inuse(session_pool, parms->idx);
699 "%s: %s: Invalid or not allocated index, idx:%d\n",
700 tf_dir_2_str(parms->dir),
701 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
706 rc = tf_msg_tcam_entry_set(tfp, parms);
712 tf_get_tcam_entry(struct tf *tfp __rte_unused,
713 struct tf_get_tcam_entry_parms *parms __rte_unused)
715 int rc = -EOPNOTSUPP;
717 if (tfp == NULL || parms == NULL) {
718 PMD_DRV_LOG(ERR, "Invalid parameters\n");
722 if (tfp->session == NULL || tfp->session->core_data == NULL) {
724 "%s, Session info invalid\n",
725 tf_dir_2_str(parms->dir));
733 tf_free_tcam_entry(struct tf *tfp,
734 struct tf_free_tcam_entry_parms *parms)
737 struct tf_session *tfs;
738 struct bitalloc *session_pool;
740 if (parms == NULL || tfp == NULL)
743 if (tfp->session == NULL || tfp->session->core_data == NULL) {
744 PMD_DRV_LOG(ERR, "%s: Session error\n",
745 tf_dir_2_str(parms->dir));
749 tfs = (struct tf_session *)(tfp->session->core_data);
751 rc = tf_rm_lookup_tcam_type_pool(tfs,
753 parms->tcam_tbl_type,
755 /* Error logging handled by tf_rm_lookup_tcam_type_pool */
759 rc = ba_inuse(session_pool, (int)parms->idx);
760 if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
761 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
762 tf_dir_2_str(parms->dir),
763 tf_tcam_tbl_2_str(parms->tcam_tbl_type),
768 ba_free(session_pool, (int)parms->idx);
770 rc = tf_msg_tcam_entry_free(tfp, parms);
773 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
774 tf_dir_2_str(parms->dir),
775 tf_tcam_tbl_2_str(parms->tcam_tbl_type),