int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev, struct bnxt_qplib_rcfw *rcfw) { rcfw->pdev = pdev; rcfw->creq.max_elements = BNXT_QPLIB_CREQE_MAX_CNT; if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->creq, NULL, 0, &rcfw->creq.max_elements, BNXT_QPLIB_CREQE_UNITS, 0, PAGE_SIZE, HWQ_TYPE_L2_CMPL)) { dev_err(&rcfw->pdev->dev, "QPLIB: HW channel CREQ allocation failed"); goto fail; } rcfw->cmdq.max_elements = BNXT_QPLIB_CMDQE_MAX_CNT; if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->cmdq, NULL, 0, &rcfw->cmdq.max_elements, BNXT_QPLIB_CMDQE_UNITS, 0, PAGE_SIZE, HWQ_TYPE_CTX)) { dev_err(&rcfw->pdev->dev, "QPLIB: HW channel CMDQ allocation failed"); goto fail; } rcfw->crsqe_tbl = kcalloc(rcfw->cmdq.max_elements, sizeof(*rcfw->crsqe_tbl), GFP_KERNEL); if (!rcfw->crsqe_tbl) goto fail; return 0; fail: bnxt_qplib_free_rcfw_channel(rcfw); return -ENOMEM; }
int bnxt_qplib_alloc_fast_reg_page_list(struct bnxt_qplib_res *res, struct bnxt_qplib_frpl *frpl, int max_pg_ptrs) { int pg_ptrs, pages, rc; /* Re-calculate the max to fit the HWQ allocation model */ pg_ptrs = roundup_pow_of_two(max_pg_ptrs); pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; if (!pages) pages++; if (pages > MAX_PBL_LVL_1_PGS) return -ENOMEM; frpl->hwq.max_elements = pages; rc = bnxt_qplib_alloc_init_hwq(res->pdev, &frpl->hwq, NULL, 0, &frpl->hwq.max_elements, PAGE_SIZE, 0, PAGE_SIZE, HWQ_TYPE_CTX); if (!rc) frpl->max_pg_ptrs = pg_ptrs; return rc; }
int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, u64 *pbl_tbl, int num_pbls, bool block) { struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct cmdq_register_mr req; struct creq_register_mr_resp resp; u16 cmd_flags = 0, level; int pg_ptrs, pages, i, rc; dma_addr_t **pbl_ptr; u32 pg_size; if (num_pbls) { pg_ptrs = roundup_pow_of_two(num_pbls); pages = pg_ptrs >> MAX_PBL_LVL_1_PGS_SHIFT; if (!pages) pages++; if (pages > MAX_PBL_LVL_1_PGS) { dev_err(&res->pdev->dev, "QPLIB: SP: Reg MR pages "); dev_err(&res->pdev->dev, "requested (0x%x) exceeded max (0x%x)", pages, MAX_PBL_LVL_1_PGS); return -ENOMEM; } /* Free the hwq if it already exist, must be a rereg */ if (mr->hwq.max_elements) bnxt_qplib_free_hwq(res->pdev, &mr->hwq); mr->hwq.max_elements = pages; rc = bnxt_qplib_alloc_init_hwq(res->pdev, &mr->hwq, NULL, 0, &mr->hwq.max_elements, PAGE_SIZE, 0, PAGE_SIZE, HWQ_TYPE_CTX); if (rc) { dev_err(&res->pdev->dev, "SP: Reg MR memory allocation failed"); return -ENOMEM; } /* Write to the hwq */ pbl_ptr = (dma_addr_t **)mr->hwq.pbl_ptr; for (i = 0; i < num_pbls; i++) pbl_ptr[PTR_PG(i)][PTR_IDX(i)] = (pbl_tbl[i] & PAGE_MASK) | PTU_PTE_VALID; } RCFW_CMD_PREP(req, REGISTER_MR, cmd_flags); /* Configure the request */ if (mr->hwq.level == PBL_LVL_MAX) { level = 0; req.pbl = 0; pg_size = PAGE_SIZE; } else { level = mr->hwq.level + 1; req.pbl = cpu_to_le64(mr->hwq.pbl[PBL_LVL_0].pg_map_arr[0]); pg_size = mr->hwq.pbl[PBL_LVL_0].pg_size; } req.log2_pg_size_lvl = (level << CMDQ_REGISTER_MR_LVL_SFT) | ((ilog2(pg_size) << CMDQ_REGISTER_MR_LOG2_PG_SIZE_SFT) & CMDQ_REGISTER_MR_LOG2_PG_SIZE_MASK); req.access = (mr->flags & 0xFFFF); req.va = cpu_to_le64(mr->va); req.key = cpu_to_le32(mr->lkey); req.mr_size = cpu_to_le64(mr->total_size); rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, block); if (rc) goto fail; return 0; fail: if (mr->hwq.max_elements) bnxt_qplib_free_hwq(res->pdev, &mr->hwq); return rc; }