18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Broadcom NetXtreme-E RoCE driver.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2016 - 2017, Broadcom. All rights reserved.  The term
58c2ecf20Sopenharmony_ci * Broadcom refers to Broadcom Limited and/or its subsidiaries.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
88c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
98c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
108c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the
118c2ecf20Sopenharmony_ci * BSD license below:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
148c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
158c2ecf20Sopenharmony_ci * are met:
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
198c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
208c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
218c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
228c2ecf20Sopenharmony_ci *    distribution.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
258c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
268c2ecf20Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
278c2ecf20Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
298c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
308c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
318c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
328c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
338c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
348c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * Description: QPLib resource manager
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define dev_fmt(fmt) "QPLIB: " fmt
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
428c2ecf20Sopenharmony_ci#include <linux/pci.h>
438c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
448c2ecf20Sopenharmony_ci#include <linux/inetdevice.h>
458c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
468c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
478c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
488c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h>
498c2ecf20Sopenharmony_ci#include <rdma/ib_umem.h>
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#include "roce_hsi.h"
528c2ecf20Sopenharmony_ci#include "qplib_res.h"
538c2ecf20Sopenharmony_ci#include "qplib_sp.h"
548c2ecf20Sopenharmony_ci#include "qplib_rcfw.h"
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_stats_ctx(struct pci_dev *pdev,
578c2ecf20Sopenharmony_ci				      struct bnxt_qplib_stats *stats);
588c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_stats_ctx(struct pci_dev *pdev,
598c2ecf20Sopenharmony_ci				      struct bnxt_qplib_chip_ctx *cctx,
608c2ecf20Sopenharmony_ci				      struct bnxt_qplib_stats *stats);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/* PBL */
638c2ecf20Sopenharmony_cistatic void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
648c2ecf20Sopenharmony_ci		       bool is_umem)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct pci_dev *pdev = res->pdev;
678c2ecf20Sopenharmony_ci	int i;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	if (!is_umem) {
708c2ecf20Sopenharmony_ci		for (i = 0; i < pbl->pg_count; i++) {
718c2ecf20Sopenharmony_ci			if (pbl->pg_arr[i])
728c2ecf20Sopenharmony_ci				dma_free_coherent(&pdev->dev, pbl->pg_size,
738c2ecf20Sopenharmony_ci						  (void *)((unsigned long)
748c2ecf20Sopenharmony_ci						   pbl->pg_arr[i] &
758c2ecf20Sopenharmony_ci						  PAGE_MASK),
768c2ecf20Sopenharmony_ci						  pbl->pg_map_arr[i]);
778c2ecf20Sopenharmony_ci			else
788c2ecf20Sopenharmony_ci				dev_warn(&pdev->dev,
798c2ecf20Sopenharmony_ci					 "PBL free pg_arr[%d] empty?!\n", i);
808c2ecf20Sopenharmony_ci			pbl->pg_arr[i] = NULL;
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci	vfree(pbl->pg_arr);
848c2ecf20Sopenharmony_ci	pbl->pg_arr = NULL;
858c2ecf20Sopenharmony_ci	vfree(pbl->pg_map_arr);
868c2ecf20Sopenharmony_ci	pbl->pg_map_arr = NULL;
878c2ecf20Sopenharmony_ci	pbl->pg_count = 0;
888c2ecf20Sopenharmony_ci	pbl->pg_size = 0;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic void bnxt_qplib_fill_user_dma_pages(struct bnxt_qplib_pbl *pbl,
928c2ecf20Sopenharmony_ci					   struct bnxt_qplib_sg_info *sginfo)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	struct ib_block_iter biter;
958c2ecf20Sopenharmony_ci	int i = 0;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	rdma_umem_for_each_dma_block(sginfo->umem, &biter, sginfo->pgsize) {
988c2ecf20Sopenharmony_ci		pbl->pg_map_arr[i] = rdma_block_iter_dma_address(&biter);
998c2ecf20Sopenharmony_ci		pbl->pg_arr[i] = NULL;
1008c2ecf20Sopenharmony_ci		pbl->pg_count++;
1018c2ecf20Sopenharmony_ci		i++;
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic int __alloc_pbl(struct bnxt_qplib_res *res,
1068c2ecf20Sopenharmony_ci		       struct bnxt_qplib_pbl *pbl,
1078c2ecf20Sopenharmony_ci		       struct bnxt_qplib_sg_info *sginfo)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct pci_dev *pdev = res->pdev;
1108c2ecf20Sopenharmony_ci	bool is_umem = false;
1118c2ecf20Sopenharmony_ci	u32 pages;
1128c2ecf20Sopenharmony_ci	int i;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	if (sginfo->nopte)
1158c2ecf20Sopenharmony_ci		return 0;
1168c2ecf20Sopenharmony_ci	if (sginfo->umem)
1178c2ecf20Sopenharmony_ci		pages = ib_umem_num_dma_blocks(sginfo->umem, sginfo->pgsize);
1188c2ecf20Sopenharmony_ci	else
1198c2ecf20Sopenharmony_ci		pages = sginfo->npages;
1208c2ecf20Sopenharmony_ci	/* page ptr arrays */
1218c2ecf20Sopenharmony_ci	pbl->pg_arr = vmalloc(pages * sizeof(void *));
1228c2ecf20Sopenharmony_ci	if (!pbl->pg_arr)
1238c2ecf20Sopenharmony_ci		return -ENOMEM;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	pbl->pg_map_arr = vmalloc(pages * sizeof(dma_addr_t));
1268c2ecf20Sopenharmony_ci	if (!pbl->pg_map_arr) {
1278c2ecf20Sopenharmony_ci		vfree(pbl->pg_arr);
1288c2ecf20Sopenharmony_ci		pbl->pg_arr = NULL;
1298c2ecf20Sopenharmony_ci		return -ENOMEM;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci	pbl->pg_count = 0;
1328c2ecf20Sopenharmony_ci	pbl->pg_size = sginfo->pgsize;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (!sginfo->umem) {
1358c2ecf20Sopenharmony_ci		for (i = 0; i < pages; i++) {
1368c2ecf20Sopenharmony_ci			pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
1378c2ecf20Sopenharmony_ci							    pbl->pg_size,
1388c2ecf20Sopenharmony_ci							    &pbl->pg_map_arr[i],
1398c2ecf20Sopenharmony_ci							    GFP_KERNEL);
1408c2ecf20Sopenharmony_ci			if (!pbl->pg_arr[i])
1418c2ecf20Sopenharmony_ci				goto fail;
1428c2ecf20Sopenharmony_ci			pbl->pg_count++;
1438c2ecf20Sopenharmony_ci		}
1448c2ecf20Sopenharmony_ci	} else {
1458c2ecf20Sopenharmony_ci		is_umem = true;
1468c2ecf20Sopenharmony_ci		bnxt_qplib_fill_user_dma_pages(pbl, sginfo);
1478c2ecf20Sopenharmony_ci	}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return 0;
1508c2ecf20Sopenharmony_cifail:
1518c2ecf20Sopenharmony_ci	__free_pbl(res, pbl, is_umem);
1528c2ecf20Sopenharmony_ci	return -ENOMEM;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* HWQ */
1568c2ecf20Sopenharmony_civoid bnxt_qplib_free_hwq(struct bnxt_qplib_res *res,
1578c2ecf20Sopenharmony_ci			 struct bnxt_qplib_hwq *hwq)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	int i;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	if (!hwq->max_elements)
1628c2ecf20Sopenharmony_ci		return;
1638c2ecf20Sopenharmony_ci	if (hwq->level >= PBL_LVL_MAX)
1648c2ecf20Sopenharmony_ci		return;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	for (i = 0; i < hwq->level + 1; i++) {
1678c2ecf20Sopenharmony_ci		if (i == hwq->level)
1688c2ecf20Sopenharmony_ci			__free_pbl(res, &hwq->pbl[i], hwq->is_user);
1698c2ecf20Sopenharmony_ci		else
1708c2ecf20Sopenharmony_ci			__free_pbl(res, &hwq->pbl[i], false);
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	hwq->level = PBL_LVL_MAX;
1748c2ecf20Sopenharmony_ci	hwq->max_elements = 0;
1758c2ecf20Sopenharmony_ci	hwq->element_size = 0;
1768c2ecf20Sopenharmony_ci	hwq->prod = 0;
1778c2ecf20Sopenharmony_ci	hwq->cons = 0;
1788c2ecf20Sopenharmony_ci	hwq->cp_bit = 0;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci/* All HWQs are power of 2 in size */
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
1848c2ecf20Sopenharmony_ci			      struct bnxt_qplib_hwq_attr *hwq_attr)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	u32 npages, aux_slots, pg_size, aux_pages = 0, aux_size = 0;
1878c2ecf20Sopenharmony_ci	struct bnxt_qplib_sg_info sginfo = {};
1888c2ecf20Sopenharmony_ci	u32 depth, stride, npbl, npde;
1898c2ecf20Sopenharmony_ci	dma_addr_t *src_phys_ptr, **dst_virt_ptr;
1908c2ecf20Sopenharmony_ci	struct bnxt_qplib_res *res;
1918c2ecf20Sopenharmony_ci	struct pci_dev *pdev;
1928c2ecf20Sopenharmony_ci	int i, rc, lvl;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	res = hwq_attr->res;
1958c2ecf20Sopenharmony_ci	pdev = res->pdev;
1968c2ecf20Sopenharmony_ci	pg_size = hwq_attr->sginfo->pgsize;
1978c2ecf20Sopenharmony_ci	hwq->level = PBL_LVL_MAX;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	depth = roundup_pow_of_two(hwq_attr->depth);
2008c2ecf20Sopenharmony_ci	stride = roundup_pow_of_two(hwq_attr->stride);
2018c2ecf20Sopenharmony_ci	if (hwq_attr->aux_depth) {
2028c2ecf20Sopenharmony_ci		aux_slots = hwq_attr->aux_depth;
2038c2ecf20Sopenharmony_ci		aux_size = roundup_pow_of_two(hwq_attr->aux_stride);
2048c2ecf20Sopenharmony_ci		aux_pages = (aux_slots * aux_size) / pg_size;
2058c2ecf20Sopenharmony_ci		if ((aux_slots * aux_size) % pg_size)
2068c2ecf20Sopenharmony_ci			aux_pages++;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (!hwq_attr->sginfo->umem) {
2108c2ecf20Sopenharmony_ci		hwq->is_user = false;
2118c2ecf20Sopenharmony_ci		npages = (depth * stride) / pg_size + aux_pages;
2128c2ecf20Sopenharmony_ci		if ((depth * stride) % pg_size)
2138c2ecf20Sopenharmony_ci			npages++;
2148c2ecf20Sopenharmony_ci		if (!npages)
2158c2ecf20Sopenharmony_ci			return -EINVAL;
2168c2ecf20Sopenharmony_ci		hwq_attr->sginfo->npages = npages;
2178c2ecf20Sopenharmony_ci	} else {
2188c2ecf20Sopenharmony_ci		npages = ib_umem_num_dma_blocks(hwq_attr->sginfo->umem,
2198c2ecf20Sopenharmony_ci						hwq_attr->sginfo->pgsize);
2208c2ecf20Sopenharmony_ci		hwq->is_user = true;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	if (npages == MAX_PBL_LVL_0_PGS) {
2248c2ecf20Sopenharmony_ci		/* This request is Level 0, map PTE */
2258c2ecf20Sopenharmony_ci		rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], hwq_attr->sginfo);
2268c2ecf20Sopenharmony_ci		if (rc)
2278c2ecf20Sopenharmony_ci			goto fail;
2288c2ecf20Sopenharmony_ci		hwq->level = PBL_LVL_0;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (npages > MAX_PBL_LVL_0_PGS) {
2328c2ecf20Sopenharmony_ci		if (npages > MAX_PBL_LVL_1_PGS) {
2338c2ecf20Sopenharmony_ci			u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ?
2348c2ecf20Sopenharmony_ci				    0 : PTU_PTE_VALID;
2358c2ecf20Sopenharmony_ci			/* 2 levels of indirection */
2368c2ecf20Sopenharmony_ci			npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT;
2378c2ecf20Sopenharmony_ci			if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT))
2388c2ecf20Sopenharmony_ci				npbl++;
2398c2ecf20Sopenharmony_ci			npde = npbl >> MAX_PDL_LVL_SHIFT;
2408c2ecf20Sopenharmony_ci			if (npbl % BIT(MAX_PDL_LVL_SHIFT))
2418c2ecf20Sopenharmony_ci				npde++;
2428c2ecf20Sopenharmony_ci			/* Alloc PDE pages */
2438c2ecf20Sopenharmony_ci			sginfo.pgsize = npde * pg_size;
2448c2ecf20Sopenharmony_ci			sginfo.npages = 1;
2458c2ecf20Sopenharmony_ci			rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci			/* Alloc PBL pages */
2488c2ecf20Sopenharmony_ci			sginfo.npages = npbl;
2498c2ecf20Sopenharmony_ci			sginfo.pgsize = PAGE_SIZE;
2508c2ecf20Sopenharmony_ci			rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo);
2518c2ecf20Sopenharmony_ci			if (rc)
2528c2ecf20Sopenharmony_ci				goto fail;
2538c2ecf20Sopenharmony_ci			/* Fill PDL with PBL page pointers */
2548c2ecf20Sopenharmony_ci			dst_virt_ptr =
2558c2ecf20Sopenharmony_ci				(dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr;
2568c2ecf20Sopenharmony_ci			src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr;
2578c2ecf20Sopenharmony_ci			if (hwq_attr->type == HWQ_TYPE_MR) {
2588c2ecf20Sopenharmony_ci			/* For MR it is expected that we supply only 1 contigous
2598c2ecf20Sopenharmony_ci			 * page i.e only 1 entry in the PDL that will contain
2608c2ecf20Sopenharmony_ci			 * all the PBLs for the user supplied memory region
2618c2ecf20Sopenharmony_ci			 */
2628c2ecf20Sopenharmony_ci				for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count;
2638c2ecf20Sopenharmony_ci				     i++)
2648c2ecf20Sopenharmony_ci					dst_virt_ptr[0][i] = src_phys_ptr[i] |
2658c2ecf20Sopenharmony_ci						flag;
2668c2ecf20Sopenharmony_ci			} else {
2678c2ecf20Sopenharmony_ci				for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count;
2688c2ecf20Sopenharmony_ci				     i++)
2698c2ecf20Sopenharmony_ci					dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
2708c2ecf20Sopenharmony_ci						src_phys_ptr[i] |
2718c2ecf20Sopenharmony_ci						PTU_PDE_VALID;
2728c2ecf20Sopenharmony_ci			}
2738c2ecf20Sopenharmony_ci			/* Alloc or init PTEs */
2748c2ecf20Sopenharmony_ci			rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_2],
2758c2ecf20Sopenharmony_ci					 hwq_attr->sginfo);
2768c2ecf20Sopenharmony_ci			if (rc)
2778c2ecf20Sopenharmony_ci				goto fail;
2788c2ecf20Sopenharmony_ci			hwq->level = PBL_LVL_2;
2798c2ecf20Sopenharmony_ci			if (hwq_attr->sginfo->nopte)
2808c2ecf20Sopenharmony_ci				goto done;
2818c2ecf20Sopenharmony_ci			/* Fill PBLs with PTE pointers */
2828c2ecf20Sopenharmony_ci			dst_virt_ptr =
2838c2ecf20Sopenharmony_ci				(dma_addr_t **)hwq->pbl[PBL_LVL_1].pg_arr;
2848c2ecf20Sopenharmony_ci			src_phys_ptr = hwq->pbl[PBL_LVL_2].pg_map_arr;
2858c2ecf20Sopenharmony_ci			for (i = 0; i < hwq->pbl[PBL_LVL_2].pg_count; i++) {
2868c2ecf20Sopenharmony_ci				dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
2878c2ecf20Sopenharmony_ci					src_phys_ptr[i] | PTU_PTE_VALID;
2888c2ecf20Sopenharmony_ci			}
2898c2ecf20Sopenharmony_ci			if (hwq_attr->type == HWQ_TYPE_QUEUE) {
2908c2ecf20Sopenharmony_ci				/* Find the last pg of the size */
2918c2ecf20Sopenharmony_ci				i = hwq->pbl[PBL_LVL_2].pg_count;
2928c2ecf20Sopenharmony_ci				dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=
2938c2ecf20Sopenharmony_ci								  PTU_PTE_LAST;
2948c2ecf20Sopenharmony_ci				if (i > 1)
2958c2ecf20Sopenharmony_ci					dst_virt_ptr[PTR_PG(i - 2)]
2968c2ecf20Sopenharmony_ci						    [PTR_IDX(i - 2)] |=
2978c2ecf20Sopenharmony_ci						    PTU_PTE_NEXT_TO_LAST;
2988c2ecf20Sopenharmony_ci			}
2998c2ecf20Sopenharmony_ci		} else { /* pages < 512 npbl = 1, npde = 0 */
3008c2ecf20Sopenharmony_ci			u32 flag = (hwq_attr->type == HWQ_TYPE_L2_CMPL) ?
3018c2ecf20Sopenharmony_ci				    0 : PTU_PTE_VALID;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci			/* 1 level of indirection */
3048c2ecf20Sopenharmony_ci			npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT;
3058c2ecf20Sopenharmony_ci			if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT))
3068c2ecf20Sopenharmony_ci				npbl++;
3078c2ecf20Sopenharmony_ci			sginfo.npages = npbl;
3088c2ecf20Sopenharmony_ci			sginfo.pgsize = PAGE_SIZE;
3098c2ecf20Sopenharmony_ci			/* Alloc PBL page */
3108c2ecf20Sopenharmony_ci			rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
3118c2ecf20Sopenharmony_ci			if (rc)
3128c2ecf20Sopenharmony_ci				goto fail;
3138c2ecf20Sopenharmony_ci			/* Alloc or init  PTEs */
3148c2ecf20Sopenharmony_ci			rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1],
3158c2ecf20Sopenharmony_ci					 hwq_attr->sginfo);
3168c2ecf20Sopenharmony_ci			if (rc)
3178c2ecf20Sopenharmony_ci				goto fail;
3188c2ecf20Sopenharmony_ci			hwq->level = PBL_LVL_1;
3198c2ecf20Sopenharmony_ci			if (hwq_attr->sginfo->nopte)
3208c2ecf20Sopenharmony_ci				goto done;
3218c2ecf20Sopenharmony_ci			/* Fill PBL with PTE pointers */
3228c2ecf20Sopenharmony_ci			dst_virt_ptr =
3238c2ecf20Sopenharmony_ci				(dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr;
3248c2ecf20Sopenharmony_ci			src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr;
3258c2ecf20Sopenharmony_ci			for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++)
3268c2ecf20Sopenharmony_ci				dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
3278c2ecf20Sopenharmony_ci					src_phys_ptr[i] | flag;
3288c2ecf20Sopenharmony_ci			if (hwq_attr->type == HWQ_TYPE_QUEUE) {
3298c2ecf20Sopenharmony_ci				/* Find the last pg of the size */
3308c2ecf20Sopenharmony_ci				i = hwq->pbl[PBL_LVL_1].pg_count;
3318c2ecf20Sopenharmony_ci				dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=
3328c2ecf20Sopenharmony_ci								  PTU_PTE_LAST;
3338c2ecf20Sopenharmony_ci				if (i > 1)
3348c2ecf20Sopenharmony_ci					dst_virt_ptr[PTR_PG(i - 2)]
3358c2ecf20Sopenharmony_ci						    [PTR_IDX(i - 2)] |=
3368c2ecf20Sopenharmony_ci						    PTU_PTE_NEXT_TO_LAST;
3378c2ecf20Sopenharmony_ci			}
3388c2ecf20Sopenharmony_ci		}
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_cidone:
3418c2ecf20Sopenharmony_ci	hwq->prod = 0;
3428c2ecf20Sopenharmony_ci	hwq->cons = 0;
3438c2ecf20Sopenharmony_ci	hwq->pdev = pdev;
3448c2ecf20Sopenharmony_ci	hwq->depth = hwq_attr->depth;
3458c2ecf20Sopenharmony_ci	hwq->max_elements = depth;
3468c2ecf20Sopenharmony_ci	hwq->element_size = stride;
3478c2ecf20Sopenharmony_ci	hwq->qe_ppg = pg_size / stride;
3488c2ecf20Sopenharmony_ci	/* For direct access to the elements */
3498c2ecf20Sopenharmony_ci	lvl = hwq->level;
3508c2ecf20Sopenharmony_ci	if (hwq_attr->sginfo->nopte && hwq->level)
3518c2ecf20Sopenharmony_ci		lvl = hwq->level - 1;
3528c2ecf20Sopenharmony_ci	hwq->pbl_ptr = hwq->pbl[lvl].pg_arr;
3538c2ecf20Sopenharmony_ci	hwq->pbl_dma_ptr = hwq->pbl[lvl].pg_map_arr;
3548c2ecf20Sopenharmony_ci	spin_lock_init(&hwq->lock);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	return 0;
3578c2ecf20Sopenharmony_cifail:
3588c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, hwq);
3598c2ecf20Sopenharmony_ci	return -ENOMEM;
3608c2ecf20Sopenharmony_ci}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/* Context Tables */
3638c2ecf20Sopenharmony_civoid bnxt_qplib_free_ctx(struct bnxt_qplib_res *res,
3648c2ecf20Sopenharmony_ci			 struct bnxt_qplib_ctx *ctx)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	int i;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->qpc_tbl);
3698c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->mrw_tbl);
3708c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->srqc_tbl);
3718c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->cq_tbl);
3728c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->tim_tbl);
3738c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
3748c2ecf20Sopenharmony_ci		bnxt_qplib_free_hwq(res, &ctx->tqm_ctx.qtbl[i]);
3758c2ecf20Sopenharmony_ci	/* restore original pde level before destroy */
3768c2ecf20Sopenharmony_ci	ctx->tqm_ctx.pde.level = ctx->tqm_ctx.pde_level;
3778c2ecf20Sopenharmony_ci	bnxt_qplib_free_hwq(res, &ctx->tqm_ctx.pde);
3788c2ecf20Sopenharmony_ci	bnxt_qplib_free_stats_ctx(res->pdev, &ctx->stats);
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_tqm_rings(struct bnxt_qplib_res *res,
3828c2ecf20Sopenharmony_ci				      struct bnxt_qplib_ctx *ctx)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	struct bnxt_qplib_hwq_attr hwq_attr = {};
3858c2ecf20Sopenharmony_ci	struct bnxt_qplib_sg_info sginfo = {};
3868c2ecf20Sopenharmony_ci	struct bnxt_qplib_tqm_ctx *tqmctx;
3878c2ecf20Sopenharmony_ci	int rc = 0;
3888c2ecf20Sopenharmony_ci	int i;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	tqmctx = &ctx->tqm_ctx;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	sginfo.pgsize = PAGE_SIZE;
3938c2ecf20Sopenharmony_ci	sginfo.pgshft = PAGE_SHIFT;
3948c2ecf20Sopenharmony_ci	hwq_attr.sginfo = &sginfo;
3958c2ecf20Sopenharmony_ci	hwq_attr.res = res;
3968c2ecf20Sopenharmony_ci	hwq_attr.type = HWQ_TYPE_CTX;
3978c2ecf20Sopenharmony_ci	hwq_attr.depth = 512;
3988c2ecf20Sopenharmony_ci	hwq_attr.stride = sizeof(u64);
3998c2ecf20Sopenharmony_ci	/* Alloc pdl buffer */
4008c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&tqmctx->pde, &hwq_attr);
4018c2ecf20Sopenharmony_ci	if (rc)
4028c2ecf20Sopenharmony_ci		goto out;
4038c2ecf20Sopenharmony_ci	/* Save original pdl level */
4048c2ecf20Sopenharmony_ci	tqmctx->pde_level = tqmctx->pde.level;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	hwq_attr.stride = 1;
4078c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_TQM_ALLOC_REQ; i++) {
4088c2ecf20Sopenharmony_ci		if (!tqmctx->qcount[i])
4098c2ecf20Sopenharmony_ci			continue;
4108c2ecf20Sopenharmony_ci		hwq_attr.depth = ctx->qpc_count * tqmctx->qcount[i];
4118c2ecf20Sopenharmony_ci		rc = bnxt_qplib_alloc_init_hwq(&tqmctx->qtbl[i], &hwq_attr);
4128c2ecf20Sopenharmony_ci		if (rc)
4138c2ecf20Sopenharmony_ci			goto out;
4148c2ecf20Sopenharmony_ci	}
4158c2ecf20Sopenharmony_ciout:
4168c2ecf20Sopenharmony_ci	return rc;
4178c2ecf20Sopenharmony_ci}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic void bnxt_qplib_map_tqm_pgtbl(struct bnxt_qplib_tqm_ctx *ctx)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	struct bnxt_qplib_hwq *tbl;
4228c2ecf20Sopenharmony_ci	dma_addr_t *dma_ptr;
4238c2ecf20Sopenharmony_ci	__le64 **pbl_ptr, *ptr;
4248c2ecf20Sopenharmony_ci	int i, j, k;
4258c2ecf20Sopenharmony_ci	int fnz_idx = -1;
4268c2ecf20Sopenharmony_ci	int pg_count;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	pbl_ptr = (__le64 **)ctx->pde.pbl_ptr;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i < MAX_TQM_ALLOC_REQ;
4318c2ecf20Sopenharmony_ci	     i++, j += MAX_TQM_ALLOC_BLK_SIZE) {
4328c2ecf20Sopenharmony_ci		tbl = &ctx->qtbl[i];
4338c2ecf20Sopenharmony_ci		if (!tbl->max_elements)
4348c2ecf20Sopenharmony_ci			continue;
4358c2ecf20Sopenharmony_ci		if (fnz_idx == -1)
4368c2ecf20Sopenharmony_ci			fnz_idx = i; /* first non-zero index */
4378c2ecf20Sopenharmony_ci		switch (tbl->level) {
4388c2ecf20Sopenharmony_ci		case PBL_LVL_2:
4398c2ecf20Sopenharmony_ci			pg_count = tbl->pbl[PBL_LVL_1].pg_count;
4408c2ecf20Sopenharmony_ci			for (k = 0; k < pg_count; k++) {
4418c2ecf20Sopenharmony_ci				ptr = &pbl_ptr[PTR_PG(j + k)][PTR_IDX(j + k)];
4428c2ecf20Sopenharmony_ci				dma_ptr = &tbl->pbl[PBL_LVL_1].pg_map_arr[k];
4438c2ecf20Sopenharmony_ci				*ptr = cpu_to_le64(*dma_ptr | PTU_PTE_VALID);
4448c2ecf20Sopenharmony_ci			}
4458c2ecf20Sopenharmony_ci			break;
4468c2ecf20Sopenharmony_ci		case PBL_LVL_1:
4478c2ecf20Sopenharmony_ci		case PBL_LVL_0:
4488c2ecf20Sopenharmony_ci		default:
4498c2ecf20Sopenharmony_ci			ptr = &pbl_ptr[PTR_PG(j)][PTR_IDX(j)];
4508c2ecf20Sopenharmony_ci			*ptr = cpu_to_le64(tbl->pbl[PBL_LVL_0].pg_map_arr[0] |
4518c2ecf20Sopenharmony_ci					   PTU_PTE_VALID);
4528c2ecf20Sopenharmony_ci			break;
4538c2ecf20Sopenharmony_ci		}
4548c2ecf20Sopenharmony_ci	}
4558c2ecf20Sopenharmony_ci	if (fnz_idx == -1)
4568c2ecf20Sopenharmony_ci		fnz_idx = 0;
4578c2ecf20Sopenharmony_ci	/* update pde level as per page table programming */
4588c2ecf20Sopenharmony_ci	ctx->pde.level = (ctx->qtbl[fnz_idx].level == PBL_LVL_2) ? PBL_LVL_2 :
4598c2ecf20Sopenharmony_ci			  ctx->qtbl[fnz_idx].level + 1;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic int bnxt_qplib_setup_tqm_rings(struct bnxt_qplib_res *res,
4638c2ecf20Sopenharmony_ci				      struct bnxt_qplib_ctx *ctx)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	int rc = 0;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_tqm_rings(res, ctx);
4688c2ecf20Sopenharmony_ci	if (rc)
4698c2ecf20Sopenharmony_ci		goto fail;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	bnxt_qplib_map_tqm_pgtbl(&ctx->tqm_ctx);
4728c2ecf20Sopenharmony_cifail:
4738c2ecf20Sopenharmony_ci	return rc;
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci/*
4778c2ecf20Sopenharmony_ci * Routine: bnxt_qplib_alloc_ctx
4788c2ecf20Sopenharmony_ci * Description:
4798c2ecf20Sopenharmony_ci *     Context tables are memories which are used by the chip fw.
4808c2ecf20Sopenharmony_ci *     The 6 tables defined are:
4818c2ecf20Sopenharmony_ci *             QPC ctx - holds QP states
4828c2ecf20Sopenharmony_ci *             MRW ctx - holds memory region and window
4838c2ecf20Sopenharmony_ci *             SRQ ctx - holds shared RQ states
4848c2ecf20Sopenharmony_ci *             CQ ctx - holds completion queue states
4858c2ecf20Sopenharmony_ci *             TQM ctx - holds Tx Queue Manager context
4868c2ecf20Sopenharmony_ci *             TIM ctx - holds timer context
4878c2ecf20Sopenharmony_ci *     Depending on the size of the tbl requested, either a 1 Page Buffer List
4888c2ecf20Sopenharmony_ci *     or a 1-to-2-stage indirection Page Directory List + 1 PBL is used
4898c2ecf20Sopenharmony_ci *     instead.
4908c2ecf20Sopenharmony_ci *     Table might be employed as follows:
4918c2ecf20Sopenharmony_ci *             For 0      < ctx size <= 1 PAGE, 0 level of ind is used
4928c2ecf20Sopenharmony_ci *             For 1 PAGE < ctx size <= 512 entries size, 1 level of ind is used
4938c2ecf20Sopenharmony_ci *             For 512    < ctx size <= MAX, 2 levels of ind is used
4948c2ecf20Sopenharmony_ci * Returns:
4958c2ecf20Sopenharmony_ci *     0 if success, else -ERRORS
4968c2ecf20Sopenharmony_ci */
4978c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res,
4988c2ecf20Sopenharmony_ci			 struct bnxt_qplib_ctx *ctx,
4998c2ecf20Sopenharmony_ci			 bool virt_fn, bool is_p5)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	struct bnxt_qplib_hwq_attr hwq_attr = {};
5028c2ecf20Sopenharmony_ci	struct bnxt_qplib_sg_info sginfo = {};
5038c2ecf20Sopenharmony_ci	int rc = 0;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (virt_fn || is_p5)
5068c2ecf20Sopenharmony_ci		goto stats_alloc;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* QPC Tables */
5098c2ecf20Sopenharmony_ci	sginfo.pgsize = PAGE_SIZE;
5108c2ecf20Sopenharmony_ci	sginfo.pgshft = PAGE_SHIFT;
5118c2ecf20Sopenharmony_ci	hwq_attr.sginfo = &sginfo;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	hwq_attr.res = res;
5148c2ecf20Sopenharmony_ci	hwq_attr.depth = ctx->qpc_count;
5158c2ecf20Sopenharmony_ci	hwq_attr.stride = BNXT_QPLIB_MAX_QP_CTX_ENTRY_SIZE;
5168c2ecf20Sopenharmony_ci	hwq_attr.type = HWQ_TYPE_CTX;
5178c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&ctx->qpc_tbl, &hwq_attr);
5188c2ecf20Sopenharmony_ci	if (rc)
5198c2ecf20Sopenharmony_ci		goto fail;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	/* MRW Tables */
5228c2ecf20Sopenharmony_ci	hwq_attr.depth = ctx->mrw_count;
5238c2ecf20Sopenharmony_ci	hwq_attr.stride = BNXT_QPLIB_MAX_MRW_CTX_ENTRY_SIZE;
5248c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&ctx->mrw_tbl, &hwq_attr);
5258c2ecf20Sopenharmony_ci	if (rc)
5268c2ecf20Sopenharmony_ci		goto fail;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/* SRQ Tables */
5298c2ecf20Sopenharmony_ci	hwq_attr.depth = ctx->srqc_count;
5308c2ecf20Sopenharmony_ci	hwq_attr.stride = BNXT_QPLIB_MAX_SRQ_CTX_ENTRY_SIZE;
5318c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&ctx->srqc_tbl, &hwq_attr);
5328c2ecf20Sopenharmony_ci	if (rc)
5338c2ecf20Sopenharmony_ci		goto fail;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	/* CQ Tables */
5368c2ecf20Sopenharmony_ci	hwq_attr.depth = ctx->cq_count;
5378c2ecf20Sopenharmony_ci	hwq_attr.stride = BNXT_QPLIB_MAX_CQ_CTX_ENTRY_SIZE;
5388c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&ctx->cq_tbl, &hwq_attr);
5398c2ecf20Sopenharmony_ci	if (rc)
5408c2ecf20Sopenharmony_ci		goto fail;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* TQM Buffer */
5438c2ecf20Sopenharmony_ci	rc = bnxt_qplib_setup_tqm_rings(res, ctx);
5448c2ecf20Sopenharmony_ci	if (rc)
5458c2ecf20Sopenharmony_ci		goto fail;
5468c2ecf20Sopenharmony_ci	/* TIM Buffer */
5478c2ecf20Sopenharmony_ci	ctx->tim_tbl.max_elements = ctx->qpc_count * 16;
5488c2ecf20Sopenharmony_ci	hwq_attr.depth = ctx->qpc_count * 16;
5498c2ecf20Sopenharmony_ci	hwq_attr.stride = 1;
5508c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_init_hwq(&ctx->tim_tbl, &hwq_attr);
5518c2ecf20Sopenharmony_ci	if (rc)
5528c2ecf20Sopenharmony_ci		goto fail;
5538c2ecf20Sopenharmony_cistats_alloc:
5548c2ecf20Sopenharmony_ci	/* Stats */
5558c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_stats_ctx(res->pdev, res->cctx, &ctx->stats);
5568c2ecf20Sopenharmony_ci	if (rc)
5578c2ecf20Sopenharmony_ci		goto fail;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	return 0;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_cifail:
5628c2ecf20Sopenharmony_ci	bnxt_qplib_free_ctx(res, ctx);
5638c2ecf20Sopenharmony_ci	return rc;
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci/* GUID */
5678c2ecf20Sopenharmony_civoid bnxt_qplib_get_guid(u8 *dev_addr, u8 *guid)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	u8 mac[ETH_ALEN];
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	/* MAC-48 to EUI-64 mapping */
5728c2ecf20Sopenharmony_ci	memcpy(mac, dev_addr, ETH_ALEN);
5738c2ecf20Sopenharmony_ci	guid[0] = mac[0] ^ 2;
5748c2ecf20Sopenharmony_ci	guid[1] = mac[1];
5758c2ecf20Sopenharmony_ci	guid[2] = mac[2];
5768c2ecf20Sopenharmony_ci	guid[3] = 0xff;
5778c2ecf20Sopenharmony_ci	guid[4] = 0xfe;
5788c2ecf20Sopenharmony_ci	guid[5] = mac[3];
5798c2ecf20Sopenharmony_ci	guid[6] = mac[4];
5808c2ecf20Sopenharmony_ci	guid[7] = mac[5];
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_sgid_tbl(struct bnxt_qplib_res *res,
5848c2ecf20Sopenharmony_ci				     struct bnxt_qplib_sgid_tbl *sgid_tbl)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	kfree(sgid_tbl->tbl);
5878c2ecf20Sopenharmony_ci	kfree(sgid_tbl->hw_id);
5888c2ecf20Sopenharmony_ci	kfree(sgid_tbl->ctx);
5898c2ecf20Sopenharmony_ci	kfree(sgid_tbl->vlan);
5908c2ecf20Sopenharmony_ci	sgid_tbl->tbl = NULL;
5918c2ecf20Sopenharmony_ci	sgid_tbl->hw_id = NULL;
5928c2ecf20Sopenharmony_ci	sgid_tbl->ctx = NULL;
5938c2ecf20Sopenharmony_ci	sgid_tbl->vlan = NULL;
5948c2ecf20Sopenharmony_ci	sgid_tbl->max = 0;
5958c2ecf20Sopenharmony_ci	sgid_tbl->active = 0;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_sgid_tbl(struct bnxt_qplib_res *res,
5998c2ecf20Sopenharmony_ci				     struct bnxt_qplib_sgid_tbl *sgid_tbl,
6008c2ecf20Sopenharmony_ci				     u16 max)
6018c2ecf20Sopenharmony_ci{
6028c2ecf20Sopenharmony_ci	sgid_tbl->tbl = kcalloc(max, sizeof(*sgid_tbl->tbl), GFP_KERNEL);
6038c2ecf20Sopenharmony_ci	if (!sgid_tbl->tbl)
6048c2ecf20Sopenharmony_ci		return -ENOMEM;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	sgid_tbl->hw_id = kcalloc(max, sizeof(u16), GFP_KERNEL);
6078c2ecf20Sopenharmony_ci	if (!sgid_tbl->hw_id)
6088c2ecf20Sopenharmony_ci		goto out_free1;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	sgid_tbl->ctx = kcalloc(max, sizeof(void *), GFP_KERNEL);
6118c2ecf20Sopenharmony_ci	if (!sgid_tbl->ctx)
6128c2ecf20Sopenharmony_ci		goto out_free2;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	sgid_tbl->vlan = kcalloc(max, sizeof(u8), GFP_KERNEL);
6158c2ecf20Sopenharmony_ci	if (!sgid_tbl->vlan)
6168c2ecf20Sopenharmony_ci		goto out_free3;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	sgid_tbl->max = max;
6198c2ecf20Sopenharmony_ci	return 0;
6208c2ecf20Sopenharmony_ciout_free3:
6218c2ecf20Sopenharmony_ci	kfree(sgid_tbl->ctx);
6228c2ecf20Sopenharmony_ci	sgid_tbl->ctx = NULL;
6238c2ecf20Sopenharmony_ciout_free2:
6248c2ecf20Sopenharmony_ci	kfree(sgid_tbl->hw_id);
6258c2ecf20Sopenharmony_ci	sgid_tbl->hw_id = NULL;
6268c2ecf20Sopenharmony_ciout_free1:
6278c2ecf20Sopenharmony_ci	kfree(sgid_tbl->tbl);
6288c2ecf20Sopenharmony_ci	sgid_tbl->tbl = NULL;
6298c2ecf20Sopenharmony_ci	return -ENOMEM;
6308c2ecf20Sopenharmony_ci};
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_cistatic void bnxt_qplib_cleanup_sgid_tbl(struct bnxt_qplib_res *res,
6338c2ecf20Sopenharmony_ci					struct bnxt_qplib_sgid_tbl *sgid_tbl)
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	int i;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	for (i = 0; i < sgid_tbl->max; i++) {
6388c2ecf20Sopenharmony_ci		if (memcmp(&sgid_tbl->tbl[i], &bnxt_qplib_gid_zero,
6398c2ecf20Sopenharmony_ci			   sizeof(bnxt_qplib_gid_zero)))
6408c2ecf20Sopenharmony_ci			bnxt_qplib_del_sgid(sgid_tbl, &sgid_tbl->tbl[i].gid,
6418c2ecf20Sopenharmony_ci					    sgid_tbl->tbl[i].vlan_id, true);
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci	memset(sgid_tbl->tbl, 0, sizeof(*sgid_tbl->tbl) * sgid_tbl->max);
6448c2ecf20Sopenharmony_ci	memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
6458c2ecf20Sopenharmony_ci	memset(sgid_tbl->vlan, 0, sizeof(u8) * sgid_tbl->max);
6468c2ecf20Sopenharmony_ci	sgid_tbl->active = 0;
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cistatic void bnxt_qplib_init_sgid_tbl(struct bnxt_qplib_sgid_tbl *sgid_tbl,
6508c2ecf20Sopenharmony_ci				     struct net_device *netdev)
6518c2ecf20Sopenharmony_ci{
6528c2ecf20Sopenharmony_ci	u32 i;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	for (i = 0; i < sgid_tbl->max; i++)
6558c2ecf20Sopenharmony_ci		sgid_tbl->tbl[i].vlan_id = 0xffff;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	memset(sgid_tbl->hw_id, -1, sizeof(u16) * sgid_tbl->max);
6588c2ecf20Sopenharmony_ci}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_pkey_tbl(struct bnxt_qplib_res *res,
6618c2ecf20Sopenharmony_ci				     struct bnxt_qplib_pkey_tbl *pkey_tbl)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	if (!pkey_tbl->tbl)
6648c2ecf20Sopenharmony_ci		dev_dbg(&res->pdev->dev, "PKEY tbl not present\n");
6658c2ecf20Sopenharmony_ci	else
6668c2ecf20Sopenharmony_ci		kfree(pkey_tbl->tbl);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	pkey_tbl->tbl = NULL;
6698c2ecf20Sopenharmony_ci	pkey_tbl->max = 0;
6708c2ecf20Sopenharmony_ci	pkey_tbl->active = 0;
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_pkey_tbl(struct bnxt_qplib_res *res,
6748c2ecf20Sopenharmony_ci				     struct bnxt_qplib_pkey_tbl *pkey_tbl,
6758c2ecf20Sopenharmony_ci				     u16 max)
6768c2ecf20Sopenharmony_ci{
6778c2ecf20Sopenharmony_ci	pkey_tbl->tbl = kcalloc(max, sizeof(u16), GFP_KERNEL);
6788c2ecf20Sopenharmony_ci	if (!pkey_tbl->tbl)
6798c2ecf20Sopenharmony_ci		return -ENOMEM;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	pkey_tbl->max = max;
6828c2ecf20Sopenharmony_ci	return 0;
6838c2ecf20Sopenharmony_ci};
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci/* PDs */
6868c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_pd(struct bnxt_qplib_pd_tbl *pdt, struct bnxt_qplib_pd *pd)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	u32 bit_num;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	bit_num = find_first_bit(pdt->tbl, pdt->max);
6918c2ecf20Sopenharmony_ci	if (bit_num == pdt->max)
6928c2ecf20Sopenharmony_ci		return -ENOMEM;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	/* Found unused PD */
6958c2ecf20Sopenharmony_ci	clear_bit(bit_num, pdt->tbl);
6968c2ecf20Sopenharmony_ci	pd->id = bit_num;
6978c2ecf20Sopenharmony_ci	return 0;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ciint bnxt_qplib_dealloc_pd(struct bnxt_qplib_res *res,
7018c2ecf20Sopenharmony_ci			  struct bnxt_qplib_pd_tbl *pdt,
7028c2ecf20Sopenharmony_ci			  struct bnxt_qplib_pd *pd)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	if (test_and_set_bit(pd->id, pdt->tbl)) {
7058c2ecf20Sopenharmony_ci		dev_warn(&res->pdev->dev, "Freeing an unused PD? pdn = %d\n",
7068c2ecf20Sopenharmony_ci			 pd->id);
7078c2ecf20Sopenharmony_ci		return -EINVAL;
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci	pd->id = 0;
7108c2ecf20Sopenharmony_ci	return 0;
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_pd_tbl(struct bnxt_qplib_pd_tbl *pdt)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	kfree(pdt->tbl);
7168c2ecf20Sopenharmony_ci	pdt->tbl = NULL;
7178c2ecf20Sopenharmony_ci	pdt->max = 0;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res,
7218c2ecf20Sopenharmony_ci				   struct bnxt_qplib_pd_tbl *pdt,
7228c2ecf20Sopenharmony_ci				   u32 max)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	u32 bytes;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	bytes = max >> 3;
7278c2ecf20Sopenharmony_ci	if (!bytes)
7288c2ecf20Sopenharmony_ci		bytes = 1;
7298c2ecf20Sopenharmony_ci	pdt->tbl = kmalloc(bytes, GFP_KERNEL);
7308c2ecf20Sopenharmony_ci	if (!pdt->tbl)
7318c2ecf20Sopenharmony_ci		return -ENOMEM;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	pdt->max = max;
7348c2ecf20Sopenharmony_ci	memset((u8 *)pdt->tbl, 0xFF, bytes);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return 0;
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci/* DPIs */
7408c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_dpi(struct bnxt_qplib_dpi_tbl *dpit,
7418c2ecf20Sopenharmony_ci			 struct bnxt_qplib_dpi     *dpi,
7428c2ecf20Sopenharmony_ci			 void                      *app)
7438c2ecf20Sopenharmony_ci{
7448c2ecf20Sopenharmony_ci	u32 bit_num;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	bit_num = find_first_bit(dpit->tbl, dpit->max);
7478c2ecf20Sopenharmony_ci	if (bit_num == dpit->max)
7488c2ecf20Sopenharmony_ci		return -ENOMEM;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	/* Found unused DPI */
7518c2ecf20Sopenharmony_ci	clear_bit(bit_num, dpit->tbl);
7528c2ecf20Sopenharmony_ci	dpit->app_tbl[bit_num] = app;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	dpi->dpi = bit_num;
7558c2ecf20Sopenharmony_ci	dpi->dbr = dpit->dbr_bar_reg_iomem + (bit_num * PAGE_SIZE);
7568c2ecf20Sopenharmony_ci	dpi->umdbr = dpit->unmapped_dbr + (bit_num * PAGE_SIZE);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	return 0;
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ciint bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
7628c2ecf20Sopenharmony_ci			   struct bnxt_qplib_dpi_tbl *dpit,
7638c2ecf20Sopenharmony_ci			   struct bnxt_qplib_dpi     *dpi)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	if (dpi->dpi >= dpit->max) {
7668c2ecf20Sopenharmony_ci		dev_warn(&res->pdev->dev, "Invalid DPI? dpi = %d\n", dpi->dpi);
7678c2ecf20Sopenharmony_ci		return -EINVAL;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci	if (test_and_set_bit(dpi->dpi, dpit->tbl)) {
7708c2ecf20Sopenharmony_ci		dev_warn(&res->pdev->dev, "Freeing an unused DPI? dpi = %d\n",
7718c2ecf20Sopenharmony_ci			 dpi->dpi);
7728c2ecf20Sopenharmony_ci		return -EINVAL;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci	if (dpit->app_tbl)
7758c2ecf20Sopenharmony_ci		dpit->app_tbl[dpi->dpi] = NULL;
7768c2ecf20Sopenharmony_ci	memset(dpi, 0, sizeof(*dpi));
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	return 0;
7798c2ecf20Sopenharmony_ci}
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_dpi_tbl(struct bnxt_qplib_res     *res,
7828c2ecf20Sopenharmony_ci				    struct bnxt_qplib_dpi_tbl *dpit)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	kfree(dpit->tbl);
7858c2ecf20Sopenharmony_ci	kfree(dpit->app_tbl);
7868c2ecf20Sopenharmony_ci	if (dpit->dbr_bar_reg_iomem)
7878c2ecf20Sopenharmony_ci		pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
7888c2ecf20Sopenharmony_ci	memset(dpit, 0, sizeof(*dpit));
7898c2ecf20Sopenharmony_ci}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res     *res,
7928c2ecf20Sopenharmony_ci				    struct bnxt_qplib_dpi_tbl *dpit,
7938c2ecf20Sopenharmony_ci				    u32                       dbr_offset)
7948c2ecf20Sopenharmony_ci{
7958c2ecf20Sopenharmony_ci	u32 dbr_bar_reg = RCFW_DBR_PCI_BAR_REGION;
7968c2ecf20Sopenharmony_ci	resource_size_t bar_reg_base;
7978c2ecf20Sopenharmony_ci	u32 dbr_len, bytes;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	if (dpit->dbr_bar_reg_iomem) {
8008c2ecf20Sopenharmony_ci		dev_err(&res->pdev->dev, "DBR BAR region %d already mapped\n",
8018c2ecf20Sopenharmony_ci			dbr_bar_reg);
8028c2ecf20Sopenharmony_ci		return -EALREADY;
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	bar_reg_base = pci_resource_start(res->pdev, dbr_bar_reg);
8068c2ecf20Sopenharmony_ci	if (!bar_reg_base) {
8078c2ecf20Sopenharmony_ci		dev_err(&res->pdev->dev, "BAR region %d resc start failed\n",
8088c2ecf20Sopenharmony_ci			dbr_bar_reg);
8098c2ecf20Sopenharmony_ci		return -ENOMEM;
8108c2ecf20Sopenharmony_ci	}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	dbr_len = pci_resource_len(res->pdev, dbr_bar_reg) - dbr_offset;
8138c2ecf20Sopenharmony_ci	if (!dbr_len || ((dbr_len & (PAGE_SIZE - 1)) != 0)) {
8148c2ecf20Sopenharmony_ci		dev_err(&res->pdev->dev, "Invalid DBR length %d\n", dbr_len);
8158c2ecf20Sopenharmony_ci		return -ENOMEM;
8168c2ecf20Sopenharmony_ci	}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	dpit->dbr_bar_reg_iomem = ioremap(bar_reg_base + dbr_offset,
8198c2ecf20Sopenharmony_ci						  dbr_len);
8208c2ecf20Sopenharmony_ci	if (!dpit->dbr_bar_reg_iomem) {
8218c2ecf20Sopenharmony_ci		dev_err(&res->pdev->dev,
8228c2ecf20Sopenharmony_ci			"FP: DBR BAR region %d mapping failed\n", dbr_bar_reg);
8238c2ecf20Sopenharmony_ci		return -ENOMEM;
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	dpit->unmapped_dbr = bar_reg_base + dbr_offset;
8278c2ecf20Sopenharmony_ci	dpit->max = dbr_len / PAGE_SIZE;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	dpit->app_tbl = kcalloc(dpit->max, sizeof(void *), GFP_KERNEL);
8308c2ecf20Sopenharmony_ci	if (!dpit->app_tbl)
8318c2ecf20Sopenharmony_ci		goto unmap_io;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	bytes = dpit->max >> 3;
8348c2ecf20Sopenharmony_ci	if (!bytes)
8358c2ecf20Sopenharmony_ci		bytes = 1;
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	dpit->tbl = kmalloc(bytes, GFP_KERNEL);
8388c2ecf20Sopenharmony_ci	if (!dpit->tbl) {
8398c2ecf20Sopenharmony_ci		kfree(dpit->app_tbl);
8408c2ecf20Sopenharmony_ci		dpit->app_tbl = NULL;
8418c2ecf20Sopenharmony_ci		goto unmap_io;
8428c2ecf20Sopenharmony_ci	}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	memset((u8 *)dpit->tbl, 0xFF, bytes);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	return 0;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ciunmap_io:
8498c2ecf20Sopenharmony_ci	pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
8508c2ecf20Sopenharmony_ci	dpit->dbr_bar_reg_iomem = NULL;
8518c2ecf20Sopenharmony_ci	return -ENOMEM;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci/* PKEYs */
8558c2ecf20Sopenharmony_cistatic void bnxt_qplib_cleanup_pkey_tbl(struct bnxt_qplib_pkey_tbl *pkey_tbl)
8568c2ecf20Sopenharmony_ci{
8578c2ecf20Sopenharmony_ci	memset(pkey_tbl->tbl, 0, sizeof(u16) * pkey_tbl->max);
8588c2ecf20Sopenharmony_ci	pkey_tbl->active = 0;
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic void bnxt_qplib_init_pkey_tbl(struct bnxt_qplib_res *res,
8628c2ecf20Sopenharmony_ci				     struct bnxt_qplib_pkey_tbl *pkey_tbl)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	u16 pkey = 0xFFFF;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	memset(pkey_tbl->tbl, 0, sizeof(u16) * pkey_tbl->max);
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	/* pkey default = 0xFFFF */
8698c2ecf20Sopenharmony_ci	bnxt_qplib_add_pkey(res, pkey_tbl, &pkey, false);
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci/* Stats */
8738c2ecf20Sopenharmony_cistatic void bnxt_qplib_free_stats_ctx(struct pci_dev *pdev,
8748c2ecf20Sopenharmony_ci				      struct bnxt_qplib_stats *stats)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	if (stats->dma) {
8778c2ecf20Sopenharmony_ci		dma_free_coherent(&pdev->dev, stats->size,
8788c2ecf20Sopenharmony_ci				  stats->dma, stats->dma_map);
8798c2ecf20Sopenharmony_ci	}
8808c2ecf20Sopenharmony_ci	memset(stats, 0, sizeof(*stats));
8818c2ecf20Sopenharmony_ci	stats->fw_id = -1;
8828c2ecf20Sopenharmony_ci}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_cistatic int bnxt_qplib_alloc_stats_ctx(struct pci_dev *pdev,
8858c2ecf20Sopenharmony_ci				      struct bnxt_qplib_chip_ctx *cctx,
8868c2ecf20Sopenharmony_ci				      struct bnxt_qplib_stats *stats)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	memset(stats, 0, sizeof(*stats));
8898c2ecf20Sopenharmony_ci	stats->fw_id = -1;
8908c2ecf20Sopenharmony_ci	stats->size = cctx->hw_stats_size;
8918c2ecf20Sopenharmony_ci	stats->dma = dma_alloc_coherent(&pdev->dev, stats->size,
8928c2ecf20Sopenharmony_ci					&stats->dma_map, GFP_KERNEL);
8938c2ecf20Sopenharmony_ci	if (!stats->dma) {
8948c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Stats DMA allocation failed\n");
8958c2ecf20Sopenharmony_ci		return -ENOMEM;
8968c2ecf20Sopenharmony_ci	}
8978c2ecf20Sopenharmony_ci	return 0;
8988c2ecf20Sopenharmony_ci}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_civoid bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	bnxt_qplib_cleanup_pkey_tbl(&res->pkey_tbl);
9038c2ecf20Sopenharmony_ci	bnxt_qplib_cleanup_sgid_tbl(res, &res->sgid_tbl);
9048c2ecf20Sopenharmony_ci}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ciint bnxt_qplib_init_res(struct bnxt_qplib_res *res)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	bnxt_qplib_init_sgid_tbl(&res->sgid_tbl, res->netdev);
9098c2ecf20Sopenharmony_ci	bnxt_qplib_init_pkey_tbl(res, &res->pkey_tbl);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	return 0;
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_civoid bnxt_qplib_free_res(struct bnxt_qplib_res *res)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	bnxt_qplib_free_pkey_tbl(res, &res->pkey_tbl);
9178c2ecf20Sopenharmony_ci	bnxt_qplib_free_sgid_tbl(res, &res->sgid_tbl);
9188c2ecf20Sopenharmony_ci	bnxt_qplib_free_pd_tbl(&res->pd_tbl);
9198c2ecf20Sopenharmony_ci	bnxt_qplib_free_dpi_tbl(res, &res->dpi_tbl);
9208c2ecf20Sopenharmony_ci}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ciint bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev,
9238c2ecf20Sopenharmony_ci			 struct net_device *netdev,
9248c2ecf20Sopenharmony_ci			 struct bnxt_qplib_dev_attr *dev_attr)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	int rc = 0;
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	res->pdev = pdev;
9298c2ecf20Sopenharmony_ci	res->netdev = netdev;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_sgid_tbl(res, &res->sgid_tbl, dev_attr->max_sgid);
9328c2ecf20Sopenharmony_ci	if (rc)
9338c2ecf20Sopenharmony_ci		goto fail;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_pkey_tbl(res, &res->pkey_tbl, dev_attr->max_pkey);
9368c2ecf20Sopenharmony_ci	if (rc)
9378c2ecf20Sopenharmony_ci		goto fail;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_pd_tbl(res, &res->pd_tbl, dev_attr->max_pd);
9408c2ecf20Sopenharmony_ci	if (rc)
9418c2ecf20Sopenharmony_ci		goto fail;
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	rc = bnxt_qplib_alloc_dpi_tbl(res, &res->dpi_tbl, dev_attr->l2_db_size);
9448c2ecf20Sopenharmony_ci	if (rc)
9458c2ecf20Sopenharmony_ci		goto fail;
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	return 0;
9488c2ecf20Sopenharmony_cifail:
9498c2ecf20Sopenharmony_ci	bnxt_qplib_free_res(res);
9508c2ecf20Sopenharmony_ci	return rc;
9518c2ecf20Sopenharmony_ci}
952