1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
12 #include <sys/param.h>
14 #include <sys/ioctl.h>
17 #include <rte_common.h>
18 #include <rte_errno.h>
23 #include "tf_common.h"
25 #include "tf_em_common.h"
29 #include "tf_ext_flow_handle.h"
34 TF_EM_BNXT_LFC_CFA_EEM_DMABUF_EXPORT_REQ = 5,
37 struct tf_em_bnxt_lfc_req_hdr {
41 enum tf_em_req_type req_type;
44 struct tf_em_bnxt_lfc_cfa_eem_std_hdr {
48 #define TF_EM_BNXT_LFC_EEM_CFG_PRIMARY_FUNC (1 << 0)
51 struct tf_em_bnxt_lfc_dmabuf_fd {
52 int fd[TF_DIR_MAX][TF_MAX_TABLE];
59 struct tf_em_bnxt_lfc_cfa_eem_dmabuf_export_req {
60 struct tf_em_bnxt_lfc_cfa_eem_std_hdr std;
66 struct tf_em_bnxt_lfc_req {
67 struct tf_em_bnxt_lfc_req_hdr hdr;
69 struct tf_em_bnxt_lfc_cfa_eem_dmabuf_export_req
70 eem_dmabuf_export_req;
75 #define TF_EEM_BNXT_LFC_IOCTL_MAGIC 0x98
76 #define BNXT_LFC_REQ \
77 _IOW(TF_EEM_BNXT_LFC_IOCTL_MAGIC, 1, struct tf_em_bnxt_lfc_req)
82 extern void *eem_db[TF_DIR_MAX];
84 extern struct tf_tbl_scope_cb tbl_scopes[TF_NUM_TBL_SCOPE];
87 tf_em_dmabuf_mem_unmap(struct hcapi_cfa_em_table *tbl)
89 struct hcapi_cfa_em_page_tbl *tp;
91 uint32_t page_no, pg_count;
93 for (level = (tbl->num_lvl - 1); level < tbl->num_lvl; level++) {
94 tp = &tbl->pg_tbl[level];
96 pg_count = tbl->page_cnt[level];
97 for (page_no = 0; page_no < pg_count; page_no++) {
98 if (tp->pg_va_tbl != NULL &&
99 tp->pg_va_tbl[page_no] != NULL &&
101 (void)munmap(tp->pg_va_tbl[page_no],
106 tfp_free((void *)tp->pg_va_tbl);
107 tfp_free((void *)tp->pg_pa_tbl);
112 * Unregisters EM Ctx in Firmware
115 * Pointer to a TruFlow handle
118 * Pointer to a table scope control block
121 * Receive or transmit direction
124 tf_em_ctx_unreg(struct tf_tbl_scope_cb *tbl_scope_cb,
127 struct hcapi_cfa_em_ctx_mem_info *ctxp =
128 &tbl_scope_cb->em_ctx_info[dir];
129 struct hcapi_cfa_em_table *tbl;
132 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
133 tbl = &ctxp->em_tables[i];
134 tf_em_dmabuf_mem_unmap(tbl);
138 static int tf_export_tbl_scope(int lfc_fd,
143 struct tf_em_bnxt_lfc_req tf_lfc_req;
144 struct tf_em_bnxt_lfc_dmabuf_fd *dma_fd;
145 struct tfp_calloc_parms mparms;
148 memset(&tf_lfc_req, 0, sizeof(struct tf_em_bnxt_lfc_req));
149 tf_lfc_req.hdr.ver = 1;
150 tf_lfc_req.hdr.bus = bus;
151 tf_lfc_req.hdr.devfn = devfn;
152 tf_lfc_req.hdr.req_type = TF_EM_BNXT_LFC_CFA_EEM_DMABUF_EXPORT_REQ;
153 tf_lfc_req.req.eem_dmabuf_export_req.flags = O_ACCMODE;
154 tf_lfc_req.req.eem_dmabuf_export_req.std.version = 1;
157 mparms.size = sizeof(struct tf_em_bnxt_lfc_dmabuf_fd);
158 mparms.alignment = 0;
160 dma_fd = (struct tf_em_bnxt_lfc_dmabuf_fd *)mparms.mem_va;
161 tf_lfc_req.req.eem_dmabuf_export_req.dma_fd = dma_fd;
163 rc = ioctl(lfc_fd, BNXT_LFC_REQ, &tf_lfc_req);
166 "EXT EEM export chanel_fd %d, rc=%d\n",
173 memcpy(fd, dma_fd->fd, sizeof(dma_fd->fd));
180 tf_em_dmabuf_mem_map(struct hcapi_cfa_em_table *tbl,
183 struct hcapi_cfa_em_page_tbl *tp;
188 struct tfp_calloc_parms parms;
190 for (level = (tbl->num_lvl - 1); level < tbl->num_lvl; level++) {
191 tp = &tbl->pg_tbl[level];
193 pg_count = tbl->page_cnt[level];
196 parms.nitems = pg_count;
197 parms.size = sizeof(void *);
200 if ((tfp_calloc(&parms)) != 0)
203 tp->pg_va_tbl = parms.mem_va;
204 parms.nitems = pg_count;
205 parms.size = sizeof(void *);
208 if ((tfp_calloc(&parms)) != 0) {
209 tfp_free((void *)tp->pg_va_tbl);
213 tp->pg_pa_tbl = parms.mem_va;
215 tp->pg_size = TF_EM_PAGE_SIZE;
217 for (page_no = 0; page_no < pg_count; page_no++) {
218 tp->pg_va_tbl[page_no] = mmap(NULL,
220 PROT_READ | PROT_WRITE,
224 if (tp->pg_va_tbl[page_no] == (void *)-1) {
226 "MMap memory error. level:%d page:%d pg_count:%d - %s\n",
233 offset += tp->pg_size;
241 static int tf_mmap_tbl_scope(struct tf_tbl_scope_cb *tbl_scope_cb,
246 struct hcapi_cfa_em_table *tbl;
248 if (tbl_type == TF_EFC_TABLE)
251 tbl = &tbl_scope_cb->em_ctx_info[dir].em_tables[tbl_type];
252 return tf_em_dmabuf_mem_map(tbl, dmabuf_fd);
255 #define TF_LFC_DEVICE "/dev/bnxt_lfc"
258 tf_prepare_dmabuf_bnxt_lfc_device(struct tf_tbl_scope_cb *tbl_scope_cb)
262 lfc_fd = open(TF_LFC_DEVICE, O_RDWR);
265 "EEM: open %s device error\n",
270 tbl_scope_cb->lfc_fd = lfc_fd;
275 int offload_system_mmap(struct tf_tbl_scope_cb *tbl_scope_cb)
280 enum hcapi_cfa_em_table_type tbl_type;
282 rc = tf_prepare_dmabuf_bnxt_lfc_device(tbl_scope_cb);
284 TFP_DRV_LOG(ERR, "EEM: Prepare bnxt_lfc channel failed\n");
288 rc = tf_export_tbl_scope(tbl_scope_cb->lfc_fd,
289 (int *)tbl_scope_cb->fd,
291 tbl_scope_cb->devfn);
294 "export dmabuf fd failed\n");
298 tbl_scope_cb->valid = true;
300 for (dir = 0; dir < TF_DIR_MAX; dir++) {
301 for (tbl_type = TF_KEY0_TABLE; tbl_type <
302 TF_MAX_TABLE; tbl_type++) {
303 if (tbl_type == TF_EFC_TABLE)
306 dmabuf_fd = tbl_scope_cb->fd[(dir ? 0 : 1)][tbl_type];
307 rc = tf_mmap_tbl_scope(tbl_scope_cb,
313 "dir:%d tbl:%d mmap failed rc %d\n",
325 tf_destroy_dmabuf_bnxt_lfc_device(struct tf_tbl_scope_cb *tbl_scope_cb)
327 close(tbl_scope_cb->lfc_fd);
333 tf_dmabuf_alloc(struct tf *tfp, struct tf_tbl_scope_cb *tbl_scope_cb)
337 rc = tfp_msg_hwrm_oem_cmd(tfp,
338 tbl_scope_cb->em_ctx_info[TF_DIR_RX].em_tables[TF_KEY0_TABLE].num_entries);
340 PMD_DRV_LOG(ERR, "EEM: Failed to prepare system memory rc:%d\n",
347 tf_dmabuf_free(struct tf *tfp, struct tf_tbl_scope_cb *tbl_scope_cb)
351 rc = tfp_msg_hwrm_oem_cmd(tfp, 0);
353 TFP_DRV_LOG(ERR, "EEM: Failed to cleanup system memory\n");
355 tf_destroy_dmabuf_bnxt_lfc_device(tbl_scope_cb);
361 tf_em_ext_alloc(struct tf *tfp,
362 struct tf_alloc_tbl_scope_parms *parms)
365 struct tf_session *tfs;
366 struct tf_tbl_scope_cb *tbl_scope_cb;
367 struct tf_rm_allocate_parms aparms = { 0 };
368 struct tf_free_tbl_scope_parms free_parms;
369 struct tf_rm_free_parms fparms = { 0 };
372 struct hcapi_cfa_em_table *em_tables;
374 TF_CHECK_PARMS2(tfp, parms);
376 /* Retrieve the session information */
377 rc = tf_session_get_session(tfp, &tfs);
380 "Failed to lookup session, rc:%s\n",
385 aparms.rm_db = eem_db[TF_DIR_RX];
386 aparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
387 aparms.index = (uint32_t *)&parms->tbl_scope_id;
388 rc = tf_rm_allocate(&aparms);
391 "Failed to allocate table scope\n");
395 tbl_scope_cb = &tbl_scopes[parms->tbl_scope_id];
396 tbl_scope_cb->index = parms->tbl_scope_id;
397 tbl_scope_cb->tbl_scope_id = parms->tbl_scope_id;
398 tbl_scope_cb->bus = tfs->session_id.internal.bus;
399 tbl_scope_cb->devfn = tfs->session_id.internal.device;
401 for (dir = 0; dir < TF_DIR_MAX; dir++) {
402 rc = tf_msg_em_qcaps(tfp,
404 &tbl_scope_cb->em_caps[dir]);
407 "EEM: Unable to query for EEM capability,"
415 * Validate and setup table sizes
417 if (tf_em_validate_num_entries(tbl_scope_cb, parms))
420 rc = tf_dmabuf_alloc(tfp, tbl_scope_cb);
423 "System DMA buff alloc failed\n");
427 for (dir = 0; dir < TF_DIR_MAX; dir++) {
428 for (i = TF_KEY0_TABLE; i < TF_MAX_TABLE; i++) {
429 if (i == TF_EFC_TABLE)
433 &tbl_scope_cb->em_ctx_info[dir].em_tables[i];
435 rc = tf_em_size_table(em_tables, TF_EM_PAGE_SIZE);
437 TFP_DRV_LOG(ERR, "Size table failed\n");
442 em_tables = tbl_scope_cb->em_ctx_info[dir].em_tables;
443 rc = tf_create_tbl_pool_external(dir,
445 em_tables[TF_RECORD_TABLE].num_entries,
446 em_tables[TF_RECORD_TABLE].entry_size);
450 "%s TBL: Unable to allocate idx pools %s\n",
457 #if (TF_EM_SYSMEM_DELAY_EXPORT == 0)
458 rc = offload_system_mmap(tbl_scope_cb);
462 "System alloc mmap failed\n");
470 free_parms.tbl_scope_id = parms->tbl_scope_id;
471 tf_em_ext_free(tfp, &free_parms);
475 /* Free Table control block */
476 fparms.rm_db = eem_db[TF_DIR_RX];
477 fparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
478 fparms.index = parms->tbl_scope_id;
484 tf_em_ext_free(struct tf *tfp,
485 struct tf_free_tbl_scope_parms *parms)
488 struct tf_session *tfs;
489 struct tf_tbl_scope_cb *tbl_scope_cb;
491 struct tf_rm_free_parms aparms = { 0 };
493 TF_CHECK_PARMS2(tfp, parms);
495 /* Retrieve the session information */
496 rc = tf_session_get_session(tfp, &tfs);
499 "Failed to lookup session, rc:%s\n",
504 tbl_scope_cb = &tbl_scopes[parms->tbl_scope_id];
506 /* Free Table control block */
507 aparms.rm_db = eem_db[TF_DIR_RX];
508 aparms.db_index = TF_EM_TBL_TYPE_TBL_SCOPE;
509 aparms.index = parms->tbl_scope_id;
510 rc = tf_rm_free(&aparms);
513 "Failed to free table scope\n");
516 for (dir = 0; dir < TF_DIR_MAX; dir++) {
517 /* Free associated external pools
519 tf_destroy_tbl_pool_external(dir,
523 tf_em_ctx_unreg(tbl_scope_cb, dir);
527 HWRM_TF_EXT_EM_OP_INPUT_OP_EXT_EM_DISABLE);
530 tf_dmabuf_free(tfp, tbl_scope_cb);
531 tbl_scope_cb->valid = false;