Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <string.h>
7 : : #include <math.h>
8 : : #include <sys/param.h>
9 : : #include <rte_common.h>
10 : : #include <rte_errno.h>
11 : : #include <rte_log.h>
12 : :
13 : : #include "tf_core.h"
14 : : #include "tf_util.h"
15 : : #include "tf_common.h"
16 : : #include "tf_em.h"
17 : : #include "tf_em_common.h"
18 : : #include "tf_msg.h"
19 : : #include "tfp.h"
20 : : #include "lookup3.h"
21 : : #include "tf_ext_flow_handle.h"
22 : :
23 : : #include "bnxt.h"
24 : :
25 : : #define PTU_PTE_VALID 0x1UL
26 : : #define PTU_PTE_LAST 0x2UL
27 : : #define PTU_PTE_NEXT_TO_LAST 0x4UL
28 : :
29 : : /* Number of pointers per page_size */
30 : : #define MAX_PAGE_PTRS(page_size) ((page_size) / sizeof(void *))
31 : :
32 : : /**
33 : : * Function to free a page table
34 : : *
35 : : * [in] tp
36 : : * Pointer to the page table to free
37 : : */
38 : : static void
39 : 0 : tf_em_free_pg_tbl(struct hcapi_cfa_em_page_tbl *tp)
40 : : {
41 : : uint32_t i;
42 : :
43 [ # # ]: 0 : for (i = 0; i < tp->pg_count; i++) {
44 [ # # ]: 0 : if (!tp->pg_va_tbl[i]) {
45 : 0 : TFP_DRV_LOG(WARNING,
46 : : "No mapping for page: %d table: %016" PRIu64 "\n",
47 : : i,
48 : : (uint64_t)(uintptr_t)tp);
49 : 0 : continue;
50 : : }
51 : :
52 : 0 : tfp_free(tp->pg_va_tbl[i]);
53 : 0 : tp->pg_va_tbl[i] = NULL;
54 : : }
55 : :
56 : 0 : tp->pg_count = 0;
57 : 0 : tfp_free(tp->pg_va_tbl);
58 : 0 : tp->pg_va_tbl = NULL;
59 : 0 : tfp_free(tp->pg_pa_tbl);
60 : 0 : tp->pg_pa_tbl = NULL;
61 : 0 : }
62 : :
63 : : /**
64 : : * Function to free an EM table
65 : : *
66 : : * [in] tbl
67 : : * Pointer to the EM table to free
68 : : */
69 : : static void
70 : 0 : tf_em_free_page_table(struct hcapi_cfa_em_table *tbl)
71 : : {
72 : : struct hcapi_cfa_em_page_tbl *tp;
73 : : int i;
74 : :
75 [ # # ]: 0 : for (i = 0; i < tbl->num_lvl; i++) {
76 : 0 : tp = &tbl->pg_tbl[i];
77 : 0 : TFP_DRV_LOG(INFO,
78 : : "EEM: Freeing page table: size %u lvl %d cnt %u\n",
79 : : TF_EM_PAGE_SIZE,
80 : : i,
81 : : tp->pg_count);
82 : :
83 : 0 : tf_em_free_pg_tbl(tp);
84 : : }
85 : :
86 : 0 : tbl->l0_addr = NULL;
87 : 0 : tbl->l0_dma_addr = 0;
88 : 0 : tbl->num_lvl = 0;
89 : 0 : tbl->num_data_pages = 0;
90 : 0 : }
91 : :
92 : : /**
93 : : * Allocation of page tables
94 : : *
95 : : * [in] tfp
96 : : * Pointer to a TruFlow handle
97 : : *
98 : : * [in] pg_count
99 : : * Page count to allocate
100 : : *
101 : : * [in] pg_size
102 : : * Size of each page
103 : : *
104 : : * Returns:
105 : : * 0 - Success
106 : : * -ENOMEM - Out of memory
107 : : */
108 : : static int
109 : 0 : tf_em_alloc_pg_tbl(struct hcapi_cfa_em_page_tbl *tp,
110 : : uint32_t pg_count,
111 : : uint32_t pg_size)
112 : : {
113 : : uint32_t i;
114 : : struct tfp_calloc_parms parms;
115 : :
116 : 0 : parms.nitems = pg_count;
117 : 0 : parms.size = sizeof(void *);
118 : 0 : parms.alignment = 0;
119 : :
120 [ # # ]: 0 : if (tfp_calloc(&parms) != 0)
121 : : return -ENOMEM;
122 : :
123 : 0 : tp->pg_va_tbl = parms.mem_va;
124 : :
125 [ # # ]: 0 : if (tfp_calloc(&parms) != 0) {
126 : 0 : tfp_free(tp->pg_va_tbl);
127 : 0 : return -ENOMEM;
128 : : }
129 : :
130 : 0 : tp->pg_pa_tbl = parms.mem_va;
131 : :
132 : 0 : tp->pg_count = 0;
133 : 0 : tp->pg_size = pg_size;
134 : :
135 [ # # ]: 0 : for (i = 0; i < pg_count; i++) {
136 : 0 : parms.nitems = 1;
137 : 0 : parms.size = pg_size;
138 : 0 : parms.alignment = TF_EM_PAGE_ALIGNMENT;
139 : :
140 [ # # ]: 0 : if (tfp_calloc(&parms) != 0)
141 : 0 : goto cleanup;
142 : :
143 : 0 : tp->pg_pa_tbl[i] = (uintptr_t)parms.mem_pa;
144 : 0 : tp->pg_va_tbl[i] = parms.mem_va;
145 : :
146 : 0 : memset(tp->pg_va_tbl[i], 0, pg_size);
147 : 0 : tp->pg_count++;
148 : : }
149 : :
150 : : return 0;
151 : :
152 : : cleanup:
153 : 0 : tf_em_free_pg_tbl(tp);
154 : 0 : return -ENOMEM;
155 : : }
156 : :
157 : : /**
158 : : * Allocates EM page tables
159 : : *
160 : : * [in] tbl
161 : : * Table to allocate pages for
162 : : *
163 : : * Returns:
164 : : * 0 - Success
165 : : * -ENOMEM - Out of memory
166 : : */
167 : : static int
168 : 0 : tf_em_alloc_page_table(struct hcapi_cfa_em_table *tbl)
169 : : {
170 : : struct hcapi_cfa_em_page_tbl *tp;
171 : : int rc = 0;
172 : : int i;
173 : : uint32_t j;
174 : :
175 [ # # ]: 0 : for (i = 0; i < tbl->num_lvl; i++) {
176 : 0 : tp = &tbl->pg_tbl[i];
177 : :
178 : 0 : rc = tf_em_alloc_pg_tbl(tp,
179 : : tbl->page_cnt[i],
180 : : TF_EM_PAGE_SIZE);
181 [ # # ]: 0 : if (rc) {
182 : 0 : TFP_DRV_LOG(WARNING,
183 : : "Failed to allocate page table: lvl: %d, rc:%s\n",
184 : : i,
185 : : strerror(-rc));
186 : 0 : goto cleanup;
187 : : }
188 : :
189 [ # # ]: 0 : for (j = 0; j < tp->pg_count; j++) {
190 : 0 : TFP_DRV_LOG(INFO,
191 : : "EEM: Allocated page table: size %u lvl %d cnt"
192 : : " %u VA:%p PA:%p\n",
193 : : TF_EM_PAGE_SIZE,
194 : : i,
195 : : tp->pg_count,
196 : : (void *)(uintptr_t)tp->pg_va_tbl[j],
197 : : (void *)(uintptr_t)tp->pg_pa_tbl[j]);
198 : : }
199 : : }
200 : : return rc;
201 : :
202 : : cleanup:
203 : 0 : tf_em_free_page_table(tbl);
204 : 0 : return rc;
205 : : }
206 : :
207 : : /**
208 : : * Links EM page tables
209 : : *
210 : : * [in] tp
211 : : * Pointer to page table
212 : : *
213 : : * [in] tp_next
214 : : * Pointer to the next page table
215 : : *
216 : : * [in] set_pte_last
217 : : * Flag controlling if the page table is last
218 : : */
219 : : static void
220 : 0 : tf_em_link_page_table(struct hcapi_cfa_em_page_tbl *tp,
221 : : struct hcapi_cfa_em_page_tbl *tp_next,
222 : : bool set_pte_last)
223 : : {
224 : 0 : uint64_t *pg_pa = tp_next->pg_pa_tbl;
225 : : uint64_t *pg_va;
226 : : uint64_t valid;
227 : : uint32_t k = 0;
228 : : uint32_t i;
229 : : uint32_t j;
230 : :
231 [ # # ]: 0 : for (i = 0; i < tp->pg_count; i++) {
232 : 0 : pg_va = tp->pg_va_tbl[i];
233 : :
234 [ # # ]: 0 : for (j = 0; j < MAX_PAGE_PTRS(tp->pg_size); j++) {
235 [ # # # # ]: 0 : if (k == tp_next->pg_count - 2 && set_pte_last)
236 : : valid = PTU_PTE_NEXT_TO_LAST | PTU_PTE_VALID;
237 [ # # # # ]: 0 : else if (k == tp_next->pg_count - 1 && set_pte_last)
238 : : valid = PTU_PTE_LAST | PTU_PTE_VALID;
239 : : else
240 : : valid = PTU_PTE_VALID;
241 : :
242 : 0 : pg_va[j] = tfp_cpu_to_le_64(pg_pa[k] | valid);
243 [ # # ]: 0 : if (++k >= tp_next->pg_count)
244 : : return;
245 : : }
246 : : }
247 : : }
248 : :
249 : : /**
250 : : * Setup a EM page table
251 : : *
252 : : * [in] tbl
253 : : * Pointer to EM page table
254 : : */
255 : : static void
256 : 0 : tf_em_setup_page_table(struct hcapi_cfa_em_table *tbl)
257 : : {
258 : : struct hcapi_cfa_em_page_tbl *tp_next;
259 : : struct hcapi_cfa_em_page_tbl *tp;
260 : : bool set_pte_last = 0;
261 : : int i;
262 : :
263 [ # # ]: 0 : for (i = 0; i < tbl->num_lvl - 1; i++) {
264 : 0 : tp = &tbl->pg_tbl[i];
265 : 0 : tp_next = &tbl->pg_tbl[i + 1];
266 [ # # ]: 0 : if (i == tbl->num_lvl - 2)
267 : : set_pte_last = 1;
268 : 0 : tf_em_link_page_table(tp, tp_next, set_pte_last);
269 : : }
270 : :
271 : 0 : tbl->l0_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_va_tbl[0];
272 : 0 : tbl->l0_dma_addr = tbl->pg_tbl[TF_PT_LVL_0].pg_pa_tbl[0];
273 : 0 : }
274 : :
275 : : /**
276 : : * Unregisters EM Ctx in Firmware
277 : : *
278 : : * [in] tfp
279 : : * Pointer to a TruFlow handle
280 : : *
281 : : * [in] tbl_scope_cb
282 : : * Pointer to a table scope control block
283 : : *
284 : : * [in] dir
285 : : * Receive or transmit direction
286 : : */
287 : : static void
288 : 0 : tf_em_ctx_unreg(struct tf *tfp,
289 : : struct tf_tbl_scope_cb *tbl_scope_cb,
290 : : int dir)
291 : : {
292 : : struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
293 : : struct hcapi_cfa_em_table *tbl;
294 : : int i;
295 : :
296 [ # # ]: 0 : for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
297 : 0 : tbl = &ctxp->em_tables[i];
298 : :
299 [ # # # # ]: 0 : if (tbl->num_entries != 0 && tbl->entry_size != 0) {
300 : 0 : tf_msg_em_mem_unrgtr(tfp, &tbl->ctx_id);
301 : 0 : tf_em_free_page_table(tbl);
302 : : }
303 : : }
304 : 0 : }
305 : :
306 : : /**
307 : : * Registers EM Ctx in Firmware
308 : : *
309 : : * [in] tfp
310 : : * Pointer to a TruFlow handle
311 : : *
312 : : * [in] tbl_scope_cb
313 : : * Pointer to a table scope control block
314 : : *
315 : : * [in] dir
316 : : * Receive or transmit direction
317 : : *
318 : : * Returns:
319 : : * 0 - Success
320 : : * -ENOMEM - Out of Memory
321 : : */
322 : : static int
323 : 0 : tf_em_ctx_reg(struct tf *tfp,
324 : : struct tf_tbl_scope_cb *tbl_scope_cb,
325 : : int dir)
326 : : {
327 : : struct hcapi_cfa_em_ctx_mem_info *ctxp = &tbl_scope_cb->em_ctx_info[dir];
328 : : struct hcapi_cfa_em_table *tbl;
329 : : int rc = 0;
330 : : int i;
331 : :
332 [ # # ]: 0 : for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
333 : 0 : tbl = &ctxp->em_tables[i];
334 : :
335 [ # # # # ]: 0 : if (tbl->num_entries && tbl->entry_size) {
336 : 0 : rc = tf_em_size_table(tbl, TF_EM_PAGE_SIZE);
337 : :
338 [ # # ]: 0 : if (rc)
339 : 0 : goto cleanup;
340 : :
341 : 0 : rc = tf_em_alloc_page_table(tbl);
342 [ # # ]: 0 : if (rc)
343 : 0 : goto cleanup;
344 : :
345 : 0 : tf_em_setup_page_table(tbl);
346 : 0 : rc = tf_msg_em_mem_rgtr(tfp,
347 : 0 : tbl->num_lvl - 1,
348 : : TF_EM_PAGE_SIZE_ENUM,
349 : : tbl->l0_dma_addr,
350 : : &tbl->ctx_id);
351 [ # # ]: 0 : if (rc)
352 : 0 : goto cleanup;
353 : : }
354 : : }
355 : : return rc;
356 : :
357 : 0 : cleanup:
358 : 0 : tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
359 : 0 : return rc;
360 : : }
361 : :
362 : : int
363 : 0 : tf_em_ext_alloc(struct tf *tfp,
364 : : struct tf_alloc_tbl_scope_parms *parms)
365 : : {
366 : : int rc;
367 : : enum tf_dir dir;
368 : : struct tf_tbl_scope_cb *tbl_scope_cb;
369 : : struct hcapi_cfa_em_table *em_tables;
370 : : struct tf_free_tbl_scope_parms free_parms;
371 : 0 : struct tf_rm_allocate_parms aparms = { 0 };
372 : 0 : struct tf_rm_free_parms fparms = { 0 };
373 : : struct tfp_calloc_parms cparms;
374 : 0 : struct tf_session *tfs = NULL;
375 : : struct em_ext_db *ext_db = NULL;
376 : 0 : void *ext_ptr = NULL;
377 : : uint16_t pf;
378 : :
379 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
380 [ # # ]: 0 : if (rc) {
381 : 0 : TFP_DRV_LOG(ERR, "Failed to get tf_session, rc:%s\n",
382 : : strerror(-rc));
383 : 0 : return rc;
384 : : }
385 : :
386 : 0 : rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
387 [ # # ]: 0 : if (rc) {
388 : 0 : TFP_DRV_LOG(ERR,
389 : : "Failed to get em_ext_db from session, rc:%s\n",
390 : : strerror(-rc));
391 : 0 : return rc;
392 : : }
393 : 0 : ext_db = (struct em_ext_db *)ext_ptr;
394 : :
395 : 0 : rc = tfp_get_pf(tfp, &pf);
396 [ # # ]: 0 : if (rc) {
397 : 0 : TFP_DRV_LOG(ERR,
398 : : "EEM: PF query error rc:%s\n",
399 : : strerror(-rc));
400 : 0 : goto cleanup;
401 : : }
402 : :
403 : : /* Get Table Scope control block from the session pool */
404 : 0 : aparms.rm_db = ext_db->eem_db[TF_DIR_RX];
405 : 0 : aparms.subtype = TF_EM_TBL_TYPE_TBL_SCOPE;
406 : 0 : aparms.index = (uint32_t *)&parms->tbl_scope_id;
407 : 0 : rc = tf_rm_allocate(&aparms);
408 [ # # ]: 0 : if (rc) {
409 : 0 : TFP_DRV_LOG(ERR,
410 : : "Failed to allocate table scope\n");
411 : 0 : goto cleanup;
412 : : }
413 : :
414 : : /* Create tbl_scope, initialize and attach to the session */
415 : 0 : cparms.nitems = 1;
416 : 0 : cparms.size = sizeof(struct tf_tbl_scope_cb);
417 : 0 : cparms.alignment = 0;
418 : 0 : rc = tfp_calloc(&cparms);
419 [ # # ]: 0 : if (rc) {
420 : : /* Log error */
421 : 0 : TFP_DRV_LOG(ERR,
422 : : "Failed to allocate session table scope, rc:%s\n",
423 : : strerror(-rc));
424 : 0 : goto cleanup;
425 : : }
426 : :
427 : 0 : tbl_scope_cb = cparms.mem_va;
428 : 0 : tbl_scope_cb->tbl_scope_id = parms->tbl_scope_id;
429 : 0 : tbl_scope_cb->pf = pf;
430 : :
431 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
432 : 0 : rc = tf_msg_em_qcaps(tfp,
433 : : dir,
434 : : &tbl_scope_cb->em_caps[dir]);
435 [ # # ]: 0 : if (rc) {
436 : 0 : TFP_DRV_LOG(ERR,
437 : : "EEM: Unable to query for EEM capability,"
438 : : " rc:%s\n",
439 : : strerror(-rc));
440 : 0 : goto cleanup_ts;
441 : : }
442 : : }
443 : :
444 : : /*
445 : : * Validate and setup table sizes
446 : : */
447 [ # # ]: 0 : if (tf_em_validate_num_entries(tbl_scope_cb, parms))
448 : 0 : goto cleanup_ts;
449 : :
450 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
451 : : /*
452 : : * Allocate tables and signal configuration to FW
453 : : */
454 : 0 : rc = tf_em_ctx_reg(tfp, tbl_scope_cb, dir);
455 [ # # ]: 0 : if (rc) {
456 : 0 : TFP_DRV_LOG(ERR,
457 : : "EEM: Unable to register for EEM ctx,"
458 : : " rc:%s\n",
459 : : strerror(-rc));
460 : 0 : goto cleanup_ts;
461 : : }
462 : :
463 : 0 : em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
464 : 0 : rc = tf_msg_em_cfg(tfp,
465 : : em_tables[TF_KEY0_TABLE].num_entries,
466 : 0 : em_tables[TF_KEY0_TABLE].ctx_id,
467 : 0 : em_tables[TF_KEY1_TABLE].ctx_id,
468 : 0 : em_tables[TF_RECORD_TABLE].ctx_id,
469 : 0 : em_tables[TF_EFC_TABLE].ctx_id,
470 : 0 : parms->hw_flow_cache_flush_timer,
471 : : dir);
472 [ # # ]: 0 : if (rc) {
473 : 0 : TFP_DRV_LOG(ERR,
474 : : "TBL: Unable to configure EEM in firmware"
475 : : " rc:%s\n",
476 : : strerror(-rc));
477 : 0 : goto cleanup_full;
478 : : }
479 : :
480 : 0 : rc = tf_msg_em_op(tfp,
481 : : dir,
482 : : HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_ENABLE);
483 : :
484 [ # # ]: 0 : if (rc) {
485 : 0 : TFP_DRV_LOG(ERR,
486 : : "EEM: Unable to enable EEM in firmware"
487 : : " rc:%s\n",
488 : : strerror(-rc));
489 : 0 : goto cleanup_full;
490 : : }
491 : :
492 : : /* Allocate the pool of offsets of the external memory.
493 : : * Initially, this is a single fixed size pool for all external
494 : : * actions related to a single table scope.
495 : : */
496 : 0 : rc = tf_create_tbl_pool_external(dir,
497 : : tbl_scope_cb,
498 : : em_tables[TF_RECORD_TABLE].num_entries,
499 : : em_tables[TF_RECORD_TABLE].entry_size);
500 [ # # ]: 0 : if (rc) {
501 : 0 : TFP_DRV_LOG(ERR,
502 : : "%s TBL: Unable to allocate idx pools %s\n",
503 : : tf_dir_2_str(dir),
504 : : strerror(-rc));
505 : 0 : goto cleanup_full;
506 : : }
507 : : }
508 : :
509 : : /* Insert into session tbl_scope list */
510 : 0 : ll_insert(&ext_db->tbl_scope_ll, &tbl_scope_cb->ll_entry);
511 : 0 : return 0;
512 : :
513 : 0 : cleanup_full:
514 : 0 : free_parms.tbl_scope_id = parms->tbl_scope_id;
515 : : /* Insert into session list prior to ext_free */
516 : 0 : ll_insert(&ext_db->tbl_scope_ll, &tbl_scope_cb->ll_entry);
517 : 0 : tf_em_ext_free(tfp, &free_parms);
518 : 0 : return -EINVAL;
519 : :
520 : 0 : cleanup_ts:
521 : 0 : tfp_free(tbl_scope_cb);
522 : :
523 : 0 : cleanup:
524 : : /* Free Table control block */
525 : 0 : fparms.rm_db = ext_db->eem_db[TF_DIR_RX];
526 : 0 : fparms.subtype = TF_EM_TBL_TYPE_TBL_SCOPE;
527 : 0 : fparms.index = parms->tbl_scope_id;
528 : 0 : rc = tf_rm_free(&fparms);
529 [ # # ]: 0 : if (rc)
530 : 0 : TFP_DRV_LOG(ERR, "Failed to free table scope\n");
531 : :
532 : : return -EINVAL;
533 : : }
534 : :
535 : : int
536 : 0 : tf_em_ext_free(struct tf *tfp,
537 : : struct tf_free_tbl_scope_parms *parms)
538 : : {
539 : : int rc = 0;
540 : : enum tf_dir dir;
541 : : struct tf_tbl_scope_cb *tbl_scope_cb;
542 : : struct tf_session *tfs;
543 : : struct em_ext_db *ext_db = NULL;
544 : 0 : void *ext_ptr = NULL;
545 : 0 : struct tf_rm_free_parms aparms = { 0 };
546 : :
547 : 0 : rc = tf_session_get_session_internal(tfp, &tfs);
548 [ # # ]: 0 : if (rc) {
549 : 0 : TFP_DRV_LOG(ERR, "Failed to get tf_session, rc:%s\n",
550 : : strerror(-rc));
551 : 0 : return -EINVAL;
552 : : }
553 : :
554 : 0 : rc = tf_session_get_em_ext_db(tfp, &ext_ptr);
555 [ # # ]: 0 : if (rc) {
556 : 0 : TFP_DRV_LOG(ERR,
557 : : "Failed to get em_ext_db from session, rc:%s\n",
558 : : strerror(-rc));
559 : 0 : return rc;
560 : : }
561 : 0 : ext_db = (struct em_ext_db *)ext_ptr;
562 : :
563 : 0 : tbl_scope_cb = tf_em_ext_common_tbl_scope_find(tfp, parms->tbl_scope_id);
564 [ # # ]: 0 : if (tbl_scope_cb == NULL) {
565 : 0 : TFP_DRV_LOG(ERR, "Table scope error\n");
566 : 0 : return -EINVAL;
567 : : }
568 : :
569 : : /* Free Table control block */
570 : 0 : aparms.rm_db = ext_db->eem_db[TF_DIR_RX];
571 : 0 : aparms.subtype = TF_EM_TBL_TYPE_TBL_SCOPE;
572 : 0 : aparms.index = parms->tbl_scope_id;
573 : 0 : rc = tf_rm_free(&aparms);
574 [ # # ]: 0 : if (rc) {
575 : 0 : TFP_DRV_LOG(ERR,
576 : : "Failed to free table scope\n");
577 : : }
578 : :
579 : : /* free table scope locks */
580 [ # # ]: 0 : for (dir = 0; dir < TF_DIR_MAX; dir++) {
581 : : /* Free associated external pools
582 : : */
583 : 0 : tf_destroy_tbl_pool_external(dir,
584 : : tbl_scope_cb);
585 : 0 : tf_msg_em_op(tfp,
586 : : dir,
587 : : HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE);
588 : :
589 : : /* free table scope and all associated resources */
590 : 0 : tf_em_ctx_unreg(tfp, tbl_scope_cb, dir);
591 : : }
592 : :
593 : : /* remove from session list and free tbl_scope */
594 : 0 : ll_delete(&ext_db->tbl_scope_ll, &tbl_scope_cb->ll_entry);
595 : 0 : tfp_free(tbl_scope_cb);
596 : 0 : return rc;
597 : : }
|